有人知道如何使用ffmpeg从视频文件中提取总帧数吗? ffmpeg的渲染输出显示当前帧,我需要帧数来计算百分比进度。
ffprobe -v error -select_streams v:0 -count_packets \
-show_entries stream=nb_read_packets -of csv=p=0 input.mp4
实际上这个计数的是数据包而不是帧,但速度更快。结果应该是一样的。如果你想通过计算帧数来验证,请将-count_packets
更改为-count_frames
并将nb_read_packets
更改为nb_read_frames
。
-v error
这会隐藏“info”输出(版本信息等),这使得解析更容易(但如果您请求帮助,则会隐藏重要信息使得难度增加)。
-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/M4V/M4A/MOV中存在编辑列表可能会影响帧数。
众所周知的mediainfo
工具可以输出帧数:
mediainfo --Output="Video;%FrameCount%" input.avi
用于处理 MP4/M4V/M4A 文件。
MP4Box
可以显示 gpac 中的帧数:
MP4Box -info input.mp4
请参考输出中与所询问的视频流相关的媒体信息
行:
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
原子。nb_frames
足够可靠,可以简化为:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
。 - juanitogan在Unix中,这个代码运行得非常好:
ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 \
| grep 'frame=' | cut -f 2 -d ' '
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这是我和许多人都在使用的方法,效果非常好。首先,在以下代码片段中找到视频的长度:
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
一旦你有了时间,这是简单的数学问题:时间÷持续时间×100%=完成率
。
由于我的评论得到了一些赞,我觉得我会把它作为答案留下来:
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
命令将只显示最后一行(最终帧数)。
您可以使用 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技巧
并不是所有格式都存储它们的帧数或总时长 - 即使存储了,文件也可能不完整 - 因此默认情况下 ffmpeg 检测这两个值时不会准确。
相反地,尝试跳到文件末尾并读取时间,然后边读边计算当前时间。
或者,您可以尝试使用 AVFormatContext->nb_index_entries
或检测到的时长,在至少未损坏的 AVI/MOV 上应该可以正常工作,或者使用 FFMS2 库,但进度条可能会过慢而不值得使用。
ffmpeg -i "path to file" -f null /dev/null
ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"
最终输出的是帧数。这个针对带有音频的视频也适用。虽然会给出两行"nb_frames"的输出,但第一行是我测试过的视频中实际的帧数。
ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames" | head -n1 | cut -d"=" -f2
对我很有效,它可以将输出减少到只有数字。 - jgraup试试这个:
ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
*.ts
文件一起使用。输出为空行。 - Victor Polevoy我唯一能做到的精确翻译是以下内容:
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