Files
acfunlive-remake/automerge_test.go
T
tamakyi 40f4f36aa6 自动合并按文件实际位置找弹幕,修掉「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 走完合并流程
  ——那需要一整套直播素材,成本远高于收益。
2026-09-28 02:04:10 +08:00

77 lines
2.6 KiB
Go

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)
}
}