使用FFMPEG编码如何精准获得指定大小的输出视频文件
核心问题原因
你出现的偏差主要来自3个底层错误:
- 比特率计算逻辑错误:没有扣除音频流、MP4容器元数据的占用空间,直接把全部3MB配额都分配给了视频流,本身就预留了溢出空间。
- 单位换算标准不统一:如果以操作系统识别的文件大小为准,1MB=1024KB而非1000KB,3MB对应的总字节数是3145728字节,也就是3072KB,你用3000KB计算本身就有2.4%的偏差。
- 缺少x264比特率约束参数:你只用了
-b:v设置平均比特率,没有配置VBV(视频缓冲区校验器)相关的限流参数,双通编码下编码器会根据画面复杂度动态调整比特占用,画面复杂时就会超出平均比特率配额,画面简单时则会低于配额。
为什么两种时长的偏差差异很大
- 2秒短视频的关键帧(I帧)占比极高,I帧体积是P/B帧的数倍到数十倍,如果原视频画面偏简单,编码器不需要满配额就能达到预设质量,最终就会出现体积低于预期的情况。
- 35秒长视频你算出来的685k视频比特率本身就已经超出了总配额:3MB总可用比特数是3072KB * 8 = 24576kbit,35秒总可用平均比特率是24576/35 ≈ 702kbps,扣除128kbps的音频比特率,留给视频的配额只有574kbps,你设685k本身就超了19%,加上容器开销后最终超到3.6MB是正常结果。
精准控制文件大小的方案
第一步:正确计算目标比特率
公式如下,预留5%-10%的空间给容器元数据即可:
总目标字节数 = 目标大小(MB) * 1024 * 1024 总可用比特数(kbit) = 总目标字节数 * 8 / 1000 总平均比特率(kbps) = 总可用比特数 / 视频时长(秒) 视频目标比特率(kbps) = (总平均比特率 - 音频比特率) * 0.9 // 乘0.9是预留10%的冗余空间
以你35秒3MB的场景举例:
总可用比特数 = 310241024*8/1000 ≈ 25166kbit
总平均比特率 = 25166 / 35 ≈ 719kbps
视频目标比特率 = (719 - 128) * 0.9 ≈ 532kbps
第二步:调整FFmpeg编码参数
添加VBV限流参数和最大文件限制参数,确保不会超出配额,双通命令修正为:
ffmpeg -y -i input -c:v libx264 -preset medium -b:v 532k -maxrate 580k -bufsize 580k -pass 1 -c:a aac -b:a 128k -f mp4 /dev/null && \ ffmpeg -i input -c:v libx264 -preset medium -b:v 532k -maxrate 580k -bufsize 580k -pass 2 -c:a aac -b:a 128k -fs 3145728 output.mp4
其中-maxrate、-bufsize是VBV限流参数,限制瞬时比特率不会超出太多,-fs 3145728是硬限制文件最大为3MB,超出就自动截断,不会出现超大小的情况。
内容的提问来源于stack exchange,提问作者Murat Colyaran
相关产品推荐
相关产品推荐

