自动合并按文件实际位置找弹幕,修掉「jsonl 文件不存在」
为什么: 录制结束时 moveFile 已经把 .ass / .nick.ass / .jsonl 搬到保存目录,但合并时只有视频 分段走了 findMovedFile 兜底,弹幕 jsonl 一直拿着录制时算出来的旧路径。于是文件明明 安安稳稳躺在保存目录里,burnDanmu 却去旧位置找,自动合并以「jsonl 文件不存在」告终 并推送一条失败通知。 连带还有两处也指向错误位置:tempMergeOutput 用 filepath.Dir(jsonlFile) 决定中间成片 写到哪个目录,mergeDelDanmu 按它去删那三个弹幕文件。 处理方式是新增 resolveAfterMove(path)——找不着就退回原路径,这样报错还能说清本来想 找哪儿——然后在两处归一:prepareForMerge 让返回的 jsonl 是解析后的路径;autoMergeJob 里也要归一,因为中间成片写到哪、事后删哪几个文件都看这条路径。 上一个提交(录制直接写保存目录)落地后这条会退化成空操作,文件压根不再挪窝;留着它 是为了兜住「运行中改了保存目录」「老录播补合并」这类场景。 验证: - 新增 automerge_test.go 两条:prepareForMerge 返回的视频与 jsonl 都从录制位置解析到 保存位置;目标目录里没有同名文件时退回原路径而不是返回空串。 - go test ./... 23.6s 与 go test -race ./... 26.4s 均全绿,215 个顶层用例。 - 反向验证新增一项:删掉 prepareForMerge 里那句归一,对应用例确实变红。 - 验证边界说明:测到的是路径解析这一层,没有构造一整场录制跑真 ffmpeg 走完合并流程 ——那需要一整套直播素材,成本远高于收益。
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// 录制结束时文件会被移动到保存目录,视频分段和弹幕文件都要按新位置找。
|
||||
// 以前只有视频分段走了查找,弹幕还拿着录制时的路径:视频找到了、弹幕找不到,
|
||||
// 整场合并以「jsonl 文件不存在」告终(用户看到的就是合成失败 + 一条失败推送)。
|
||||
func TestPrepareForMergeFindsMovedJsonl(t *testing.T) {
|
||||
savedConfig := config
|
||||
defer func() { config = savedConfig }()
|
||||
|
||||
root := t.TempDir()
|
||||
config.Directory = root
|
||||
config.RecordSubdir = "record"
|
||||
if err := os.MkdirAll(recordSaveDir(), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
name := "2026-09-27 22-40-42 甲 标题"
|
||||
// 录制时的位置:文件已经被搬走,这里不该再有
|
||||
oldDir := t.TempDir()
|
||||
oldVideo := filepath.Join(oldDir, name+".mp4")
|
||||
oldJsonl := filepath.Join(oldDir, name+".jsonl")
|
||||
// 实际位置
|
||||
newVideo := filepath.Join(recordSaveDir(), name+".mp4")
|
||||
newJsonl := filepath.Join(recordSaveDir(), name+".jsonl")
|
||||
for _, p := range []string{newVideo, newJsonl} {
|
||||
if err := os.WriteFile(p, []byte("{}\n"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
segs := []recordSegment{{file: oldVideo, startNs: 0}}
|
||||
video, jsonl, _, _, cleanup, err := prepareForMerge("没有这个-ffmpeg.exe", segs, oldJsonl, 0)
|
||||
defer cleanup()
|
||||
if err != nil {
|
||||
t.Fatalf("单段不该报错:%v", err)
|
||||
}
|
||||
if video != newVideo {
|
||||
t.Errorf("视频应当按保存目录里的实际位置找:\n got %s\n want %s", video, newVideo)
|
||||
}
|
||||
if jsonl != newJsonl {
|
||||
t.Errorf("弹幕文件应当按保存目录里的实际位置找:\n got %s\n want %s", jsonl, newJsonl)
|
||||
}
|
||||
}
|
||||
|
||||
// 文件确实不在(既没在录制时的位置、也不在保存目录)时,要退回原路径而不是空串:
|
||||
// 否则报错会变成「文件不存在:」,看不出到底缺的是哪个
|
||||
func TestResolveAfterMoveKeepsOriginalWhenMissing(t *testing.T) {
|
||||
savedConfig := config
|
||||
defer func() { config = savedConfig }()
|
||||
|
||||
root := t.TempDir()
|
||||
config.Directory = root
|
||||
config.RecordSubdir = "record"
|
||||
|
||||
gone := filepath.Join(t.TempDir(), "这个目录是对的但文件不在.mp4")
|
||||
if got := resolveAfterMove(gone); got != gone {
|
||||
t.Errorf("找不到时应当退回原路径:got %q want %q", got, gone)
|
||||
}
|
||||
|
||||
real := filepath.Join(root, "record", "在保存目录里.mp4")
|
||||
if err := os.MkdirAll(filepath.Dir(real), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(real, []byte("x"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := resolveAfterMove(real); got != real {
|
||||
t.Errorf("文件就在原路径时不该改:got %q want %q", got, real)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user