使用ffmpeg获取帧计数

Han*_*nsl 98 video ffmpeg

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

llo*_*gan 134

注意: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
Run Code Online (Sandbox Code Playgroud)
  • 这是一种快速的方法.
  • 并非所有格式(例如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
Run Code Online (Sandbox Code Playgroud)
  • 这是一种缓慢的方法.
  • 添加-skip_frame nokey选项仅计算关键帧.

ffmpeg:计算帧数

如果你没有,ffprobe你可以使用ffmpeg:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
Run Code Online (Sandbox Code Playgroud)
  • 这是一种有点快的方法.
  • 请参阅frame=控制台输出的末尾附近.
  • 添加-discard nokey输入选项(之前-i)仅计算关键帧.

编辑列表

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

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 --Output="Video;%FrameCount%" input.avi
Run Code Online (Sandbox Code Playgroud)

MP4Box

适用于MP4/M4V/M4A文件.

MP4Box 来自gpac可以显示帧数:

MP4Box -info input.mp4
Run Code Online (Sandbox Code Playgroud)

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

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples
Run Code Online (Sandbox Code Playgroud)

在该示例中,视频流具有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
Run Code Online (Sandbox Code Playgroud)
  • 请注意,文件可能包含多个stsz原子.

  • 或者,如果你想要更高的速度并且如果nb_frames足够可靠,则简化为:`ffprobe -v error -select_streams v:0 -show_entries stream = nb_frames -of default = nokey = 1:noprint_wrappers = 1 input.mkv` (5认同)

ata*_*xic 23

在Unix中,这就像魅力:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Run Code Online (Sandbox Code Playgroud)

  • 实际上,这看起来又快又可靠:`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]+' | 尾-1` (10认同)
  • 这是不可靠的,并且不能始终如一地工作 (8认同)
  • 真的很棒.只是您不需要复制音频流.你可以使用-an instat. (3认同)

Stu*_*son 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
Run Code Online (Sandbox Code Playgroud)

您应该能够始终如一地安全地找到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    
Run Code Online (Sandbox Code Playgroud)

只是因为并不总是期望这些状态线的完美输出.它们可以包含如下错误消息:

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    
Run Code Online (Sandbox Code Playgroud)

一旦你有时间,这是简单的数学:time / durration * 100 = % done.

  • 请注意,这不适用于可变帧率视频(显然)。 (3认同)
  • @Omar:编写要转换的代码.75.23 == 00:01:15.23 (2认同)
  • @Omar,作为.NET开发人员,我做的是从它创建一个`TimeSpan`,然后使用`currentDurationTimeSpan.Ticks /(totalDurationTimeSpan.Ticks/100)`.TimeSpan还提供了强大的Parse功能,[查看](http://msdn.microsoft.com/en-us/library/se73z7b9.aspx) (2认同)

Tim*_*orn 9

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

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
Run Code Online (Sandbox Code Playgroud)

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


ale*_*nge 8

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

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

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


a1k*_*kmm 8

尝试类似的东西:

ffmpeg -i "path to file" -f null /dev/null
Run Code Online (Sandbox Code Playgroud)

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


Had*_*ekh 7

您可以使用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"
            }
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

你可以用

ffprobe -v error -show_format -show_streams video_name
Run Code Online (Sandbox Code Playgroud)

这将为您提供流数据,如果您想要选择帧速率等信息,请使用以下命令

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name
Run Code Online (Sandbox Code Playgroud)

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

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


小智 5

尝试这个:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Run Code Online (Sandbox Code Playgroud)


aci*_*ms4 5

很抱歉死灵答案,但也许需要这个(因为我没有找到最近 ffmpeg 版本的解决方案。

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

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"
Run Code Online (Sandbox Code Playgroud)

最后它将输出帧计数。它对我来说对带有音频的视频很有用。不过,它给出了两次“nb_frames”行,但第一行是我测试的视频的实际帧数。