如何从ffmpeg输出中提取持续时间?


77

要获取有关媒体文件的大量信息,可以执行以下操作

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 2012年

Answers:


59

ffmpeg正在将信息写入,而stderr不是stdout。试试这个:

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

请注意重定向stderrstdout2>&1

编辑:

您的sed陈述也不起作用。试试这个:

ffmpeg -i file.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d ,

3
Grep是不必要的,sed -n 's/Duration: \(.*\), start/\1/gp'足够了。
potong 2011年

11
其实,sed没有必要:ffmpeg -i file.mp4 2>&1 | grep -o -P "(?<=Duration: ).*?(?=,)"
ДМИТРИЙМАЛИКОВ

1
如果要将持续时间存储为要在同一PHP脚本中使用的变量,此上下文的上下文是什么?
vertigoelectric 2013年

如何在Python中做同样的事情?
Prakhar Mohan Srivastava 2014年

18
按照其他答案的指示使用ffprobe似乎是一种更清洁,更轻松的方法:)
Pirkka Esko 2014年

161

您可以使用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 <文件> -show_format 2>&1 | sed -n's / duration = // p'–
Sunry

2
这是要走的路。ffmpeg -i一直希望在打印数据后对新文件进行转码。解决方案就在这里。
皮尔卡·埃斯科

尽管输出格式(秒)与要求的不完全相同,但应该是可接受的答案。
bovender

3
@bovender答案已更新,其中包含用于输出所需格式的选项。
llogan

1
@LordNeckbeard现在,它确实应该是公认的答案!
bovender '16

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”:不打印key:value对的键

“:escape = csv”:转义值

“ -show_entries format = duration”:在名为format的节中获取名为duration的字段的条目

参考:ffprobe手册页


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
    }
}

您可以在格式部分找到时长信息,适用于视频和音频


谢谢!这正是我所需要的!
马特W

4

如果您想使用python脚本通过ffmpeg从媒体文件中检索长度(以及所有其他元数据),则可以尝试以下操作:

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)
Rabindranath Andujar

我重新检查了@RabindranathAndujar。你是对的。该代码有效,但是打印输出的行中有错误。我更正了代码,现在它可以正常运行。感谢您指出。
petezurich

对于Linux和Windows上带有特殊字符的文件名,此脚本将失败
agarg

4

在一个请求参数的情况下,使用mediainfo及其输出格式像这样更简单(持续时间;以毫秒为单位)

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

输出

24840

2
这应该是'的MediaInfo --Inform = “总则%持续%” 〜/工作/文件/ testfiles / + h263_aac.avi'
Pogrindis

两种形式在mediainfo v18.05中均相同(似乎与以前的版本相同)。
gemelen

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

同样的答案在这里发布:如何从TS视频中裁剪最后N秒


或者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.milisecs


grepcutsed是不必要的。请参阅Ivan的答案
llogan

为什么不必要的我不明白它给出了结果
sparsh turkane

因为您可以ffprobe单独使用。同样,的输出ffmpeg仅用于提供信息,而并非用于解析:不能保证始终具有相同的结构,格式和信息,并且具有各种ffmpeg版本和各种输入格式。
llogan '16

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替代Louis Marascio的答案即可。

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

注意:开始后的..独处的时间!!


1
ffmpeg来自Libav(FFmpeg项目的一个分支)的伪造品“ ”已由Libav代替avconvffmpeg来自FFmpeg的产品正在非常积极的开发中。
llogan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.