【问题标题】:Fetch frame count with ffmpeg使用 ffmpeg 获取帧数
【发布时间】:2011-01-02 08:03:27
【问题描述】:

有谁知道如何使用 ffmpeg 从视频文件中获取总帧数? ffmpeg 的渲染输出显示当前帧,我需要帧数来计算进度百分比。

【问题讨论】:

标签: video ffmpeg


【解决方案1】:

ffprobe

ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4

这实际上是对数据包而不是帧进行计数,但速度要快得多。结果应该是一样的。如果您想通过计数帧来验证,请将 -count_packets 更改为 -count_framesnb_read_packets 更改为 nb_read_frames

ffprobe 选项的含义

  • -v error 这隐藏了“信息”输出(版本信息等),这使得解析更容易(但如果您寻求帮助,则会更难,因为它隐藏了重要信息)。

  • -count_frames统计每个流的包数,并在对应的流部分上报。

  • -select_streams v:0只选择第一个视频流。

  • -show_entries stream=nb_read_packets 仅显示nb_read_frames 的条目。

  • -of csv=p=0 设置输出格式。在这种情况下,它会隐藏描述并仅显示值。有关其他格式(包括 JSON)的信息,请参阅 FFprobe Writers

只计算关键帧

Checking keyframe interval?

MP4 编辑列表

MP4/M4V/M4A/MOV 中存在的编辑列表会影响您的帧数。

另见


媒体信息

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

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

MP4 盒子

适用于 MP4/M4V/M4A 文件。

来自gpac的MP4Box可以显示帧数:

MP4Box -info input.mp4

请参阅输出中的Media Info 行以获取相关视频流:

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

在本例中,视频流有 2525 帧。


boxdumper

适用于 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 原子。

【讨论】:

  • 或者,如果您想要更快的速度并且如果 nb_frames 足够可靠,请简化为:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • 这会为我输出两次答案(即 2600 \n 2600)。有什么特别的原因会发生吗?
  • @jbodily 我的例子还是 juanitogan 的?我不能使用任何一个复制它。在这里工作不多。
  • +1,尤其是因为,与任何命令行工具的许多其他答案不同,这个答案实际上解释了所有命令行选项。谢谢。
  • 请注意,第一个选项,查询容器,由于 count_frames 而实际处理文件。请参阅@juanitogan 的评论。
【解决方案2】:

在 Unix 中,这就像一个魅力:

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

【讨论】:

  • 真的很不错。只是您不需要复制音频流。您可以使用 -an instat。
  • @PrakharMohanSrivastava 检查this answer
  • 实际上,这似乎又快又可靠: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
  • @Michael 感谢我早上喝咖啡时的微笑 :-)
  • @TimothyZorn 你成就了我的一天!
【解决方案3】:

改为根据时间计算。

这就是我所做的,它对我和其他许多人都很有效。首先,在下面的sn-p中找到视频的长度:

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 / duration * 100 = % done

【讨论】:

  • 对不起,我很愚蠢,但是当持续时间为 hh:mm:ss.nn 格式且时间始终为 xx.yy 格式时,我该怎么做时间/持续时间?
  • @Omar,作为 .NET 开发人员,我要做的是从中创建一个 TimeSpan,然后使用 currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100)。 TimeSpan 还提供了强大的 Parse 功能,check it out
  • 优秀的解决方案,我的时间是 hh:mm:ss:ms 所以我想在这 3 年里 FFMPEG 改进了输出时间格式。
  • 请注意,控制台输出可能会显示 29.97,但它是 30000/1001 的缩写。 23.98 相同,即 24000/1001,59.94 为 60000/1001。
  • 请注意,这不适用于可变帧率视频(显然)。
【解决方案4】:

并非所有格式都存储它们的帧数或总持续时间 - 即使它们存储,文件也可能不完整 - 因此 ffmpeg 在默认情况下无法准确检测到它们中的任何一个。

相反,请尝试寻找文件末尾并读取时间,然后一边走一边计算当前时间。

或者,您可以尝试AVFormatContext->nb_index_entries 或检测到的持续时间,这应该可以在至少未损坏的 AVI/MOV 或库 FFMS2 上正常工作,这可能太慢而无法使用进度条。

【讨论】:

    【解决方案5】:

    您可以使用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/A 作为输出。

    欲了解更多信息,请查看此页面FFProbe Tips

    【讨论】:

      【解决方案6】:

      由于我的评论得到了一些赞成,我想我会把它作为答案:

      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 命令将只显示最后一行(最终帧数)。

      【讨论】:

        【解决方案7】:

        尝试类似:

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

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

        【讨论】:

          【解决方案8】:

          试试这个:

          ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
          

          【讨论】:

          • 不适用于*.ts。输出为空行。
          【解决方案9】:

          对于 necro 的回答很抱歉,但可能需要这个(因为我没有为最近的 ffmpeg 版本找到解决方案。

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

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

          最后它会输出帧数。它适用于我的音频视频。不过,它给出了两次“nb_frames”行,但第一行是我测试的视频的实际帧数。

          【讨论】:

          • 谢谢@acidrums4。验证此方法适用于我今天构建的 github 的最新版本。
          • 使用ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames" | head -n1 | cut -d"=" -f2 为我工作,它将输出减少到只是数字。
          【解决方案10】:

          以 stu 的回答为基础。以下是我如何从手机中找到视频的帧速率。我运行了以下命令一段时间。在我不耐烦并点击^C之前,我让帧数达到约10,000:

          $ 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。

          【讨论】:

            【解决方案11】:

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

            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
            【解决方案12】:

            我使用 php_ffmpeg 然后我可以获得电影的所有时间和所有帧。如下

            $input_file='/home/strone/workspace/play/CI/abc.rmvb';
            $ffmpegObj = new ffmpeg_movie($input_file);
            echo $ffmpegObj->getDuration();
                echo $ffmpegObj->getFrameCount();
            

            然后详细信息在页面上。

            http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php

            【讨论】:

              【解决方案13】:
              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 给出确切的帧数。 (不开玩笑)。
              【解决方案14】:

              Linux

              ffmpeg -i "/home/iorigins/Завантаження/123.mov" -f null /dev/null
              

              红宝石

              result = `ffmpeg -i #{path} -f null - 2>&1`
              r = result.match("frame=([0-9]+)")
              p r[1]
              

              【讨论】:

                【解决方案15】:

                ffprobeffmpeg 信息的问题 是不是帧中的实际长度有一些差异。

                此脚本尝试提取最后一帧。 成功的帧号也可以在搅拌机内部工作。 超出该数量的帧也无法在搅拌机中提取。

                #!/usr/bin/env bash
                # find the number of frames in a movie clip
                FMAYBE=$(ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 $1)
                let FMAYBE=$FMAYBE+1
                FEMPTY="-"
                while [ -n "$FEMPTY" ] ; do
                  let FMAYBE=$FMAYBE-1
                  echo "Trying $FMAYBE"
                  FEMPTY=$(ffmpeg -i $1 -vf select="between(n\,$FMAYBE\,$FMAYBE)" -vsync 0 /tmp/fmaybe%d.png 2>&1 | grep 'empty')
                done
                echo "Succeeds: $FMAYBE"
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2023-03-12
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-11-07
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-01-08
                  • 1970-01-01
                  相关资源
                  最近更新 更多