使用ffmpeg获取帧数


Answers:


158

注意:MP4 / M4V / M4A / MOV中存在编辑列表会影响您的帧号。请参阅下面的编辑列表


ffprobe:查询容器

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • 这是一种快速的方法。
  • 并非所有格式(例如Matroska)都会报告导致输出的帧数N/A。请参阅下面列出的其他方法。

ffprobe:计算帧数

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • 这是一种缓慢的方法。
  • 添加-skip_frame nokey选项以仅计算关键帧。

ffmpeg:计算帧数

如果没有,则ffprobe可以使用ffmpeg

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • 这是一种比较快的方法。
  • 请参阅frame=控制台输出附近的内容。
  • 添加-discard nokey输入选项(在之前-i)以仅计算关键帧。

编辑清单

忽略带有-ignore_editlist 1输入选项的MP4 / M4V / M4A / MOV编辑列表。默认为忽略编辑列表。

ffprobe选项意味着什么

  • -v error 这将隐藏“信息”输出(版本信息等),从而使解析更加容易。

  • -count_frames 计算每个流的帧数,并在相应的流部分中报告。

  • -select_streams v:0 仅选择视频流。

  • -show_entries stream=nb_frames-show_entries stream=nb_read_frames仅显示条目nb_framesnb_read_frames

  • -of default=nokey=1:noprint_wrappers=1将输出格式(也称为“书写器”)设置为default,不要打印每个字段的键(nokey=1),也不要打印节的页眉和页脚(noprint_wrappers=1)。还有更短的选择,例如-of csv=p=0

另见


媒体信息

众所周知的mediainfo工具可以输出帧数:

mediainfo --Output="Video;%FrameCount%" input.avi

MP4盒

对于MP4 / M4V / M4A文件。

MP4Box 从gpac可以显示帧数:

MP4Box -info input.mp4

请参考Media Info输出中有关视频流的行:

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples

在此示例中,视频流具有2525帧。


翻斗车

对于MP4 / M4V / M4A / MOV文件。

boxdumper是l-smash的简单工具。它将输出大量信息。在“ stsz样本大小”框下的部分中,参考sample_count了帧数。在此示例中,输入具有1900个视频帧:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • 请注意,一个文件可能有多个stsz原子。

5
或者,如果您想提高速度并且nb_frames足够可靠,请简化为:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
juanitogan

这将为我输出两次答案(即2600 \ n 2600)。会发生什么特殊原因吗?
jbodily

@jbodily我的例子或juanitogan的例子?我不能使用任何一个复制它。这里工作不多。
llogan

+1,这不仅是因为与其他有关任何命令行工具的其他答案不同,它实际上解释了所有命令行选项。谢谢。

1
请注意,第一个选项,即查询容器,由于count_frames而实际上处理了文件。参见@juanitogan的评论。
aggieNick02 '18

23

在Unix中,这就像魅力:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '

3
真的很不错。只是您不需要复制音频流。您可以使用-an instat。
2012年

1
@PrakharMohanSrivastava检查这个答案
Antonio

4
实际上,这似乎是快速而可靠的:ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1
Timothy Zorn

1
@Michael感谢我早上喝咖啡时的微笑:-)
Lloyd Moore

1
@TimothyZorn你成就了我的一天!
Mladen Danic

13

而是根据时间进行计算。

这就是我的工作,对我和其他许多人都很有用。)首先,在下面的代码段中找到视频的长度:

Seems stream 0 codec frame rate differs from container frame rate: 5994.00 
(5994/1) -> 29.97 (30000/1001)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/stu/Movies/District9.mov':
  Duration: 00:02:32.20, start: 0.000000, bitrate: 9808 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1920x1056, 29.97tbr, 2997tbn, 5994tbc
    Stream #0.1(eng): Audio: aac, 44100 Hz, 2 channels, s16
    Stream #0.2(eng): Data: tmcd / 0x64636D74

您应该能够始终如一地安全地 Duration: hh:mm:ss.nn确定源视频片段的大小。然后,对于每个更新行(CR,没有LF),您可以解析当前时间标记处的文本:

