tamakyi
|
3eb4aa3102
|
让 ffmpeg 的报错能进日志,并堵住三处会直接毁掉整块渲染的坑
背景:线上第 153/648 块失败,三个编码器依次报同一个 "exit status 0xffffffea"
(EINVAL)。可用的线索只有这一句 —— 因为 ffmpeg 自己的输出走的是 os.Stderr,
服务模式下没人看,等于丢掉了。所以这轮先解决"看不到原因",再顺手补几处防御。
一、把 ffmpeg 的报错留在日志里
runFFmpegWith 给 stderr 挂一个只保留最后 40 行的 writer(进度行用 \r 刷新,
一并按行处理),失败时把这段附在错误上再由上层 lPrintErrf 写进日志。
顺带过滤掉每次启动都打印的版本/编译配置那几行(configuration 一行就一千多字符,
留着会把真正的报错挤出去)。实测效果:报错里直接能看到
"moov atom not found" / "Error opening input: Invalid data found"。
二、跟编码器无关的失败不再挨个回退
滤镜图建不起来、输入文件打不开这类问题,换个编码器结果一模一样。
原来会把同一件事重跑三遍(hevc_qsv → h264_qsv → libx264),既浪费时间
又在日志里刷三行看不出区别的错误。现在命中这些关键词就直接报出完整错误。
三、头像 split 的份数必须和真正用到的份数一致
统计头像用量时按整块弹幕算,生成 overlay 时才做可见性裁剪:
同一 uid 在本块有多条、其中一条整条落在块外的话,split 会多出一个没人接收的输出 pad,
ffmpeg 直接 EINVAL 退出(报错完全看不出跟弹幕有关)。抽出 danmuVisibleInChunk
让统计、生成 overlay、写块字幕三处用同一个判断。
四、缓存命中要校验文件完整,下载改成原子写
原来只看"文件在不在",被写一半的 PNG 会被当成可用缓存塞给 ffmpeg 当输入。
现在要求 PNG 以 IEND 收尾(16 字节以下直接判无效),下载先写 .part 再改名,
旧位置搬过来的文件同样要过这道校验。
五、头像直径至少为 1
有人把 danmuFontSize 填成 1、2 时 avatarSize 会算出 0,而 scale=0:0
会让 ffmpeg 直接 EINVAL、整块渲染失败。
验证:
- gofmt / go vet / go build 通过;go test 全绿(16.8s);go test -race 全绿(22.8s);
staticcheck -checks=all 零告警
- 新增 diagnostics_test.go(10 个)与 split_pad_test.go(1 个)用例;
反向验证扩到 21 项全过
- 隔离实例:e2e.py 37 项、smoke_extra.py 33 项、smoke_late_danmu.py(越界弹幕场景)全过;
另用一个损坏的 mp4 实测,任务失败时日志里能看到 ffmpeg 的原话,
且没有出现编码器回退
|
2026-09-26 12:15:14 +08:00 |
|