补测试:重排对「本程序自己录的弹幕」零影响;多分段跨段冲突被一并解决
核实「弹道重排会不会影响正常录播的合并」时补的两个用例: - 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 —— 这是重排唯一会改变输出的场景, 方向是变好,不是回归。
This commit is contained in:
@@ -87,6 +87,60 @@ func TestRelayoutWidthScalesWithFontSize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// 多分段(断流重连)拼接时,remapJsonlTimes 只改时间、保留各段自己算的弹道,
|
||||
// 两段各自都从 0 号弹道开始排,时间压缩到同一条轴之后必然互相压。重排按拼接后
|
||||
// 的时间轴统一分配,这种跨段冲突也会一并消掉。
|
||||
func TestRelayoutFixesConcatenatedSegmentConflict(t *testing.T) {
|
||||
meta := danmuMeta{PlayResX: 1920, PlayResY: 1080, FontSize: 48}
|
||||
mk := func(base float64) []danmuRecord {
|
||||
var out []danmuRecord
|
||||
for i := 0; i < 12; i++ {
|
||||
out = append(out, danmuRecord{
|
||||
Time: base + float64(i)*0.4,
|
||||
UID: int64(3000 + i),
|
||||
Name: "观众",
|
||||
Content: "断流前后各自的弹幕",
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
// 两段各自从 0 秒开始排(录制时就是这样),拼接后第二段紧接第一段
|
||||
first := mk(0)
|
||||
relayoutLanes(first, meta)
|
||||
second := mk(4.8)
|
||||
relayoutLanes(second, meta)
|
||||
records := append(append([]danmuRecord{}, first...), second...)
|
||||
|
||||
// 前提:这种拼法本来就撞(第二段的 0 号弹道紧接第一段的 0 号弹道)
|
||||
if overlaps := countLaneOverlaps(records, meta); overlaps == 0 {
|
||||
t.Fatal("两段直接拼起来本应有同弹道冲突,用例前提不成立")
|
||||
}
|
||||
|
||||
relayoutLanes(records, meta)
|
||||
|
||||
if overlaps := countLaneOverlaps(records, meta); overlaps != 0 {
|
||||
t.Errorf("重排后仍有 %d 条同弹道冲突", overlaps)
|
||||
}
|
||||
}
|
||||
|
||||
// 按渲染时的公式统计同弹道追尾条数
|
||||
func countLaneOverlaps(records []danmuRecord, meta danmuMeta) int {
|
||||
show := int64(danmuShowSeconds * 1e9)
|
||||
resX := int64(meta.PlayResX)
|
||||
last := map[int]int64{} // 弹道 → 上一条的让位时刻
|
||||
over := 0
|
||||
for _, r := range records {
|
||||
total := int64(avatarSize(meta.FontSize)+avatarGap(meta.FontSize)) + int64(r.Width)
|
||||
rel := int64(r.Time * 1e9)
|
||||
emerge := rel + total*show/(resX+total)
|
||||
if prev, ok := last[r.Lane]; ok && rel < prev {
|
||||
over++
|
||||
}
|
||||
last[r.Lane] = emerge
|
||||
}
|
||||
return over
|
||||
}
|
||||
|
||||
// 密集弹幕(弹道信息全是坏的:lane 都是 0、width 都是 0)重排后不应再有追尾,
|
||||
// 也不该超过弹道行数上限
|
||||
func TestRelayoutNoOverlapOnDenseInput(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user