如何以秒为单位获取视频时长?

7

如何获取视频时长(秒)?

我尝试过以下方法:

ffmpeg -i file.flv 2>&1 | grep "Duration"
  Duration: 00:39:43.08, start: 0.040000, bitrate: 386 kb/s


mediainfo file.flv | grep Duration
Duration : 39mn 43s

这个翻译接近正确,但不是非常准确,2383相当于39.71分钟。

    ffmpeg -i file.flv 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@\..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }'
2383

8个回答

11

有一个更好、更快、CPU/硬盘占用更低的解决方案,只需使用mediainfo而不依赖awk:

mediainfo --Inform="General;%Duration%" input.m4v

请注意,此命令会返回毫秒级别的精度,因此比任何 grep / awk 变体更准确。例如:mediainfo --Inform="General;%Duration%" video.mp4 --> 204466mediainfo video.mp4 | grep '^Duration' --> Duration : 3 min 24 s (= 204000ms)。 - trs

4

使用 awk

mediainfo file.flv | awk '/Duration/ {print $3*60+$4}'
2383

ffmpeg -i file.flv 2>&1 | awk '/Duration/ {split($2,a,":");print a[1]*3600+a[2]*60+a[3]}'
2383.08

处理不同格式,请使用以下方法:
cat file
Duration : 39mn 43s
Duration : 39s 43ms

awk '/Duration/ {for (i=3;i<=NF;i++) if ($i~/[0-9]+mn$/) s+=$i*60; else if ($i~/[0-9]+s$/) s+=$i; else if ($i~/[0-9]+ms$/) s+=$i/10; print s;s=0}'  file
2383
43.3


谢谢Jotne,正是我想要的! - Ilia
发现了一个错误。如果视频长度小于1分钟,则您的mediainfo示例无法正确执行,因为mediainfo以不同的格式输出时间,例如:Duration: 36s 360ms,并且使用您的代码会导致结果为2520。请修复。 - Ilia
@IliaRostovtsev,您是提问者“user2783132”的同一人吗? - Jotne
不! :) 他也遇到了同样的问题,我现在可以确定。 - Ilia
@IliaRostovtsev,请查看我的更新帖子。 - Jotne

4

3

对我来说有效,你也可以试试 :)

$duration = shell_exec("ffmpeg -i \"". $input . "\" 2>&1");

preg_match("/Duration: (\d{2}:\d{2}:\d{2}\.\d{2})/",$duration,$matches);
$time = explode(':',$matches[1]);
$hour = $time[0];
$minutes = $time[1];
$seconds = round($time[2]);

$total_seconds = 0;
$total_seconds += 60 * 60 * $hour;
$total_seconds += 60 * $minutes;
echo $total_seconds += $seconds;

2
您可以使用

标签


ffprobe -v quiet -print_format xml -show_format -show_streams inputfile.flv

它将返回一个类似于以下的XML:
<?xml version="1.0" encoding="UTF-8"?>
<ffprobe>
    <streams>
        <stream index="0" codec_name="h264" codec_long_name="H.264 / AVC / MPEG-4 AVC / 
    MPEG-4 part 10" profile="High" codec_type="video" codec_time_base="1/50" codec_tag_string="avc1" codec_tag="0x31637661" width="1920" height="1080" has_b_frames="2" sample_aspect_ratio="0:1" display_aspect_ratio="0:1" pix_fmt="yuvj420p" level="40" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/12800" start_pts="0" start_time="0.000000" duration_ts="50176" duration="3.920000" bit_rate="4347640" nb_frames="98">
                <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"/>
                <tag key="language" value="eng"/>
                <tag key="handler_name" value="VideoHandler"/>
            </stream>
        <stream index="1" codec_name="aac" codec_long_name="AAC (Advanced Audio Coding)" codec_type="audi

o" codec_time_base="1/48000" codec_tag_string="mp4a" codec_tag="0x6134706d" sample_fmt="fltp" sample_rate="48000" channels="2" bits_per_sample="0" r_frame_rate="0/0" avg_frame_rate="0/0" time_base="1/48000" start_pts="-1024" start_time="-0.021333" duration_ts="189184" duration="3.941333" bit_rate="122277" nb_frames="185">
            <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"/>
            <tag key="language" value="eng"/>
            <tag key="handler_name" value="SoundHandler"/>
        </stream>
    </streams>

    <format filename="inputfile.flv" nb_streams="2" format_name="mov,mp4,m4a,3gp,3g2,mj2" format_long_name="QuickTime / MOV" start_time="-0.021333" duration="3.942000" size="2194901" bit_rate="4454390">
        <tag key="major_brand" value="isom"/>
        <tag key="minor_version" value="512"/>
        <tag key="compatible_brands" value="isomiso2avc1mp41"/>
        <tag key="encoder" value="Lavf54.63.100"/>
    </format>
</ffprobe>

然后按照视频流进行过滤,即通常具有属性索引"0"的视频流,并获取属性“duration”的值,该值已经是以秒为单位。


1

我在php中使用了这个:

exec('mediainfo --Inform="General;%Duration%" ' . $filename, $output);
// type 86 sec = 85962.695312
$durationInSec = ceil(ceil($output[0])/1000);

0

如果您已经安装了ffmpeg,那么很可能也已经安装了ffprobe

ffprobe -i file.mp4 -show_format -v quiet | sed -n 's/duration=//p' | xargs printf %.0f

该命令将返回一个整数值。

输出示例:

190


1
我也想要一个以hh:mm:ss.ms格式输出的结果,但是我必须稍微修改你建议的命令才能得到我需要的结果。我将Video替换为General,这样就得到了命令--Inform="General;%Duration/String3%"。MediaInfo版本0.7.69 - ubiquibacon
你没有将值转换为秒,而是截取了毫秒部分而不是四舍五入。因此,你的结果不准确。你可以像 Rodrigo 的答案一样轻松地切掉值的最后3位数字,省略通过 PHP 和字符串解析的绕路。 - trs
@trs 同意。我不喜欢自己以前的回答,所以我进行了编辑。 - Ilia

0
如果你拥有ffmpeg,你也应该拥有ffprobe。它以一系列键值对的形式输出信息到STDOUT,并默认以秒为单位给出持续时间(如果要使用hh:mm:ss,必须使用-sexagesimal选项):
ffprobe -show_format file.mp4 | grep -F duration | cut -d= -f2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接