frame=   84 fps= 18 q=10.0 size=       5kB time=1.68 bitrate=  26.1kbits/s    
frame=   90 fps= 17 q=10.0 size=       6kB time=1.92 bitrate=  23.8kbits/s    
frame=   94 fps= 16 q=10.0 size=     232kB time=2.08 bitrate= 913.0kbits/s    

请注意不要总是从这些状态行中获得理想的输出。它们可能包含如下错误消息:

frame=   24 fps= 24 q=-1.0 size=       0kB time=1.42 bitrate=   0.3kbits/s    
frame=   41 fps= 26 q=-1.0 size=       0kB time=2.41 bitrate=   0.2kbits/s    
[h264 @ 0x1013000]Cannot parallelize deblocking type 1, decoding such frames in
sequential order
frame=   49 fps= 24 q=26.0 size=       4kB time=0.28 bitrate= 118.1kbits/s    
frame=   56 fps= 22 q=23.0 size=       4kB time=0.56 bitrate=  62.9kbits/s    

有了时间后,就可以进行简单的数学计算:time / durration * 100 = % done


1
抱歉,我是愚蠢的,但是当持续时间为hh:mm:ss.nn格式且时间始终为xx.yy格式时,我该如何做时间/持续时间?
奥马尔·阿里

2
@Omar,作为.NET开发人员,我要做的是TimeSpan从中创建一个,然后使用currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100)。时间跨度还提供了强大的解析功能,检查出来
摆振Weitzhandler

极好的解决方案,我的时间在hh:mm:ss:ms中,所以我认为FFMPEG在这3年中改善了输出时间格式。
ElektroStudios

1
请注意,控制台输出可能会说29.97,但这是30000/1001的缩写。与23.98相同,即24000/1001和59.94是60000/1001。
llogan'2

请注意,这不适用于可变帧率视频(显然)。
蒂莫西·佐恩

8

并非所有格式都存储它们的帧数或总持续时间-即使它们保存了,文件也可能是不完整的-因此ffm​​peg默认情况下不会准确地检测到这两种格式。

而是尝试查找文件的末尾并读取时间,然后计算当前时间。

或者,您可以尝试AVFormatContext->nb_index_entries或检测到的持续时间,该持续时间至少可以在未损坏的AVI / MOV或FFMS2上正常运行,而对于进度条来说,它可能太慢而无法打扰。


8

尝试类似的方法:

ffmpeg -i "path to file" -f null /dev/null

它将帧号写入stderr,因此您可以从中检索最后一帧。


8

您可以使用ffprobe 以下命令获取帧号

  1. 第一种方法

ffprobe.exe -i video_name -print_format json -loglevel fatal -show_streams -count_frames -select_streams v

告诉以json格式打印数据

select_streams v会告诉ffprobe您只给我们video流数据,如果您将其删除,它也会为您提供audio信息

和输出将像

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mpeg4",
            "codec_long_name": "MPEG-4 part 2",
            "profile": "Simple Profile",
            "codec_type": "video",
            "codec_time_base": "1/25",
            "codec_tag_string": "mp4v",
            "codec_tag": "0x7634706d",
            "width": 640,
            "height": 480,
            "coded_width": 640,
            "coded_height": 480,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "4:3",
            "pix_fmt": "yuv420p",
            "level": 1,
            "chroma_location": "left",
            "refs": 1,
            "quarter_sample": "0",
            "divx_packed": "0",
            "r_frame_rate": "10/1",
            "avg_frame_rate": "10/1",
            "time_base": "1/3000",
            "start_pts": 0,
            "start_time": "0:00:00.000000",
            "duration_ts": 256500,
            "duration": "0:01:25.500000",
            "bit_rate": "261.816000 Kbit/s",
            "nb_frames": "855",
            "nb_read_frames": "855",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "creation_time": "2005-10-17 22:54:33",
                "language": "eng",
                "handler_name": "Apple Video Media Handler",
                "encoder": "3ivx D4 4.5.1"
            }
        }
    ]
}

2.可以使用

ffprobe -v error -show_format -show_streams video_name

这将为您提供流数据,如果要选择诸如帧频之类的信息,请使用以下命令

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name

这会根据您的视频信息给出一个数字,问题是当您使用此方法时,可能会得到一个N/Aas输出。

有关更多信息,请检查此页面FFProbe提示



3

由于我的评论得到了一些好评,因此我想将其作为答案:

ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1

