首页 文章

使用ffmpeg获取帧计数

提问于
浏览
70

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

13 回答

  • 2

    在Unix中,这就像魅力:

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

    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]
    
  • 92

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

    ffprobe&ffmpeg

    ffprobe:查询容器

    ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
    
    • 这是一种快速的方法 .

    • 并非所有格式都会报告帧数,从而导致 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
    
    • 这是一种缓慢的方法 . 由于必须对整个文件进行解码,因此根据输入的持续时间和复杂程度,可能需要一段时间才能完成 .

    ffmpeg:解码并计算帧数

    如果您没有 ffprobe ,则可以使用 ffmpegawk 代替:

    ffmpeg -i input.mkv -map 0:v:0 -c copy -f null - 2>&1 | awk '/frame=/ {print $2}'
    
    • 这是一种缓慢的方法 . 由于必须对整个文件进行解码,因此根据输入的持续时间和复杂程度,可能需要一段时间才能完成 .

    • 如果您没有 awk (例如在Windows上),可以省略 2>&1 | awk '/frame=/{print $2}' ,并在控制台输出结尾附近引用 frame= .

    仅计算关键帧

    添加 -skip_frame nokey .

    • 适用于 ffprobeffmpeg .

    编辑清单

    使用 -ignore_editlist 1 输入选项忽略MP4 / M4V / M4A / MOV编辑列表 . 默认为 not 忽略编辑列表 .

    ffprobe选项的含义

    • -v error 这会隐藏"info"输出(版本信息等),这使得解析更容易 .

    • -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 将输出格式(又名"writer")设置为 default ,不要打印每个字段的键( nokey=1 ),也不要打印节页眉和页脚( noprint_wrappers=1 ) . 有更短的替代品,如 -of csv=p=0 .

    另见


    mediainfo

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

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

    MP4Box

    适用于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 原子 .
  • 2

    而是根据时间计算它 .

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

    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 .

  • 23

    并非所有格式都存储其帧数或总持续时间 - 即使它们存在,也可能不完整 - 因此ffmpeg默认情况下不会准确检测到它们 .

    相反,尝试寻找文件的末尾并读取时间,然后计算当前时间 .

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

  • 13

    尝试类似的东西:

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

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

  • 8

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

    • 第一种方法

    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"
                }
            }
        ]
    }
    

    你可以用

    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

  • 3

    试试这个:

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

    以斯图的答案为基础 . 这是我如何从手机中找到视频的帧速率 . 我运行了以下命令一段时间 . 在让我不耐烦并且点击^ 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.
    $
    

    然后,我 grab 了该行的两条信息,以“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 .

  • 8

    我能做到的唯一准确的是:

    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
    
  • 1

    我使用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

  • -1

    对不起,这可能需要这个(因为我没有找到最近的ffmpeg版本的解决方案) .

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

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

    最后它将输出帧数 . 它适用于带有音频的视频 . 它提供了两次“nb_frames”行,但第一行是我测试的视频的实际帧数 .

  • 0

    在其中一个答案中提到了如何使用'mediainfo'计算帧数:

    mediainfo --Output =“Video;%FrameCount%”input.avi

    如果输入文件是h264基本流'mediainfo'则不报告帧数 . 仅当输入文件是容器(mp4,ts或avi)时,才会计算和报告帧数 .

相关问题