package main import ( "image" "image/png" "os" "path/filepath" "testing" ) // 一块里同一个人有多条弹幕、但其中一条整条落在块外(会被裁掉)时, // 头像的 split 份数必须和真正用到的份数一致 —— 否则 split 会多出一个没人接收的输出 pad, // ffmpeg 直接以 EINVAL(Windows 上就是 exit status 0xffffffea)退出, // 报错完全看不出跟弹幕有关,还会连累三个编码器挨个"失败"。 func TestRenderChunkMatchesSplitWithVisibleDanmu(t *testing.T) { ffmpegFile := getFFmpeg() if ffmpegFile == "" { t.Skip("找不到 ffmpeg,跳过") } withJobFlags(t, true, false, false) dir := t.TempDir() // 头像 av := filepath.Join(dir, "av.png") f, err := os.Create(av) if err != nil { t.Fatal(err) } if err := png.Encode(f, image.NewRGBA(image.Rect(0, 0, 16, 16))); err != nil { t.Fatal(err) } f.Close() // 同一个 uid 两条弹幕:一条在块内可见,另一条时间远在块外 uid := int64(7) chunk := danmuChunk{start: 0, end: 1, records: []danmuRecord{ {Time: 0.2, UID: uid, Name: "甲", Content: "块内可见的", Lane: 0, Width: 100}, {Time: 30.0, UID: uid, Name: "甲", Content: "整条在块外的", Lane: 1, Width: 100}, }} ctx := &burnContext{ ffmpegFile: ffmpegFile, outFile: filepath.Join(dir, "out.mp4"), meta: danmuMeta{PlayResX: 160, PlayResY: 120, FontSize: 20}, avatars: map[int64]string{uid: av}, dir: dir, encoder: "libx264", // 直接指定软编,别让 QSV 的兼容性干扰这条用例 } out := filepath.Join(dir, "chunk.mov") if err := ctx.renderChunk(chunk, "chunk.ass", out, false, nil); err != nil { t.Fatalf("同一个人有两条弹幕、其中一条在块外时不该渲染失败:%v", err) } if !fileExists(out) { t.Fatalf("应当产出文件:%s", out) } }