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

Linux 如何从ffmpeg输出中提取持续时间?,linux,bash,ffmpeg,Linux,Bash,Ffmpeg,要获得有关媒体文件的大量信息,可以执行以下操作 ffmpeg -i <filename> 我只想输出00:08:07.98,所以我尝试了 ffmpeg -i file.mp4 | grep Duration| sed 's/Duration: \(.*\), start/\1/g' 但它可以打印所有内容,而不仅仅是长度 甚至ffmpeg-i file.mp4 | grep Duration都会输出所有内容 如何获得持续时间长度?ffmpeg正在将该信息写入stderr,而不是st

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

ffmpeg -i <filename>
我只想输出
00:08:07.98
,所以我尝试了

ffmpeg -i file.mp4 | grep Duration| sed 's/Duration: \(.*\), start/\1/g'
但它可以打印所有内容,而不仅仅是长度

甚至
ffmpeg-i file.mp4 | grep Duration
都会输出所有内容


如何获得持续时间长度?

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

ffmpeg -i file.mp4 2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'
ffmpeg -i file.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d ,
注意将
stderr
重定向到
stdout
2>&1

编辑:

您的
sed
语句也不起作用。试试这个:

ffmpeg -i file.mp4 2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'
ffmpeg -i file.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d ,
你可以试试这个:

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

对于一个请求参数,使用mediainfo及其输出格式(持续时间;以毫秒为单位)更简单

输出

24840

对于希望在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

这里发布了相同的答案:

您可以使用
ffprobe

ffprobe -i <file> -show_entries format=duration -v quiet -of csv="p=0"
添加
-sexagesimal
选项将持续时间输出为小时:分钟:秒。微秒:


根据我的经验,许多工具以某种表格/有序结构提供所需的数据,还提供参数来收集数据的特定部分。这也适用于smartctl、nvidia smi和ffmpeg/ffprobe等。简单地说,通常不需要围绕管道传输数据,也不需要为这样的任务打开子shell

因此,我会为作业使用正确的工具-在这种情况下,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”:只输出所需的原始数据值

“-打印格式”:使用某种格式打印数据

“compact=”:使用压缩输出格式

“print_section=0”:不打印节名

“:nokey=1”:不打印key:value对的密钥

“:escape=csv”:对值进行转义

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


参考资料:

ffmpeg已被avconv替换:只需将avconb替换为路易斯·马拉西奥的答案即可

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

注意:传统的。*之后开始获得独处的时间

>我只需在C++中使用文本文件,然后提取令牌。为什么?我不像其他人一样是linux终端专家

要设置它,我将在Linux中执行此操作

ffmpeg -i <file> 2>&1 | grep "" > mytext.txt
ffmpeg-i2>&1 | grep”“>mytext.txt

然后运行一些C++应用程序来获取所需的数据。可能会提取所有重要的值,并使用令牌重新格式化以供进一步处理。


我只需要开发自己的解决方案,人们会取笑我,因为我是Linux新手,我不太喜欢编写脚本。

Argh。算了吧。看起来我必须从C和C++编程中得到蛛网,然后使用它。我不知道让它工作的所有shell技巧

这就是我走了多远

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

然后我可能用C++应用程序来提取持续时间,而不是提取令牌。 我没有发布解决方案,因为我现在不是一个好人


更新-我有我的方法来获得持续时间戳 步骤1-将媒体信息保存到文本文件中

ffprobe -i myfile 2>&1 | awk '{ print }' > textdump.txt
第2步-掌握所需信息并提取 注意a。这是我的C代码,用于切掉生成的逗号,因为输出类似于
00:00:01.331,

下面是C代码,它接受stdin并输出所需的正确信息。我不得不把“大于”和“小于”的标志拿出来观看

#包括stdio.h
#包括string.h
void main()
{
//史密斯上将2016年11月3日
半焦时间[80];
内伦;
字符*正确;
扫描频率(“%s”和时间);
correct=(char*)malloc(strlen(time));
如果(!正确)
{
printf(“\n内存错误”);
返回;
}
memcpy(正确,&时间,strlen(时间)-1);
正确[strlen(time)]='/0';
printf(“%s”,正确);
自由(正确);
}
现在输出格式正确,如
00:00:01.33

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


HH:MM:SS.milisecs

我建议使用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
    }
}

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

最佳解决方案:剪切导出,获得类似于00:05:03.22的内容


如果您想通过使用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)

Grep是不必要的,
sed-n's/Duration:\(.*\),start/\1/gp'
就足够了。实际上,
sed
是不必要的:
ffmpeg-i file.mp4 2>&1 | Grep-o-P“(?如果我想将持续时间存储为同一PHP脚本中使用的变量,那么上下文是什么?如何在Python中执行相同的操作?按照其他答案中的说明使用ffprobe似乎是一种更干净、更省事的方法:)IMHO MediaInfo肯定会为您提供一个更容易解析的输出。这应该是“MediaInfo--Inform=“General;”%Duration%”~/work/files/testfiles/+h263_aac.avi”这两个表单在MediaInfo v18.05中的工作方式相同(似乎与以前的版本相同)。对于我的ffmpeg-0.6.5-1.el6.rf.x86_64,格式是:ffprobe-show_format 2>&1 | sed-n's/duration=//p'这就是方法。ffmpeg-我总是想在打印数据后转码一个新文件。这里有一个更干净的解决方案。应该是可以接受的答案,尽管输出格式(秒)不完全是所要求的。@bovender答案更新为输出所需格式的选项。@LordNeckbeard现在它真的应该是可接受的答案了!来自Libav(ffmpeg项目的分支)的伪“
ffmpeg
”已被
avconv替换<
cat textdump.txt |  grep "Duration" | awk '{ print $2 }' | ./a.out
ffmpeg -i abc.mp4 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//
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
    }
}
ffmpeg -i input 2>&1 | grep Duration | cut -c 13-23
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",
      ...
      ...