Unreal调用ffmpeg导出视频出现字节偏移花屏问题
故障排查与修复方案
核心花屏原因
花屏是Windows平台下管道未用二进制模式打开导致的,和像素写入逻辑无关:
- Windows平台C标准IO默认是文本模式,写入内容只要出现
0x0A(即十进制10,对应R通道值为10的像素),系统会自动在前面插入1字节0x0D,每插入一个字节,后续所有数据就整体偏移1位,累积下来就会出现斜向错位类花屏。 - 你测试时把R通道固定为255、G/B固定为0时,写入的字节只有
0x00和0xFF,完全不存在0x0A,不会触发自动转义,所以画面正常,和你观察到的现象完全匹配。
修复方式非常简单:调用popen打开ffmpeg管道时,把打开模式从"w"改成"wb",强制使用二进制模式,关闭自动换行转义即可。
其他必须修复的逻辑问题
1. 通道填充逻辑不符合预期
你代码里的counter是静态变量,每写完一整帧才加1,实际运行效果是三帧循环切纯色:
- counter为0的帧:所有像素仅R通道写真实值,G/B为0
- counter为1的帧:所有像素仅G通道写255,R/B为0
- counter为2的帧:所有像素仅B通道写255,R/G为0
完全不是“仅传输红色通道调试”的预期效果。如果要保留红通道调试逻辑,直接删掉counter相关判断即可:
for (int i = 0; i < ViewportSize[0] * ViewportSize[1]; i++) { ViewportImgRGB[3*i] = ViewportImg[i].R; ViewportImgRGB[3*i + 1] = 0; ViewportImgRGB[3*i + 2] = 0; }
2. Unreal视口数据的行对齐问题
Unreal读取的视口像素默认带GPU内存行对齐(Stride),每行内存长度会对齐到4/16字节整数倍,不一定等于视口宽度。你当前循环上限取ViewportImg.Num(),如果数组长度大于W*H,会往ViewportImgRGB数组越界写内存;如果直接按W宽度读,会把行尾的填充垃圾值写到画面里。
修复方式:要么读视口数据时手动指定行跨度为W * sizeof(FColor)关闭对齐,要么按行拷贝像素,跳过每行末尾的填充字节。
3. ffmpeg参数补全
当前ffmpeg命令没有指定IO模式,建议补充-avioflags direct参数,关闭ffmpeg侧的额外缓冲对齐,避免出现意料之外的字节偏移:
std::string command = "ffmpeg -loglevel warning -r " + std::to_string(1) + " -f rawvideo -pix_fmt rgb24 -s " + std::to_string(int(ViewportSize[0])) + "x" + std::to_string(int(ViewportSize[1])) + " -avioflags direct -i - -threads 0 -preset fast -y -crf 21 " + std::string(TCHAR_TO_UTF8(*FString( IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*FPaths::ProjectDir())))) + "raisimUnrealRecording" + std::to_string(dt.GetTimeOfDay().GetFractionTicks()) + ".mp4";
修复验证顺序
- 优先修改popen打开模式为
"wb",这一步改完99%概率直接解决花屏问题 - 修正通道填充逻辑,删掉错误的counter判断
- 处理UE侧行对齐问题,避免画面边缘出现异常彩条
- 补全ffmpeg参数,提升长时录制的稳定性
内容的提问来源于stack exchange,提问作者ultrafrog
相关产品推荐
相关产品推荐

