命令行

命令行

我得到了一个没有元数据的视频文件。

例如如果我这样做:

ffmpeg -i test.m2v

我得到这些值:

Duration: N/A, bitrate: N/A

还有办法获取视频/.m2v 文件的时长吗?

编辑:

完整的控制台输出:

ffmpeg version 2.8.4 Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 5.2.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libdcadec --enable-libfr
eetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enab
le-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-lzma --enable-decklink
--enable-zlib
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, mpegvideo, from '.\Test.m2v':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], max. 7000 kb/s, 25 fps, 25 tbr, 1200k tbn, 50 tbc

答案1

对于原始比特流,可以使用 ffprobe。

ffprobe -show_entries stream=r_frame_rate,nb_read_frames -select_streams v -count_frames -of compact=p=0:nk=1 -v 0 in.m2v

这产生了

30/1|120

其中第一个条目是帧速率,是一个有理数,第二个条目是计数的帧数。持续时间是120 / (30/1) = 4.00s

答案2

如果你有元数据,那么你需要建造通过读取和解析整个文件来获取这些元数据(这就是它的ffprobe作用),并根据文件的实际内容得到正确的答案。

没有更准确答案。然而,快点答案。正如所注意到的,“如果你在 VLC 中打开此类视频,它会立即显示视频的时长“。在很多地方,VLC(以及其他工具)似乎估计,而不是读取并解析整个文件(您可能无法或不愿意这样做):

/* try to calculate movie time */
if( p_sys->p_fp->i_data_packets_count > 0 )
{
    uint64_t i_count;
    uint64_t i_size = stream_Size( p_demux->s );

    if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
    {
        i_size = p_sys->i_data_end;
    }

    /* real number of packets */
    i_count = ( i_size - p_sys->i_data_begin ) /
              p_sys->p_fp->i_min_data_packet_size;

    /* calculate the time duration in micro-s */
    p_sys->i_length = VLC_TICK_FROM_MSFTIME(p_sys->p_fp->i_play_duration) *
               (vlc_tick_t)i_count /
               (vlc_tick_t)p_sys->p_fp->i_data_packets_count;
    if( p_sys->i_length <= p_sys->p_fp->i_preroll )
        p_sys->i_length = 0;
    else
    {
        p_sys->i_length  -= p_sys->p_fp->i_preroll;
        p_sys->i_bitrate = 8 * i_size * CLOCK_FREQ / p_sys->i_length;
    }
}

在这种情况下,

流 #0:0:视频:mpeg2video(主)、yuv420p(电视)、720x576 [SAR 64:45 DAR 16:9],最大 7000 kb/s、25 fps、25 tbr、1200k tbn、50 tbc

已知流速度为 7000 kb/s,文件大小为,将文件大小除以 7000 kbit 并乘以 8 即可立即得出可能的持续时间(以秒为单位)。

例如我这里有一个文件(实际文件时长 02:32:19,文件大小 733,802,496)

Stream #0:0: Video: ... 562 kb/s, 25 fps ...
Stream #0:1: Audio: ... 54 kb/s

562+54 为 616kbits,即 77kbytes。733,802,496 除以 (77*1024) 为 9306,9306 秒为 2 小时 35 分 6 秒,不确切地正确,但非常接近。

根据实际使用的编解码器、音频/视频交错方法、相同的填充以及是否是 CBR 或 VBR,实际准确度可能会有所不同。

缺乏可靠的元数据,如果您重视速度而不是准确性,那么我担心估计是可行的方法。

在某些情况下,您可能能够同时执行这两项操作(根据文件头和大小提供即时估计,然后在 UI/程序没有更好的事情可做时开始读取并优化答案。然后,您甚至可以将新计算的元数据保存在某个地方,以便以后需要时检索它们 - 在数据库、缩略图文件、备用数据流中,或者甚至在可行的情况下提供更新/“修复”视频文件)。

命令行

从命令行使用 ffmpeg:

 #!/bin/bash

 if [ ! -r "$1" ]; then
     echo "File '$1' not found"
     exit 1
 fi
 FILESIZE=$( stat -c "%s" "$1" )
 STREAMS=$( 
      ffmpeg -i "$1" 2>&1 \
      | grep 'Stream #' \
      | tr "," "\n" \
      | grep "kb/s" \
      | tr " " "\n" \
      | grep "^[1-9][0-9]*$" )
 RATE=0
 for r in $STREAMS; do
     RATE=$[ $RATE + $r ]
 done
 # I don't think that bash has decimal support, so we use bc
 SECONDS=$( echo "$FILESIZE / $RATE" | bc )
 # To get seconds in HH:MM:SS format we use 'date'
 DURATION=$( TZ=UTC date +"%H:%M:%S" -d @$SECONDS )

即使视频文件中有多个音频流,这也应该是准确的。我不确定如果有字幕之类的数据流会发生什么。这种流的大小应该不大,所以它不应该造成干扰,但话又说回来,它可能造成干扰。

相关内容