Python OpenCV+FFmpeg推RTMP流CPU占用过高优化问询
首先澄清核心认知偏差:
移除
-pix_fmt bgr24参数后CPU占用下降,和BGR转RGB的开销没有关联。此时FFmpeg未获取到输入原始帧的正确像素格式,会默认按yuv420p格式错误解析传入的BGR字节流,本质是跳过了正确的帧解析、格式转换流程直接编码乱序字节,才会出现CPU占用降低的情况,对应输出就是你看到的色彩错乱、帧错位的异常画面。
你当前方案CPU占用高于纯FFmpeg推流,核心原因有两个:一是FFmpeg命令缺失关键编码参数,默认编码配置效率低;二是帧格式转换流程存在冗余开销,可通过以下方案优化:
补全编码参数,使用优化的x264编码配置
你当前命令中注释掉了-c:v libx264和输出像素格式参数,FFmpeg封装FLV时会自动选择默认编码配置,没有针对推流场景做优化,这部分是CPU开销的主要来源。请使用补全后的参数,额外添加zerolatency调优项适配实时推流场景,减少无意义的算力消耗:command = ['ffmpeg', '-y', '-an', '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', sizeStr, '-r', '25', '-i', '-', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'ultrafast', '-tune', 'zerolatency', '-f', 'flv', rtmp]纯FFmpeg推流CPU占用低,本质是它读取本地视频时直接从解码器拿到YUV格式帧,无需额外色彩转换即可送入编码器,流程没有冗余。
把格式转换步骤前移到OpenCV侧,消除FFmpeg侧转换开销
OpenCV的cvtColor函数做了SIMD指令集优化,色彩空间转换效率高于FFmpeg的通用raw视频解析转换流程。你可以在读取帧后直接在OpenCV侧把帧转为编码需要的YUV420P格式,再传给FFmpeg,此时FFmpeg不需要再做任何格式转换,这部分开销可以降到接近0:- 读帧后添加转换逻辑:
yuv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420) - 将FFmpeg输入参数的
-pix_fmt bgr24修改为-pix_fmt yuv420p - 后续写入管道时直接传入
yuv_frame.tobytes()即可
- 读帧后添加转换逻辑:
可选进阶优化:减少管道内存拷贝
如果做完前两步后CPU占用仍有差距,可以把subprocess的默认PIPE替换为命名管道传递帧数据,减少用户态/内核态的内存拷贝开销,对于720p/1080p@25fps的常规推流场景,前两个优化落地后CPU占用基本可以和纯FFmpeg推流持平。
内容的提问来源于stack exchange,提问作者shao wenzhi

