弹幕字号按画面短边自动定,竖屏成片不再字大到铺满整行
1. 字号基准从「画面高度」改成「画面短边」 以前合并时只用高度比换算字号(字号 × 视频高 ÷ 弹幕文件高)。横屏弹幕文件 (1920x1080、60 号)配竖屏视频(720x1280)时会被放大到 71 号,而画面只有 720 宽,一条 10 字弹幕就铺满整行。横竖屏互换时高度不是约束文字宽度的维度, 短边才是:横屏取高、竖屏取宽。 2. 「弹幕字号」填 0 的含义从「跟随弹幕文件」改成「自动按画面分辨率」 取画布短边的 5.56%(60/1080)。于是 1920x1080 → 60、1280x720 → 40、 960x540 → 30,横屏行为与以前完全一致;720x1280 → 40(以前 60)、 640x1280 → 36。填大于 0 仍是精确像素覆盖。 3. 录制端竖屏档位预设 720x1280 的字号从 60 改成 40 原来横屏三档都是短边的 5.56%,只有竖屏这档是 8.33%,比横屏大 50%。 改完四档口径一致,新录的弹幕文件和成片也对得上。 4. 坐标系和字号拆开 unifyDanmuSpace 只负责把 PlayRes 统一到视频分辨率,字号统一交给 applyFontSize 按最终画布算,避免两处各改一次。 5. .gitignore 加上 /avatar_cache 头像缓存挪到程序目录后,程序正好跑在仓库里,缓存目录会被 git 看见, git add . 会把那 336 个 PNG 一起提交进去。 已验证: - 新增 TestShortSide / TestAutoFontSize / TestSubConfigsMatchAutoFontSize / TestApplyFontSize;TestUnifyDanmuSpace 改成只校验 PlayRes,并且新增断言 确认它不再动字号。 - 反向验证:把短边规则临时退回「按高度」,TestAutoFontSize 报 「720x1280 应为 40,实际 71」「1080x1920 应为 60,实际 107」, TestApplyFontSize、TestSubConfigsMatchAutoFontSize 同步失败。 - 端到端:造 720x1280 竖屏视频 + 1920x1080/60 号的 jsonl,字号填 0 真跑一次合并, 日志打出「竖屏画布 720x1280,弹幕字号自动取 40」;同一输入再用旧规则跑一次对照, 抽同一时刻的帧量墨迹高度:改前 46px、改后 25px(1.84 倍)。 - gofmt / go vet / go build / GOOS=linux go build / go test 全过。
This commit is contained in:
+112
-13
@@ -123,32 +123,131 @@ func TestRelayoutFixesConcatenatedSegmentConflict(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// 弹幕坐标系(PlayRes)和视频分辨率不一致时统一到视频坐标系:
|
||||
// 跟随文件时字号按高度比换算,用户填了字号就按成片像素直接用
|
||||
// 画布短边:横屏取高、竖屏取宽
|
||||
func TestShortSide(t *testing.T) {
|
||||
cases := []struct {
|
||||
w, h, want int
|
||||
}{
|
||||
{1920, 1080, 1080},
|
||||
{1080, 1920, 1080},
|
||||
{720, 1280, 720},
|
||||
{1280, 720, 720},
|
||||
{1080, 1080, 1080},
|
||||
{0, 1080, 0},
|
||||
{1920, -1, 0},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := shortSide(c.w, c.h); got != c.want {
|
||||
t.Errorf("shortSide(%d,%d) 应为 %d,实际 %d", c.w, c.h, c.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自动字号 = 画布短边的 5.56%。竖屏必须按宽度算 ——
|
||||
// 按高度算的话 720x1280 会得到 71,一条弹幕就铺满整行。
|
||||
func TestAutoFontSize(t *testing.T) {
|
||||
cases := []struct {
|
||||
vw, vh, want int
|
||||
}{
|
||||
{1920, 1080, 60},
|
||||
{1280, 720, 40},
|
||||
{960, 540, 30},
|
||||
{720, 1280, 40},
|
||||
{640, 1280, 36},
|
||||
{1080, 1920, 60},
|
||||
{1080, 1080, 60}, // 方形按宽算
|
||||
{0, 1080, 0}, // 拿不到尺寸
|
||||
{1920, 0, 0},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := autoFontSize(c.vw, c.vh); got != c.want {
|
||||
t.Errorf("autoFontSize(%d,%d) 应为 %d,实际 %d", c.vw, c.vh, c.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 录制端的档位预设必须和自动字号规则一致,否则录出来的弹幕文件和成片对不上
|
||||
func TestSubConfigsMatchAutoFontSize(t *testing.T) {
|
||||
for key, cfg := range subConfigs {
|
||||
want := autoFontSize(cfg.PlayResX, cfg.PlayResY)
|
||||
if cfg.FontSize != want {
|
||||
t.Errorf("档位 %d(%dx%d)字号应为 %d,实际 %d",
|
||||
key, cfg.PlayResX, cfg.PlayResY, want, cfg.FontSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 主流程:先把坐标系统一到视频分辨率,再按画布定字号
|
||||
func TestApplyFontSize(t *testing.T) {
|
||||
// 横屏弹幕文件 + 竖屏成片:以前按高度比会放大到 71,现在按短边取 40
|
||||
meta := danmuMeta{PlayResX: 1920, PlayResY: 1080, FontSize: 60}
|
||||
unifyDanmuSpace(&meta, 720, 1280)
|
||||
applyFontSize(&meta, 0)
|
||||
if meta.FontSize != 40 {
|
||||
t.Errorf("竖屏成片字号应为 40,实际 %d", meta.FontSize)
|
||||
}
|
||||
|
||||
// 横屏成片和弹幕文件一致时保持原样
|
||||
meta = danmuMeta{PlayResX: 1920, PlayResY: 1080, FontSize: 60}
|
||||
unifyDanmuSpace(&meta, 1920, 1080)
|
||||
applyFontSize(&meta, 0)
|
||||
if meta.FontSize != 60 {
|
||||
t.Errorf("1080p 横屏字号应为 60,实际 %d", meta.FontSize)
|
||||
}
|
||||
|
||||
// 竖屏弹幕文件 + 同尺寸竖屏成片:老文件写的 60 要归一到 40
|
||||
meta = danmuMeta{PlayResX: 720, PlayResY: 1280, FontSize: 60}
|
||||
unifyDanmuSpace(&meta, 720, 1280)
|
||||
applyFontSize(&meta, 0)
|
||||
if meta.FontSize != 40 {
|
||||
t.Errorf("竖屏弹幕文件应归一到 40,实际 %d", meta.FontSize)
|
||||
}
|
||||
|
||||
// 设置里填了数就按填的来(成片像素)
|
||||
meta = danmuMeta{PlayResX: 1920, PlayResY: 1080, FontSize: 60}
|
||||
unifyDanmuSpace(&meta, 720, 1280)
|
||||
applyFontSize(&meta, 33)
|
||||
if meta.FontSize != 33 {
|
||||
t.Errorf("填了 33 就该用 33,实际 %d", meta.FontSize)
|
||||
}
|
||||
|
||||
// 拿不到画布尺寸时保留弹幕文件里的字号
|
||||
meta = danmuMeta{FontSize: 48}
|
||||
applyFontSize(&meta, 0)
|
||||
if meta.FontSize != 48 {
|
||||
t.Errorf("拿不到尺寸时应保留 48,实际 %d", meta.FontSize)
|
||||
}
|
||||
|
||||
// 低分辨率也别算出 0 号字
|
||||
meta = danmuMeta{PlayResX: 4, PlayResY: 4, FontSize: 30}
|
||||
applyFontSize(&meta, 0)
|
||||
if meta.FontSize < 1 {
|
||||
t.Errorf("字号不能小于 1,实际 %d", meta.FontSize)
|
||||
}
|
||||
}
|
||||
|
||||
// 弹幕坐标系(PlayRes)和视频分辨率不一致时统一到视频坐标系;
|
||||
// 字号不在这里改,由 applyFontSize 按最终画布决定
|
||||
func TestUnifyDanmuSpace(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
resX, resY, fontSize int
|
||||
vw, vh int
|
||||
override int
|
||||
wantChanged bool
|
||||
wantFontSize int
|
||||
}{
|
||||
{"坐标系一致不动", 1920, 1080, 60, 1920, 1080, 0, false, 60},
|
||||
{"960x540 弹幕配 720x1280 视频(跟随文件)", 960, 540, 30, 720, 1280, 0, true, 71},
|
||||
{"同上但用户填了 42", 960, 540, 30, 720, 1280, 42, true, 42},
|
||||
{"手机档 720x1280 弹幕配 540x960 视频", 720, 1280, 60, 540, 960, 0, true, 45},
|
||||
{"探测不到视频尺寸就不动", 960, 540, 30, 0, 0, 0, false, 30},
|
||||
{"相同宽高比但不同分辨率也要按视频走", 1280, 720, 40, 1920, 1080, 0, true, 60},
|
||||
{"坐标系一致不动", 1920, 1080, 60, 1920, 1080, false},
|
||||
{"960x540 弹幕配 720x1280 视频", 960, 540, 30, 720, 1280, true},
|
||||
{"探测不到视频尺寸就不动", 960, 540, 30, 0, 0, false},
|
||||
{"相同宽高比但不同分辨率也要按视频走", 1280, 720, 40, 1920, 1080, true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
meta := danmuMeta{PlayResX: c.resX, PlayResY: c.resY, FontSize: c.fontSize}
|
||||
changed := unifyDanmuSpace(&meta, c.vw, c.vh, c.override)
|
||||
changed := unifyDanmuSpace(&meta, c.vw, c.vh)
|
||||
if changed != c.wantChanged {
|
||||
t.Errorf("%s:changed 应为 %v,实际 %v", c.name, c.wantChanged, changed)
|
||||
}
|
||||
if meta.FontSize != c.wantFontSize {
|
||||
t.Errorf("%s:字号应为 %d,实际 %d", c.name, c.wantFontSize, meta.FontSize)
|
||||
if meta.FontSize != c.fontSize {
|
||||
t.Errorf("%s:统一坐标系不该动字号,应为 %d,实际 %d", c.name, c.fontSize, meta.FontSize)
|
||||
}
|
||||
if changed {
|
||||
if meta.PlayResX != c.vw || meta.PlayResY != c.vh {
|
||||
|
||||
Reference in New Issue
Block a user