Files
MediaOrganizer/docs/adr/0007-category-partitions-musicvideos.md
Shuery c1ed1795c2
CI / lint + test + build (push) Canceled after 0s
docs: 重写 README、新增项目报告与开发工具配置
- README 现代化重写:徽章区、特性一览、统一 GitHub 提示块格式、修正版本号与 AI 默认值
- 新增 docs/PROJECT_REPORT.md 学术项目报告(含许可证合规分析与死链修复记录)
- 收录 23 份 ADR 架构决策记录与 CONTEXT.md 领域术语表
- 新增开发配置:.editorconfig / .shellcheckrc / .markdownlint-cli2.jsonc
- .gitignore 补充 mo_map/、检查报告、编辑器临时文件
- 新增 config.example.json 配置模板(不含真实密钥)
2026-08-14 22:41:40 +08:00

5.7 KiB
Raw Permalink Blame History

配置按类目分区、特典类别外置与 Music Videos 类目

用户需求:四个配置文件(special_maps / special_keywords / skip_directories / season_offsets)"不仅需要支持当前的,还需要支持其它所有类目";特典类别判定表完全外置;并实现 Music Videos(音乐视频)类目。三项合为 v9.6。

配置按类目分区

四个文件支持两种形态:全局单表(旧版,行为不变)与类目分区({"tv": {...}, "musicvideo": [...]})。分区判定 is_category_partitioned:顶层全部键 ∈ MO_CATEGORY_KEYS(movie/tv/music/musicvideo/video/audio/default/global)→ 分区形态;混合形态警告并按全局处理(避免类目键被当数据键)。

查询链统一:类目/流程分区 → default 分区 → 全局表 → 内置默认。关键决策:

  1. 分区键语义因文件而异:特典映射/词表用类目键(tv/musicvideo);跳过目录用流程键(video/music)——目录语义判断发生在类目确定之前(正是用词表辅助判定),无法按条目类目取值;find_show_*/count_main_videos/detect_special 查 video 流程分区。
  2. skip_directories 分区 = 完整语义:分区形态不叠加内置默认——否则 music 流程会命中 video 侧内置词(如 "sps"),分区失去意义;通用词放 default 分区。旧全局形态保持"数组内容优先、空数组回退内置"。
  3. special_keywords 分区 = 叠加语义:tv 分区词 + 内置默认兜底(词表是积累型,AI 持续学习)。
  4. AI 写回自动适配:learn_skip_dirs/learn_special_keywords 检测分区形态,写 video/tv 分区(jq .video[...]/.tv[...] 路径),全局形态写顶层;内存表同步更新分区表。
  5. 分区引用展开:special_maps 分区内字符串引用同分区优先,其次全局表(resolve_special_value_cat)。

考虑过的方案:分区键用前缀(category.tv 等,丑且破坏旧格式兼容);分区判定用"至少一个类目键"(混合形态静默错位);skip_directories 保持全局 + 仅扩展词表(无法按流程区分,music 流程误命中 video 词)。

特典类别判定表外置

special_category_tag 原硬编码 24 项类别(Menu/CM/PV/...)→ 外置 mo_config/special_categories.json:数组保序 = 优先级([{"match": "nced", "tag": "NCED"}])。查询链:用户表(按序子串)→ 内置默认表(保留在 special_category_tag 作最后兜底)→ "Special"。缺失时交互创建(SPECIAL_CATEGORIES_TEMPLATE 常量),自动化跳过(内置兜底)。

考虑过的方案:对象形态(JSON 对象无顺序,判定优先级丢失——"mini anime" 需先于 "anime");并入 special_keywords(语义不同:词表判定"是否特典",类别表判定"S00 标签",且词表被 AI 写回,类别表是用户静态维护)。

Music Videos 类目

识别信号 = musicvideo 判定词(special_keywords 的 musicvideo 分区 → default → 内置 MUSICVIDEO_WORDS 13 词:mv/music video/live/concert/performance/演唱会/音乐视频/音乐录影带/现场 等)。不回退 tv 特典词表("sp" 子串命中 "SPs" 目录 = 稳定误判,正是开发中发现的 flakiness 根因之一)。

  1. 目录信号(强信号):目录名精确匹配(归一化去空格小写整名相等)musicvideo 词 → 整目录音乐视频(即使文件名含季集标记)。精确匹配避免 "Muv-Luv"/"tmp.xxx" 含词误判——开发中实测 mktemp 临时目录名(tmp.XXXXXXXX)约 3% 概率含 cm/sp/pv/mv 两字符词导致测试偶发失败,精确匹配彻底根除。
  2. 文件名信号:方括号标记子串命中 musicvideo 词。双命中歧义(标记同时在特典词表,如 [MV]/[PV])用 "歌手 - 歌名" 模式消解:文件名含 - → 音乐视频(歌手分隔是音乐视频命名典型结构);不含 → 保持特典路径("动画名 [MV]" 剧集 MV 特典不被误判)。两侧词表可配置完全控制。
  3. 命名:MusicVideos/{artist}/{title}.{ext}(NAMING_MUSICVIDEO 模板,Jellyfin 官方结构)。artist 链:元数据 ALBUMARTIST → ARTIST → 父目录名解析("歌手 - 歌名"取首段;无分隔符整名;源根直属不解析)→ FOLDER_UNKNOWN。
  4. 不进 AI:本地规则无网络请求,识别失败(artist 兜底 Unknown)恒成功,不消耗 AI 轮次;unknown 才交 AI(保持 AI 类型域 movie/tv 不变,零 prompt 改动)。
  5. 排除在特典路径外:musicvideo 判定置于 parse 的年份提取之后、TV/特典规则之前;[PV]/[CM] 不在 musicvideo 词表 → 特典路径不受影响。

考虑过的方案:目录信号子串匹配(flakiness 实证否决);musicvideo 词表回退 tv 特典词表(SPs 误判);双命中一律 musicvideo(剧集 MV 特典误判);Music Videos 走 AI 判断(需扩展 prompt 类型域,且本地规则已覆盖多数文件——CONTEXT 挂账"多数文件规则补齐"正是此意)。

配套

  • 新文件:src/lib/config/maps.sh 扩展(分区加载/查询 + 特典类别表),src/lib/main.sh(MUSICVIDEO_WORDS_TEMPLATE/SPECIAL_CATEGORIES_TEMPLATE 常量、分区表全局变量),src/lib/media/filename.sh(detect_musicvideo),src/lib/media/identify.sh(identify_musicvideo),src/lib/media/ai_resolve.sh(fallback musicvideo 分支),src/lib/pipeline/process.sh(分发),src/lib/integrate/ai.sh(写回分区感知)。
  • 测试:tests/cases/media/musicvideo.sh(7 例)、tests/cases/config/categories.sh(5 例)、tests/cases/config/partition.sh(6 例);全量 107 通过。
  • 版本 9.6(main.sh SCRIPT_VERSION + bashly.yml)。