如何获取视频每帧真实存储大小以计算每秒比特率?
问题原因及解决方案
你当前代码计算的是解码后原始像素帧的大小,而视频文件里存储的是经过编码压缩后的帧数据(比如H.264、AV1这类编码格式),两者完全不是一个概念——原始像素帧大小只和分辨率、位深有关,和视频的压缩率、编码格式无关,所以自然和文件实际总大小对不上。
要获取视频每帧的真实存储大小,推荐用以下方法:
方法一:用ffprobe直接获取(最简便可靠)
ffprobe是FFmpeg套件里的工具,能直接读取视频容器中的帧元数据,包括每帧的压缩后字节大小。
步骤:
- 先确保你的环境安装了FFmpeg(包含ffprobe工具)
- 用Python调用ffprobe命令解析帧大小,示例代码:
import subprocess import os def get_frame_sizes(video_path): # 调用ffprobe提取视频流每帧的字节大小 cmd = [ "ffprobe", "-select_streams", "v:0", # 选择第一个视频流 "-show_entries", "frame=pkt_size", # 只获取帧的数据包大小 "-of", "csv=p=0", # 输出格式为纯文本每行一个数值 "-hide_banner", "-loglevel", "error", video_path ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: raise RuntimeError(f"解析失败: {result.stderr}") # 转换为整数列表,每个元素对应一帧的字节数 return [int(line) for line in result.stdout.strip().split("\n") if line] def get_video_fps(video_path): # 获取视频帧率 cmd = [ "ffprobe", "-select_streams", "v:0", "-show_entries", "stream=r_frame_rate", "-of", "csv=p=0", "-hide_banner", "-loglevel", "error", video_path ] result = subprocess.run(cmd, capture_output=True, text=True) fps_str = result.stdout.strip() num, den = map(int, fps_str.split("/")) return num / den # 示例使用 video_file = "your_video.mp4" frame_sizes = get_frame_sizes(video_file) total_frame_size = sum(frame_sizes) fps = get_video_fps(video_file) print(f"所有帧总大小(字节): {total_frame_size}") print(f"文件实际大小(字节): {os.stat(video_file).st_size}") print(f"平均每帧大小(字节): {total_frame_size / len(frame_sizes):.2f}") # 计算每秒比特率(bps):平均帧大小(字节)*8(转比特)*帧率 bitrate = (total_frame_size / len(frame_sizes)) * 8 * fps print(f"视频每秒比特率(bps): {bitrate:.2f}")
说明:
pkt_size就是该帧在视频文件中实际占用的字节数,包含编码后的帧数据和少量容器头部信息- 总帧大小和文件实际大小会有小幅差异,因为文件还包含容器的元数据(比如索引、格式信息),但核心的视频数据都在帧里
方法二:手动解析视频容器格式(不推荐)
如果不想依赖FFmpeg,需要自己解析视频容器的结构(比如MP4的ISO BMFF格式、MKV的EBML格式),找到存储帧数据的区块(比如MP4的mdat盒子),再根据容器的帧索引分割每帧的大小。这种方法需要深入了解视频容器的规范,实现复杂且容易出错,仅适合有底层格式开发经验的场景。
内容的提问来源于stack exchange,提问作者tianlong yu
相关产品推荐
相关产品推荐

