修第三批 P2:除零、停止/暂停的响应与状态一致性、临时文件、带 BOM 的 ASS
一、弹幕滚动时间不再整数除零 write() 里拿 (PlayResX+length) 做除数,PlayResX 被配成 0 又收到一条空内容弹幕时 分母正好是 0,直接 panic 终止整场录制。抽成 scrollMarks 并给分母为 0 的兜底 (退回半个停留时长,至少让它正常显示出来)。 二、点停止不再要等整个块渲完 jobAttach 原来只看 paused:停止请求若落在 jobGate 之后、ffmpeg 启动过程中, job.proc 还没登记,jobStop 拿不到进程可杀,用户得等整个块渲完(大块要几分钟)。 现在 attach 时发现任务已请求停止就地把它杀掉,上层拿到 errJobStopped, 卡片显示的是「已停止」而不是「失败」。 三、暂停没挂住就回滚状态 jobPause 先把 job.paused 置 true 再调 suspendProcess,挂起失败时状态已经改了: 界面显示「已暂停」而 ffmpeg 还在跑。失败时回滚(只在 proc 仍是同一个进程时回滚)。 jobResume 同理:恢复不成放回「已暂停」,免得显示在跑却停着。 四、.ass 还原的临时 jsonl 用完就删 还原结果写不进录播目录时会退到系统临时目录的固定名文件,原来从不清理, 每失败一次留一份。新增 danmuSource.tempJsonl 标记 + dropTempDanmu 收尾删除; 只删标记过的临时文件 —— 正常情况下那个路径是用户录播目录里的同名 jsonl, 删了就是丢数据。 五、带 BOM 的 ASS 能整份解析 带 UTF-8 BOM 时首行是 BOM+[Script Info],一个节都进不去,最后只报 「可能不是弹幕文件」,跟真实原因完全对不上。解析时剥掉 BOM。 六、头像下载期间暂停/停止不用再干等 单次超时 30 秒 × 3 次重试,最坏 96 秒才响应暂停/停止。单次超时收到 10 秒 (头像只有几百 KB),并且每次重试前过闸门:暂停在这里等、停止直接放弃, 不再把剩下的重试跑完;停止也不再打「头像不可用」的告警。 验证: - gofmt -l 空;go vet ./... 空;go build 与 GOOS=linux go build 通过 - go test ./... 全绿(10.9s);go test -race ./... 全绿(14.5s) - 新增 p2_fixes_test.go 8 个用例;本轮 6 项加上一批 6 项共 12 项反向验证全部通过 (每项临时退回源码 → 对应测试确实失败 → 恢复) - 51897 隔离实例上完整复测:e2e.py 37 项全过、smoke_extra.py 33 项全过
This commit is contained in:
@@ -251,6 +251,9 @@ type danmuSource struct {
|
||||
last float64
|
||||
hasAvatar bool
|
||||
source string // 来源说明
|
||||
// 从 .ass 还原出来的结果写不进原目录、退到系统临时目录时置位:
|
||||
// 这种文件调用方用完必须删掉,别在临时目录里越攒越多
|
||||
tempJsonl bool
|
||||
}
|
||||
|
||||
func prepareDanmuSource(path string, write bool) (danmuSource, error) {
|
||||
@@ -294,12 +297,21 @@ func prepareDanmuSource(path string, write bool) (danmuSource, error) {
|
||||
}
|
||||
lPrintWarnf("无法把还原结果写入 %s(%v),改用临时文件 %s", jsonlPath, err, tmp)
|
||||
src.jsonlPath = tmp
|
||||
src.tempJsonl = true
|
||||
return src, nil
|
||||
}
|
||||
lPrintf("已把 %s 还原成 %s", filepath.Base(path), filepath.Base(jsonlPath))
|
||||
return src, nil
|
||||
}
|
||||
|
||||
// .ass 还原结果退到系统临时目录时,用完就删。只删标记过的临时文件:
|
||||
// 正常情况 jsonlPath 是用户录播目录里的同名 jsonl,删了就是丢数据
|
||||
func dropTempDanmu(src danmuSource) {
|
||||
if src.tempJsonl {
|
||||
_ = os.Remove(src.jsonlPath)
|
||||
}
|
||||
}
|
||||
|
||||
// 输出文件名只能是文件名本身,且固定为 mp4
|
||||
func sanitizeOutName(name string) (string, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
@@ -479,6 +491,8 @@ func runManualMerge(plan mergePlan) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 还原结果写不进原目录时用的是系统临时目录里的文件,合并完就删掉
|
||||
defer dropTempDanmu(src)
|
||||
|
||||
// 每一段的录制开始时刻取自文件名,用来算偏移和拼接后的时间轴
|
||||
segs := make([]recordSegment, 0, len(plan.videos))
|
||||
|
||||
Reference in New Issue
Block a user