Как извлечь длительность времени из вывода ffmpeg?
Чтобы получить много информации о медиафайле, можно сделать
ffmpeg -i <filename>
где будет выводиться много строк, в частности одна
Duration: 00:08:07.98, start: 0.000000, bitrate: 2080 kb/s
Я хотел бы вывести только 00:08:07.98
вот я и пытаюсь
ffmpeg -i file.mp4 | grep Duration| sed 's/Duration: \(.*\), start/\1/g'
Но он печатает все, а не только длину.
Четное ffmpeg -i file.mp4 | grep Duration
выводит все.
Как я могу получить только продолжительность?
19 ответов
ffmpeg записывает эту информацию stderr
не stdout
, Попробуй это:
ffmpeg -i file.mp4 2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'
Обратите внимание на перенаправление stderr
в stdout
: 2>&1
РЕДАКТИРОВАТЬ:
Ваш sed
заявление тоже не работает. Попробуй это:
ffmpeg -i file.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d ,
Ты можешь использовать ffprobe
:
ffprobe -i <file> -show_entries format=duration -v quiet -of csv="p=0"
Он выведет продолжительность в секундах, например:
154.12
Добавление -sexagesimal
опция выведет длительность в виде часов: минут: секунд. микросекунд:
00:02:34.12
Из моего опыта многие инструменты предлагают желаемые данные в виде таблицы / упорядоченной структуры, а также предлагают параметры для сбора определенных частей этих данных. Это относится, например, к smartctl, nvidia-smi и ffmpeg/ffprobe. Проще говоря - часто нет необходимости передавать данные или открывать подоболочки для такой задачи.
Как следствие, я бы использовал правильный инструмент для работы - в этом случае ffprobe вернет необработанное значение длительности в секундах, после чего можно будет создать желаемый формат времени самостоятельно:
$ ffmpeg --version
ffmpeg version 2.2.3 ...
Команда может отличаться в зависимости от используемой версии.
#!/usr/bin/env bash
input_file="/path/to/media/file"
# Get raw duration value
ffprobe -v quiet -print_format compact=print_section=0:nokey=1:escape=csv -show_entries format=duration "$input_file"
Объяснение:
"-v quiet": не выводить ничего, кроме желаемого значения необработанных данных
"-print_format": использовать определенный формат для распечатки данных
"compact=": использовать компактный формат вывода
"print_section=0": не печатать название раздела
":nokey=1": не печатать ключ пары ключ: значение
":escape=csv": экранировать значение
"-show_entries format=duration": получить записи поля с именем длительности в разделе с именем format
Ссылка: страницы руководства ffprobe
Я рекомендую использовать формат JSON, это проще для анализа
ffprobe -i your-input-file.mp4 -v quiet -print_format json -show_format -show_streams -hide_banner
{
"streams": [
{
"index": 0,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "HE-AACv2",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"sample_fmt": "fltp",
"sample_rate": "44100",
"channels": 2,
"channel_layout": "stereo",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/28224000",
"duration_ts": 305349201,
"duration": "10.818778",
"bit_rate": "27734",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
}
}
],
"format": {
"filename": "your-input-file.mp4",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "aac",
"format_long_name": "raw ADTS AAC (Advanced Audio Coding)",
"duration": "10.818778",
"size": "37506",
"bit_rate": "27734",
"probe_score": 51
}
}
Вы можете найти информацию о продолжительности в разделе формата, работает как для видео, так и для аудио
В случае одного параметра запроса проще использовать mediainfo и его выходное форматирование следующим образом (для длительности; ответ в миллисекундах)
amber ~ > mediainfo --Output="General;%Duration%" ~/work/files/testfiles/+h263_aac.avi
24840
Если вы хотите получить длину (и, возможно, все другие метаданные) из вашего медиа-файла с помощью ffmpeg , используя скрипт на python, вы можете попробовать это:
import subprocess
import json
input_file = "< path to your input file here >"
metadata = subprocess.check_output(f"ffprobe -i {input_file} -v quiet -print_format json -show_format -hide_banner".split(" "))
metadata = json.loads(metadata)
print(f"Length of file is: {float(length["format"]["duration"])}")
print(metadata)
Выход:
Length of file is: 7579.977143
{
"streams": [
{
"index": 0,
"codec_name": "mp3",
"codec_long_name": "MP3 (MPEG audio layer 3)",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"sample_fmt": "fltp",
"sample_rate": "44100",
"channels": 2,
"channel_layout": "stereo",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/14112000",
"start_pts": 353600,
"start_time": "0.025057",
"duration_ts": 106968637440,
"duration": "7579.977143",
"bit_rate": "320000",
...
...
Это мое действительно простое решение с использованием ffmpeg и awk . Выход
ffmpeg -i file.mp3
содержать строку
Duration: 00:00:04.80, bitrate: 352 kb/s
. Просто используя awk:
ffmpeg -i file.mp3 |& awk '/Duration:/ {print $2}'
Могу напечатать ожидаемый результат:
00:00:04.80
Это медленно, так как декодирует ввод, но будет показывать правильную продолжительность, даже если в метаданных есть неправильная/отсутствующая информация:
ffmpeg -i <filename> -f null - 2>&1 | awk -F= 'BEGIN{RS=" "}/^time=/{t=$2}END{print t}'
Для тех, кто хочет выполнить те же вычисления без дополнительного программного обеспечения в Windows, вот скрипт для командной строки:
set input=video.ts
ffmpeg -i "%input%" 2> output.tmp
rem search " Duration: HH:MM:SS.mm, start: NNNN.NNNN, bitrate: xxxx kb/s"
for /F "tokens=1,2,3,4,5,6 delims=:., " %%i in (output.tmp) do (
if "%%i"=="Duration" call :calcLength %%j %%k %%l %%m
)
goto :EOF
:calcLength
set /A s=%3
set /A s=s+%2*60
set /A s=s+%1*60*60
set /A VIDEO_LENGTH_S = s
set /A VIDEO_LENGTH_MS = s*1000 + %4
echo Video duration %1:%2:%3.%4 = %VIDEO_LENGTH_MS%ms = %VIDEO_LENGTH_S%s
Тот же ответ опубликован здесь: Как обрезать последние N секунд из видео TS
Никакого поиска или чего-то подобного не требуется. Просто введите эту команду, и вы получите точное время с точностью до микросекунды!
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 file.mp4
Из документов ffmpeg https://trac.ffmpeg.org/wiki/FFprobeTips
ffmpeg -i abc.mp4 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//
дает вывод
HH:MM:SS.milisecs
используйте ffprobe, который используется для извлечения метаданных из медиафайлов
установить ffprobe с pip
pip установить ffprobe-python
`из импорта подпроцесса check_output
имя_файла = "video1.mp4"
command = str(check_output('ffprobe -i "'+file_name+'" 2>&1 |grep "Duration"',shell=True))
#output: b' Duration: 00:17:56.62, start: 0.000000, bitrate: 397 кб/с\n'
# разделить продолжительность в формате чч:мм:сс co = a.split(",")[0].split("Длительность:")[1].strip()
ч, м, с = a.split(':') продолжительность = int(h) * 3600 + int(m) * 60 + float(s)
печать (длительность)`
Я попробовал лучшие ответы, но ни один из них не сработал, потому что в моем аудио не было метаданных. Наконец-то я нашел ответ, который работал на этом сайте .
ffmpeg -i "${file}" -f null /dev/null 2>&1 | grep -oE "[0-9]{1}:[0-9]{2}:[0-9]{2}" | tail -n 1
# Returns duration (in seconds) of a video $1 (uses ffmpeg).
get_video_duration() {
OUTPUT=$(ffmpeg -i "$1" -vframes 1 -f rawvideo -y /dev/null 2>&1) ||
{ debug -e "get_video_duration: error running ffmpeg:\n$OUTPUT"; return 1; }
DURATION=$(echo "$OUTPUT" | grep -m1 "^[[:space:]]*Duration:" |
cut -d":" -f2- | cut -d"," -f1 | sed "s/[:\.]/ /g") ||
{ debug -e "get_video_duration: error parsing duration:\n$OUTPUT"; return 1; }
read HOURS MINUTES SECONDS DECISECONDS <<< "$DURATION"
echo $((10#$HOURS * 3600 + 10#$MINUTES * 60 + 10#$SECONDS))
}
Использование:
DURATION=$(get_video_duration "$VIDEO")
Argh. Забудь про это. Похоже, я должен вытащить паутину из моих программ на C и C++ и использовать ее вместо этого. Я не знаю всех трюков с оболочкой, чтобы заставить его работать. Это как далеко я получил.
ffmpeg -i myfile 2>&1 | grep "" > textdump.txt
и тогда я, вероятно, извлеку бы продолжительность с помощью приложения на C++ вместо извлечения токенов.
Я не публикую решение, потому что я не очень хороший человек
Обновление - у меня есть подход к получению этой отметки времени
Шаг 1 - Получить информацию о мультимедиа в текстовом файле `ffprobe -i myfile 2>&1 | grep "" > textdump.txt`
ИЛИ ЖЕ `ffprobe -i myfile 2>&1 | awk '{ print }' > textdump.txt`
Шаг 2 - Найдите необходимую информацию и извлеките ее cat textdump.txt | grep "Duration" | awk '{ print $2 }' | ./a.out
Обратите внимание на a.out. Это мой код на C, чтобы отрубить результирующую запятую, потому что выходные данные примерно такие: 00:00:01.33,
Вот код C, который принимает стандартный ввод и выводит нужную информацию. Я должен был взять больше и меньше, чем вывески для просмотра.
#include stdio.h
#include string.h
void main()
{
//by Admiral Smith Nov 3. 2016
char time[80];
int len;
char *correct;
scanf("%s", &time);
correct = (char *)malloc(strlen(time));
if (!correct)
{
printf("\nmemory error");
return;
}
memcpy(correct,&time,strlen(time)-1);
correct[strlen(time)]='/0';
printf("%s", correct);
free(correct);
}
Теперь выходные форматы правильно, как 00: 00: 01.33
Я бы просто сделал это в C++ с текстовым файлом и извлек бы токены. Зачем? Я не эксперт терминала Linux, как другие.
Для настройки я бы сделал это в Linux..
ffmpeg -i 2>&1 | grep "" > mytext.txt
а затем запустите приложение C++, чтобы получить необходимые данные. Может быть, извлечь все важные значения и переформатировать его для дальнейшей обработки с помощью токенов. Мне просто нужно будет поработать над своим собственным решением, и люди будут просто смеяться надо мной, потому что я новичок в Linux и мне не очень нравится писать сценарии.
Лучшее решение: сократить экспорт, получить что-то вроде 00:05:03.22
ffmpeg -i input 2>&1 | grep Duration | cut -c 13-23
Вы можете попробовать это:
/*
* Determine video duration with ffmpeg
* ffmpeg should be installed on your server.
*/
function mbmGetFLVDuration($file){
//$time = 00:00:00.000 format
$time = exec("ffmpeg -i ".$file." 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//");
$duration = explode(":",$time);
$duration_in_seconds = $duration[0]*3600 + $duration[1]*60+ round($duration[2]);
return $duration_in_seconds;
}
$duration = mbmGetFLVDuration('/home/username/webdir/video/file.mov');
echo $duration;
ffmpeg был заменен на avconv: просто замените avconb на ответ Луи Марасио.
avconv -i file.mp4 2>&1 | grep Duration | sed 's/Duration: \(.*\), start.*/\1/g'
Примечание: дополнительные.* После начала, чтобы получить время в одиночестве!