这应该很快,因为没有进行编码。ffmpeg只会将文件解复用并尽快读取(解码)第一个视频流。第一个grep命令将获取显示框架的文本。第二个grep命令将仅从中获取数字。该tail命令将仅显示最后一行(最终帧数)。


2

以斯图的答案为基础。这是我从手机中找到视频帧速率的方法。我运行了一段时间以下命令。我让帧数上升到大约10,000,然后再变得不耐烦并命中^ C:

$ ffmpeg -i 2013-07-07\ 12.00.59.mp4 -f null /dev/null 2>&1
...
Press [q] to stop, [?] for help
[null @ 0x7fcc80836000] Encoder did not produce proper pts, making some up.
frame= 7989 fps= 92 q=0.0 Lsize=N/A time=00:04:26.30 bitrate=N/A dup=10 drop=0    
video:749kB audio:49828kB subtitle:0 global headers:0kB muxing overhead -100.000042%
Received signal 2: terminating.
$

然后,我从该行中获取了两条信息,这些信息以“ frame =”开头,帧数为7989,时间为00:04:26.30。您首先需要将时间转换为秒,然后将帧数除以秒,以获得“每秒的帧数”。“每秒帧数”是您的帧速率。

$ bc -l
0*60*60 + 4*60 + 26.3
266.3

7989/(4*60+26.3)
30.00000000000000000000
$

我的视频的帧速率是30 fps。


2

我能够做到的唯一准确的信息如下:

ffprobe -i my_video.mp4 -show_frames 2>&1|grep -c '^\[FRAME'

为确保此功能适用于视频,请执行以下操作:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video

我支持您的答案,但这仅在视频不包含音频的情况下有效。如果包含,那么此文件将起作用:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe 2015年

2

很抱歉收到坏死的答案,但可能需要这个(因为我没有找到最新ffmpeg版本的解决方案。

使用ffmpeg 3.3.4,我发现可以找到以下内容:

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"

最后,它将输出帧数。它对带音频的视频很有效。虽然它给出了两次“ nb_frames”行,但是第一行是我测试的视频的实际帧数。


谢谢@ acidrums4。验证此方法可与我今天构建的github的最新版本一起使用。
Paul J


1
Cmd ->

ffprobe.exe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of default=nw=1 "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

Frames=24000/1001*8177.794625=196071

Proof -> 

ffmpeg -i "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4" -f null /dev/null
ffmpeg version N-92938-g0aaaca25e0-ffmpeg-windows-pacman Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.0 (GCC)
  configuration: --pkg-config=pkg-config --pkg-config-flags=--static --extra-version=ffmpeg-windows-pacman --enable-version3 --disable-debug --disable-w32threads --arch=x86_64 --target-os=mingw32 --cross-prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --enable-libcaca --enable-gray --enable-libtesseract --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libbs2b --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libzimg --enable-libzvbi --enable-libmysofa --enable-libaom --enable-libopenjpeg --enable-libopenh264 --enable-liblensfun --enable-nvenc --enable-nvdec --extra-libs=-lm --extra-libs=-lpthread --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --enable-amf --enable-libmfx --enable-gpl --enable-avisynth --enable-frei0r --enable-filter=frei0r --enable-librubberband --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxavs --enable-avresample --extra-cflags='-march=core2' --extra-cflags=-O2 --enable-static --disable-shared --prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/x86_64-w64-mingw32 --enable-nonfree --enable-decklink --enable-libfdk-aac
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 43.100 / 58. 43.100
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 47.100 /  7. 47.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'd:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
  Duration: 02:16:17.91, start: 0.000000, bitrate: 2497 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], 2397 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 93 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))
  Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
    Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.43.100 wrapped_avframe
    Stream #0:1(und): Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
      encoder         : Lavc58.43.100 pcm_s16le
frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x
video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

通常从两个参数中计算出帧速率。r_frame_rate = 24000/1001(= 23,97602397602397 ...)用ffmpeg舍入为:23.98持续时间=小时* 3600 +分钟* 60 +秒。余数= 8177,91而持续时间参数= 8177.794625但帧数= 24000/1001 * 8177.794625 = 196071给出确切的帧数。(开玩笑)。
杰拉德·温辛克

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.