核实「弹道重排会不会影响正常录播的合并」时补的两个用例: - recordjsonl_test.go:用真正的录制写入器 danmuWriter 造 500 条(密集,平均 0.22 秒一条),再按合并流程读回 jsonl 重排 —— 弹道变化 0 条、宽度变化 0 条。录制侧 写文件完全不经过 relayoutLanes,只有合并渲染前会重排,所以磁盘上的 .ass/.nick.ass/.jsonl 一个字节都不变,单段自动合并的成片和以前完全一致。 (顺带记下录制时确实会丢弹幕:500 条里 1 条因为 100 条弹道全满被丢弃, jsonl 里根本没有它,重排也不会把它变出来。) - layout_test.go:多分段(断流重连)拼接时 remapJsonlTimes 只改时间、保留各段 自己算的弹道,两段都从 0 号弹道起排,时间压缩到同一根轴后必然互相压。新增用例 先断言这种拼法本来就撞,再断言重排后冲突为 0 —— 这是重排唯一会改变输出的场景, 方向是变好,不是回归。
94 lines
2.6 KiB
Go
94 lines
2.6 KiB
Go
package main
|
||
|
||
import (
|
||
"bufio"
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"testing"
|
||
|
||
"github.com/orzogc/acfundanmu"
|
||
)
|
||
|
||
// 用真正的录制写入器(danmuWriter)产生 jsonl,再按合并的流程重排一遍,
|
||
// 验证「本程序自己录下来的弹幕」合出来和以前一模一样(弹道、宽度都不变)。
|
||
// 这也是手动合并与自动合并的分水岭:录制侧写文件完全不经过 relayoutLanes,
|
||
// 只有合并渲染前会重排,所以磁盘上的 .ass/.nick.ass/.jsonl 一个字节都不变。
|
||
func TestLiveRecordingPathUnaffected(t *testing.T) {
|
||
dir := t.TempDir()
|
||
cfg := acfundanmu.SubConfig{Title: "测试直播", PlayResX: 1920, PlayResY: 1080,
|
||
FontSize: 48, StartTime: 1700000000000000000}
|
||
ass := filepath.Join(dir, "live.ass")
|
||
w := newDanmuWriter("liveid", "stream", cfg, ass)
|
||
|
||
texts := []string{"来啦", "这首歌好听", "主播加油啊", "打卡打卡", "哈哈哈哈哈哈哈哈哈",
|
||
"这条弹幕稍微长一点看看弹道到底怎么排"}
|
||
for i := 0; i < 500; i++ {
|
||
relMs := int64(i) * 220 // 平均 0.22 秒一条,够密集
|
||
c := &acfundanmu.Comment{Content: texts[i%len(texts)]}
|
||
c.SendTime = (cfg.StartTime + relMs*1e6) / 1e6
|
||
c.UserID = int64(2000 + i%9)
|
||
c.Nickname = "观众" + string(rune('A'+i%9))
|
||
c.Avatar = "http://example.invalid/a.png"
|
||
w.write(c)
|
||
}
|
||
w.close()
|
||
|
||
f, err := os.Open(filepath.Join(dir, "live.jsonl"))
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer f.Close()
|
||
sc := bufio.NewScanner(f)
|
||
sc.Buffer(make([]byte, 1<<20), 1<<20)
|
||
var meta danmuMeta
|
||
first := true
|
||
var recs []danmuRecord
|
||
for sc.Scan() {
|
||
if first {
|
||
json.Unmarshal(sc.Bytes(), &meta)
|
||
first = false
|
||
continue
|
||
}
|
||
var r danmuRecord
|
||
if json.Unmarshal(sc.Bytes(), &r) == nil {
|
||
recs = append(recs, r)
|
||
}
|
||
}
|
||
type snap struct{ lane, width int }
|
||
before := make([]snap, len(recs))
|
||
for i, r := range recs {
|
||
before[i] = snap{r.Lane, r.Width}
|
||
}
|
||
|
||
relayoutLanes(recs, meta)
|
||
|
||
laneDiff, widthDiff := 0, 0
|
||
for i, r := range recs {
|
||
if r.Lane != before[i].lane {
|
||
laneDiff++
|
||
if laneDiff <= 3 {
|
||
t.Logf("第 %d 条弹道变了:%d → %d", i, before[i].lane, r.Lane)
|
||
}
|
||
}
|
||
if r.Width != before[i].width {
|
||
widthDiff++
|
||
}
|
||
}
|
||
t.Logf("录制产生 %d 条弹幕(含空内容 %d 条),重排后弹道变化 %d 条、宽度变化 %d 条",
|
||
len(recs), countEmpty(recs), laneDiff, widthDiff)
|
||
if laneDiff != 0 || widthDiff != 0 {
|
||
t.Errorf("正常录制的弹幕重排后不应有任何变化")
|
||
}
|
||
}
|
||
|
||
func countEmpty(recs []danmuRecord) int {
|
||
n := 0
|
||
for _, r := range recs {
|
||
if r.Content == "" {
|
||
n++
|
||
}
|
||
}
|
||
return n
|
||
}
|