Як витягти час тривалості з виводу ffmpeg?


78

Щоб отримати багато інформації про медіафайл, це можна зробити

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виводить все.

Як отримати лише тривалість?


1
IMHO MediaInfo, безсумнівно, запропонує вам набагато простіший аналіз результатів.
SirDarius,

Відповіді:


61

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 ,

3
Греп непотрібний, sed -n 's/Duration: \(.*\), start/\1/gp'достатньо.
potong

11
Власне, sedнепотрібно:ffmpeg -i file.mp4 2>&1 | grep -o -P "(?<=Duration: ).*?(?=,)"
ДМИТРИЙ МАЛИКОВ

1
Який контекст для цього, якщо я хочу зберегти тривалість як змінну, яка буде використана в тому самому сценарії PHP?
запаморочення

Як зробити те саме в Python?
Прахар Мохан Шрівастава

18
Використання ffprobe, як зазначено в інших відповідях, здається чистішим та безпроблемним підходом :)
Піркка Еско,

166

Ви можете використовувати ffprobe:

ffprobe -i <file> -show_entries format=duration -v quiet -of csv="p=0"

Він видасть тривалість у секундах, наприклад:

154.12

Додавши -sexagesimalопцію, тривалість буде виведена у годинах: хвилинах: секундах. Мікросекундах :

00:02:34.12

1
Для мого ffmpeg-0.6.5-1.el6.rf.x86_64 формат: ffprobe <file> -show_format 2> & 1 | sed -n 's / duration = // p'
Sunry

2
Це шлях. ffmpeg -i завжди хотів перекодувати новий файл після друку даних. Набагато чистіше рішення тут.
Pirkka Esko

Має бути прийнятою відповіддю, хоча вихідний формат (секунди) не зовсім відповідає тому, про що просили.
bovender

3
Відповідь @bovender оновлено з можливістю вивести потрібний формат.
llogan

1
@LordNeckbeard Тепер це дійсно повинна бути прийнята відповідь!
bovender

13

З мого досвіду, багато інструментів пропонують бажані дані в якійсь таблиці / впорядкованій структурі, а також пропонують параметри для збору конкретних частин цих даних. Це стосується, наприклад, 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 тихо": не виводити нічого іншого, крім бажаного значення вихідних даних

"-print_format": Використовуйте певний формат для роздрукування даних

"compact =": Використовуйте компактний формат виводу

"print_section = 0": Не друкуйте назву розділу

": nokey = 1": не друкувати ключ пари ключ: значення

": escape = csv": екранувати значення

"-show_entries format = duration": Отримати записи поля з іменем duration у розділі з іменем format

Довідково: ffprobe man pages


6

У випадку одного параметра запиту простіше використовувати mediainfo та його вихідне форматування таким чином (на тривалість; відповідь у мілісекундах)

mediainfo --Output="General;%Duration%" ~/work/files/testfiles/+h263_aac.avi 

виходи

24840

2
Це має бути 'mediainfo --Inform = "General;% Duration%" ~ / work / files / testfiles / + h263_aac.avi'
Pogrindis,

Обидві форми однаково працюють у середовищі mediainfo v18.05 (і, схоже, у попередніх версіях).
gemelen

4

Я рекомендую використовувати формат 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
    }
}

інформацію про тривалість можна знайти у розділі формату, працює як для відео, так і для аудіо


Дякую! Це саме те, що мені потрібно було!
Matt W

4

Якщо ви хочете отримати довжину (і, можливо, всі інші метадані) з вашого мультимедійного файлу за допомогою 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(metadata['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",
      ...
      ...

Цей код не працює: Traceback (most recent call last): File "ffprobe.py", line 9, in <module> print("Length of file is: {}".format(float(length["format"]["duration"]))) NameError: name 'length' is not defined Це повинно зробити роботу: import subprocess import json input_file = "out.mp4" metadata = subprocess.check_output(f"ffprobe -i {input_file} -v quiet -print_format json -show_format -hide_banner".split(" ")) metadata = json.loads(metadata) print("Length of file is: {}".format(float(metadata["format"]["duration"]))) print(metadata)
Рабіндранат Андухар

@RabindranathAndujar я перевірив. Ти правий. Код працює, але в рядку для роздруківки була помилка. Я виправив код, і тепер він працює нормально. Дякуємо, що вказали на це.
petezurich

Цей сценарій не вдасться використовувати для імен файлів зі спеціальними символами як в Linux, так і у Windows
agarg

1

Для тих, хто хоче виконати ті самі обчислення без додаткового програмного забезпечення в 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 -i "input.mp4" -show_entries format = duration -v quiet -of csv = "p = 0" -sexagesimal
Ray Woodcock

1
ffmpeg -i abc.mp4 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//

дає результат

HH: MM: SS. Мілісек


grep, cutІ sedє непотрібними. Дивіться відповідь Івана .
llogan

чому непотрібне, я не розумію, це дає результат
sparsh turkane

Тому що ви можете просто використовувати ffprobeпоодинці. Крім того, висновок ffmpegпризначений лише для інформаційних цілей, а не для синтаксичного аналізу: не гарантується завжди однакова структура, формат та інформація з різними ffmpegверсіями та різними форматами введення.
llogan

0

Найкраще рішення: скоротити експорт, вийде щось на зразок 00: 05: 03.22

ffmpeg -i input 2>&1 | grep Duration | cut -c 13-23

-1

Я б просто зробив це в C ++ за допомогою текстового файлу і витягнув маркери. Чому? Я не фахівець з Linux-терміналів, як інші.
Для його налаштування я б зробив це в Linux ..

ffmpeg -i 2>&1 | grep "" > mytext.txt

а потім запустіть деяку програму C ++, щоб отримати необхідні дані. Можливо, витягніть усі важливі значення та переформатуйте їх для подальшої обробки, використовуючи маркери. Мені просто доведеться попрацювати над власним рішенням, і люди будуть просто глузувати з мене, тому що я новачок у Linux, і я не дуже люблю виконувати сценарії.


-1

Арг. Забудь про це. Схоже, я повинен вилучити павутиння з мого програмування на 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, який приймає stdin і видає потрібну потрібну інформацію. Мені довелося взяти для перегляду великі та менші знаки.

#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


-5

Ви можете спробувати це:

/*
* 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;

-5

ffmpeg замінено avconv: просто підставте avconb до відповіді Луїса Марасіо.

avconv -i file.mp4 2>&1 | grep Duration | sed 's/Duration: \(.*\), start.*/\1/g'

Примітка: додатковий. * Після початку, щоб отримати час наодинці !!


1
Підробку " ffmpeg" з Libav (вилка проекту FFmpeg) замінено на avconvLibav. ffmpegвід FFmpeg знаходиться в дуже активному розвитку.
llogan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.