NB Frames 指的是一个音视频流中的帧数。缩写 NB 代表“number(数字)”。FFmpeg 及其 ffprobe 程序把这个字段称为 nb_frames。
一个文件可以包含多个流,每个流都有自己的 NB Frames 值。一个包含一个视频流和一个音频流的文件因此有 2 个独立的计数。NB Streams 是另一个值:它统计的是文件中的流数量,而不是某个流内部的帧数。
什么是帧
在视频流中,一帧就是视频的一张静止图像。在音频流中,帧的含义取决于格式。
在 AIFF 中,一个采样帧包含每个音频声道的一个采样点。在 MP3 中,一帧是一个更大的数据块,FFmpeg 会将帧数乘以每帧的采样数来得到时长。因此,你不能直接把一种音频格式的计数与另一种格式的计数进行对比。
数值的呈现方式
在已知的情况下,这个值是一个整数。这些值出现在 FFmpeg 的代码、文档和测试结果中:
708:FFmpeg 某个测试文件中一个视频流的帧数。1:HEIC 文件中单张静态图像的帧数。0:当帧数未知时,FFmpeg 编程接口使用的值。N/A:当值为 0 时,ffprobe 默认输出中显示的文本。在 JSON 和 XML 输出中,这个字段会被省略。
值为 0 或 N/A,或者字段缺失,都不能说明这个流是空的。它只表示 FFmpeg 没有在这个字段中写入计数。
数值的来源
NB Frames 通常来自文件自身的结构,因此 FFmpeg 不必实际数帧。具体来源取决于格式:
- MP4 和 MOV:FFmpeg 会累加时间到采样表(即
sttsatom)中的采样计数。 - AVI:FFmpeg 从流头部的
strhchunk 中读取一个 32 位数字。 - AIFF:FFmpeg 从 Common Chunk 中读取
numSampleFrames字段。 - WAV、MP3、FLAC 和 MKV:FFmpeg 针对这些格式的读取器不会设置该值,因此 ffprobe 的默认输出会显示
N/A。
MKV 文件仍然可以用另一个名称保存计数。mkvmerge 程序会为每个轨道写入一个名为 NUMBER_OF_FRAMES 的标签。
如何统计帧数
NB Frames 只是重复文件结构中存储的数字。这个数字并不能证明文件中真的包含了所有帧。FFmpeg 的一个 MOV 测试文件中存储的计数是 708,但 ffprobe 从该文件中只读取到 66 个数据包和 65 帧。
如果你想实际测量帧数,可以在运行 ffprobe 时加上 -show_streams 和 -count_frames 选项。ffprobe 会解码该流,并在单独的字段 nb_read_frames 中报告结果。这会更耗时,因为 ffprobe 必须解码每一帧。
你可以对视频流使用这个检查。在 AIFF 文件中,ffprobe 统计的是已解码的数据块,每个数据块包含许多采样帧,因此即使文件是完整的,这两个数字也会不同。
-count_packets 选项同样需要和 -show_streams 一起使用,它在不解码的情况下统计数据包数量,并在 nb_read_packets 字段中报告结果。一个视频数据包通常包含一个压缩帧,而一个音频数据包可能包含多个帧。
它的重要性
对于视频流,帧数和时长可以一起得出平均帧率。FFmpeg 的 MP4 和 MOV 读取器就是通过帧数和时长来计算帧率的。在同一个测试文件中,708 帧在 23.613333 秒内,大约等于每秒 29.98 帧。
帧数还能帮助你检查视频文件。如果测得的帧数远低于存储的帧数,说明视频数据的某一部分可能丢失了。