使用ffmpeg推送Python生成帧图像到RTMP流时出现色差如何解决
问题描述
我正尝试使用ffmpeg进行视频推流,输入源为Python输出的帧图像,采用管道方式传输,但推流播放时发现视频色彩与原始图像存在偏差。
当前使用的调用代码:
p = Popen(['ffmpeg', '-y', '-f', 'image2pipe', '-r', '30', '-i', '-', '-vcodec', 'mpeg4', '-qscale', '5', '-r', '30', '-b:a', '32k', '-ar', '44100', '-pix_fmt','rgb24', '-color_range', '3', '-c:v', 'libx264rgb', '-f', 'flv', 'rtmp://stream_ip/live/bbb'], stdin=PIPE)
画面对比:

问题根因
从FFmpeg运行日志可以定位到以下几个错误:
- 编码器参数冲突:命令中先后指定了
mpeg4、libx264rgb两个视频编码器,参数顺序错误导致最终FFmpeg使用了FLV格式默认的flv1编码器,自定义的色彩参数完全未生效 - 像素格式参数位置错误:FFmpeg参数为位置敏感,输入源参数必须放在
-i之前,你将-pix_fmt rgb24放在了输出参数段,没有正确指定输入帧的像素格式,FFmpeg自动将输入识别为YUV格式,转换过程中产生色偏 - 色彩范围参数非法:
-color_range 3为无效取值,合法取值仅为1(有限范围/TV级)、2(全范围/PC级),错误参数导致色彩映射异常 - 冗余音频参数:推流只有视频输入,
-b:a、-ar等音频参数无对应流匹配,会触发参数未生效警告
修正方案
情况1:Python输出为原始RGB像素帧
p = Popen([ 'ffmpeg', '-y', # 输入参数:明确指定输入为1152*720、30帧的RGB24原始帧,全范围色彩 '-f', 'rawvideo', '-vcodec', 'rawvideo', '-pix_fmt', 'rgb24', '-s', '1152x720', '-r', '30', '-color_range', '2', '-i', '-', # 输出参数:用H.264编码,适配FLV格式,指定标准色彩空间避免播放端色偏 '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-color_range', '2', '-colorspace', 'bt709', '-color_trc', 'bt709', '-color_primaries', 'bt709', '-preset', 'fast', '-crf', '23', '-r', '30', '-f', 'flv', 'rtmp://stream_ip/live/bbb' ], stdin=PIPE)
情况2:Python输出为JPEG编码的单帧字节流
p = Popen([ 'ffmpeg', '-y', # 输入参数:明确指定输入为JPEG图像流,全范围色彩 '-f', 'image2pipe', '-c:v', 'mjpeg', '-r', '30', '-color_range', '2', '-i', '-', # 输出参数:同上 '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-color_range', '2', '-colorspace', 'bt709', '-color_trc', 'bt709', '-color_primaries', 'bt709', '-preset', 'fast', '-crf', '23', '-r', '30', '-f', 'flv', 'rtmp://stream_ip/live/bbb' ], stdin=PIPE)
调整说明
- 移除了冲突的编码器和冗余音频参数,统一指定输出使用兼容FLV格式的H.264编码
- 调整了输入参数位置,明确告知FFmpeg输入帧的像素格式、色彩范围,避免自动识别出错
- 指定了标准BT.709色彩空间参数,保证不同播放端的色彩显示一致
- 将非法的色彩范围取值替换为对应全范围RGB输入的合法值2,修正色彩映射逻辑
内容的提问来源于stack exchange,提问作者codebot
相关产品推荐
相关产品推荐

