Files
MeBox/internal/service/media_probe_chapters_test.go
T
2026-09-23 16:07:28 +08:00

112 lines
3.5 KiB
Go

package service
import (
"testing"
"github.com/truewhile/MeBox/internal/model"
)
// 章节标题只有「有语义」时才认。西文关键词要词边界,否则 Options / Weekend
// 这类标题会被误判成片头/片尾;中文日文按子串匹配。
func TestChapterTitleKind(t *testing.T) {
cases := []struct {
title string
want string
}{
{"Intro", model.SegmentKindIntro},
{"Opening", model.SegmentKindIntro},
{"Opening Title", model.SegmentKindIntro},
{"OP", model.SegmentKindIntro},
{"NCOP", model.SegmentKindIntro},
{"片头", model.SegmentKindIntro},
{"オープニング", model.SegmentKindIntro},
{"Recap", model.SegmentKindRecap},
{"Previously on", model.SegmentKindRecap},
{"前情提要", model.SegmentKindRecap},
{"回顾", model.SegmentKindRecap},
{"あらすじ", model.SegmentKindRecap},
{"End Credits", model.SegmentKindCredits},
{"Credits", model.SegmentKindCredits},
{"Ending", model.SegmentKindCredits},
{"ED", model.SegmentKindCredits},
{"Outro", model.SegmentKindCredits},
{"片尾", model.SegmentKindCredits},
{"エンディング", model.SegmentKindCredits},
{"Next Episode", model.SegmentKindPreview},
{"Next time", model.SegmentKindPreview},
{"Preview", model.SegmentKindPreview},
{"预告", model.SegmentKindPreview},
{"次回予告", model.SegmentKindPreview},
// 无语义或容易误判的标题一律不认:猜错比没有数据更糟。
{"", ""},
{" ", ""},
{"Chapter 01", ""},
{"Chapter 12", ""},
{"Options", ""},
{"Weekend", ""},
{"Main Menu", ""},
{"Menu", ""},
}
for _, tc := range cases {
if got := chapterTitleKind(tc.title); got != tc.want {
t.Errorf("chapterTitleKind(%q) = %q, want %q", tc.title, got, tc.want)
}
}
}
func TestChaptersToSegmentsOnlyKeepsSemanticChapters(t *testing.T) {
rows := chaptersToSegments([]ProbeChapter{
{Index: 0, StartMs: 0, EndMs: 95_000, Title: "Chapter 01"},
{Index: 1, StartMs: 228_664, EndMs: 246_143, Title: "Opening"},
{Index: 2, StartMs: 246_500, EndMs: 247_400, Title: "Recap"}, // 不足 chapterMinMs
{Index: 3, StartMs: 3_431_000, EndMs: 0, Title: "End Credits"},
})
if len(rows) != 2 {
t.Fatalf("rows = %#v, want 2 (Opening + End Credits)", rows)
}
if rows[0].Kind != model.SegmentKindIntro || rows[0].StartMs != 228_664 || rows[0].EndMs != 246_143 {
t.Fatalf("first row = %#v", rows[0])
}
if rows[1].Kind != model.SegmentKindCredits || rows[1].StartMs != 3_431_000 || rows[1].EndMs != 0 {
t.Fatalf("second row = %#v", rows[1])
}
for _, row := range rows {
if row.Source != SegmentSourceFFprobe {
t.Fatalf("source = %q, want %q", row.Source, SegmentSourceFFprobe)
}
}
}
func TestChaptersToSegmentsIgnoresUntitledAndNegativeChapters(t *testing.T) {
rows := chaptersToSegments([]ProbeChapter{
{Index: 0, StartMs: 0, EndMs: 60_000, Title: ""},
{Index: 1, StartMs: -1, EndMs: 60_000, Title: "Intro"},
})
if len(rows) != 0 {
t.Fatalf("rows = %#v, want none", rows)
}
}
func TestNormalizeSegmentSourceFallsBackToAuto(t *testing.T) {
cases := map[string]string{
"": SegmentSourceAuto,
" ": SegmentSourceAuto,
"auto": SegmentSourceAuto,
"AUTO": SegmentSourceAuto,
"ffprobe": SegmentSourceFFprobe,
" FFprobe ": SegmentSourceFFprobe,
"theintrodb": SegmentSourceTheIntroDB,
"TheIntroDB": SegmentSourceTheIntroDB,
"aniskip": SegmentSourceAuto, // 未知值按 auto 处理
}
for input, want := range cases {
if got := NormalizeSegmentSource(input); got != want {
t.Errorf("NormalizeSegmentSource(%q) = %q, want %q", input, got, want)
}
}
}