关于 anibon-timestamper-local
用于将 YouTube 长直播整理为时间戳和主题摘要的本地处理技能。它支持递归或分组分块处理,并结合转录清理、本地多模态分析与校验步骤。
主要功能
- 01递归与分组处理模式
- 02转录清理和实体词表生成
- 03本地文本与视觉模型分析
- 04按主题归组时间戳
- 05时间戳审计与规范化
适用场景
- 01为长直播生成章节时间戳
- 02使用本地模型总结直播
- 03根据画面和参考资料核验模糊主题
- 04发布前规范转录错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zenithth/ anibon-stream-synthesis --skill anibon-timestamper-local安装后在 Claude Code 中输入/anibon-timestamper-local确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
config.jsonreferences/timestamper-handoff.mdscripts/launch_local.batlaunch_local.ps1launch_local.shlaunch_local.zshprepare_video.pyprocess_chunks_local.pysignal_detector.pyscripts/anibon/__init__.pyconfig.pydomain_db.pyknowledge_reader.pylmstudio.pymultimodal.pyparity_gates.pyphonetic_bridge.pyprompts.pystate.pysummarizer.pytimestamps.pytopic_scanner.pytranscript_source.pyvision_verify.pyworld_sanitizer.pytests/__init__.pytest_config.pytest_domain_db.pytest_knowledge_reader.pytest_lmstudio.py详细介绍
Anibon Timestamper(本地 P100 版)
概述
用于本地处理长时直播的流水线,可通过动态递归滚动摘要状态机(--mode recursive)或分组批处理(--mode group)生成 YouTube 时间戳和摘要,并支持多模态上下文融合、自动标签规范化,以及两轮 YouTube 评论格式化。
适用场景
- 在单张 GPU 上本地处理直播(例如 NVIDIA Tesla P100 16GB、Apple Silicon Metal、LM Studio、Ollama),无需承担云 API 费用。
- 云端/前沿模型:如果用户拥有云 API 访问权限,并希望通过高并发子 Agent 编排处理(Claude 3.5 Sonnet、Gemini 2.0 Pro),请改用
anibon-timestamper。
配套技能与必需子技能
anibon-world-identity(必需):只要直播内容涉及游戏、动漫、Pokémon、特摄或流行文化话题,就必须加载。最终确定时间戳前,Agent 必须根据本地参考资料(references/INDEX.md、atlas_fgo.db、pokemon.db、garbled_replacements.json)核实角色名称、游戏名称和术语。whisper-corruption-recovery:如果 Whisper 转录内容出现重复循环或静音卡顿,将自动调用。anibon-local-transcription:当 YouTube 没有字幕或自动字幕时,用于提取 16kHz 音频并运行本地 GPU 版 whisper.cpp。
流水线架构
| 0. 降噪与预规范化 | signal_detector.py / anibon/(自动) | garbled_replacements.json + default_mappings.json | 在加载分块/检测信号前,剥除 ASR 说话人标记(>>)、音效标签([เพลง]、[Applause])、音乐符号(♪)和重复卡顿循环,并纠正语音识别的语音漂移。 |
| 0.5 知识自读取 | anibon/knowledge_reader.py(自动) | signals.json + references/*.md + DBs → entity_glossary.json | 自行读取与信号匹配的领域 Markdown 参考资料,查询本地 SQLite 数据库(atlas_fgo.db、pokemon.db),并构建经过核实、按分块筛选的实体术语表。可通过 --no-knowledge-reader 跳过。 |
| 1. 准备与分块 | prepare_video.py | YouTube URL → raw_transcript.json、chunks/*.txt | 下载字幕,并将音频/转录内容切分为相互重叠的分块。 |
| 1.5 直播聊天与情绪检测 | anibon/parity_gates.py(analyze_555.py) | livechat/ → mood_555.json | 自动检测 555/笑声爆发,并对分块的情绪/语气分类(*_PULSE、HOT、WARM、QUIET),为提示词提供语气指导。 |
| 2. 主题分段(第一轮) | process_chunks_local.py | chunks/、signals.json、分镜关键帧(--multimodal-chunks) | 通过本地 LLM/VLM,结合视觉事实依据和情绪语气提示,检测主题切换/延续并生成时间戳。 |
| 2.5 视觉事实核验(可选) | anibon/vision_verify.py(--vision-verify) | video_360p.mp4 + 模糊时间戳 | 在第二轮组装前,通过本地视觉模型检查屏幕视频帧,核实含义模糊的专有名词或 [?] 标签。 |
| 3. 摘要与组装(第二轮) | anibon/summarizer.py(自动) | all_timestamps.txt → anibon_timestamps.md | 将时间戳归类为连贯的宏观主题部分(通常为 4–6 个部分),并对齐转场提示(find_best_boundary)。 |
| 4. 错误转录收集器与 Whisper 事实核验 | whisper_dispatcher.py(自动,在处理后运行) | garbled_notes_raw/ → garbled_notes.json → garbled_replacements.json | 摘要完成后自动运行:即时截取音频片段,通过本地 whisper.cpp 转录语音事实依据,并自动扩充共享词典。 |
| 5. 确定性一致性检查 | anibon/parity_gates.py(自动,在处理后运行) | all_timestamps.txt、anibon_timestamps.md | 执行前置层级的一致性检查:audit_gaps.py(强制确保间隔不超过 10m)和 check_sections.py(审查字节大小和 ASR 错误转录模式;仅生成报告)。 |
模块化库架构(scripts/anibon/)
anibon/multimodal.py:故事板幻灯片解包、自适应场景切换与评估批次关键帧选择器(每个分块 1–16 帧、16×9 RGB 辅助缓存、泰语指示性提示词固定)、兼容 OpenAI 的多图像负载构建,以及 VLM 执行。anibon/knowledge_reader.py:从signals.json自动发现领域知识、正则表达式表格/项目符号实体解析器、SQLite 数据库增强器(atlas_fgo.db、pokemon.db),以及entity_glossary.json生成器。anibon/timestamps.py:标签标准化(TAG_REMAP)、时间戳行清理、冲突防护(间隔 $\ge 45\text{s}$)、窗口验证。anibon/lmstudio.py:LM Studio 和兼容 OpenAI 的客户端(TokenMe、vLLM、Ollama)、模型解析(默认使用gemma-4-12b-it-qat@q4_k_xl或unsloth/gemma-4-26b-a4b-it@q2_k_x)、文本补全、Bearer 身份验证、绕过 Cloudflare,以及多模态 Vision API(适用于 Gemma 4 Vision、Qwen-VL 的image_url数据 URI)。anibon/websearch.py:轻量级 DuckDuckGo 搜索,使用本地 JSON 缓存(websearch_cache.json)零成本验证实体。anibon/prompts.py:递归滚动摘要和分组批处理提示词、World Identity 参考注入,以及搜索/视觉上下文块。anibon/summarizer.py:Pass 2 本地摘要器,支持语义和时间顺序去重,以及宏观主题部分组装(通常为 4–6 个部分)。anibon/state.py:检查点持久化(anibon_timestamper_state.json)、分块发现,以及多模态加载器(LiveChat、555 mood、activity)。
多层反幻觉与验证架构(4 层防御)
本地较小的大模型(例如 12B–27B)缺乏前沿模型广博的参数化世界知识,因此容易根据读音猜测并编造英文标题。anibon-timestamper-local 实现了确定性的 4 层防御管线:
-
第 1 层:元数据与标题信号摄取(
signal_detector.py)- 通过
extract_metadata_signals()从info.json摄取视频标题、描述和标签。 - 通过
discover_reference_games()动态发现anibon-world-identity/references/*.md中的所有参考游戏。 - 在推理前锚定直播上下文,防止将特定游戏误认为通用类别。
- 通过
-
第 2 层:推理前缓冲区标准化与清理(
state.py)- 在
load_chunk_file()加载分块时,自动清理 ASR 说话人漂移(ปู่บอท、ลุงบอท、ปู่โบต→ปู่โบ๊ต)。 - 在将文本传递给 LLM 提示词前,应用
default_mappings.json中的语音映射。
- 在
-
第 3 层:反猜测与不变量提示词指令(
prompts.py)- 强制执行
STREAMER IDENTITY不变量:主播只能是'ปู่โบ๊ต' (Boat)。绝不写作'ปู่บอท'、'ลุงบอท'或'ปู่โบต'。 - 强制执行
ANTI-GUESSING CONSTRAINT:绝不随意将泰语语音借词翻译成新的英文拼写。如果未在VERIFIED DOMAIN ENTITIES中找到,则使用泰语音译或用泰语描述动作。绝不编造新的英文专有名词。 - 强制执行
POKÉMON NAMING RULE:Pokémon 实体必须严格遵循'泰语名称 (English Name)'格式(先写泰国社群/官方名称,再在括号中写英文名称)。
- 强制执行
-
第 4 层:第 5 阶段确定性自动清理(
process_chunks_local.py)- 在 Pass 2 摘要组装期间自动执行
sanitize_and_audit_timestamps()。 - 确定性修正残留的说话人拼写错误和规范词典模式(
garbled_replacements.json,例如Archen→Arcane、Victor→Viktor)。 - 根据白名单标签和术语表审查时间戳行中的未验证大写拉丁词,并对可疑幻觉发出确定性审查警告。
- 在 Pass 2 摘要组装期间自动执行
执行模式
模式 1:递归滚动摘要(--mode recursive,默认且推荐)
Pu Boat 的讨论遵循自然的内容流,而非固定的时间边界。一个话题可能持续 3 分钟,也可能持续 25 分钟。
SAME_TOPIC:如果 Chunk $N$ 延续当前话题,则将其合并到滚动摘要中,不输出时间戳(0 个时间戳)。- 长篇谈话/新闻例外:如果独白或社会议题讨论跨越多个 chunk(超过 8–10 分钟)且没有时间戳,模型必须提取一个独立的子角度或具体的政策批评(1 个时间戳),而不是留下长时间空白。
- 无界链式摘要不变式:
build_recursive_prompt()和状态持久化(anibon_timestamper_state.json、recursive_outputs/chunk_XX.json)必须传递完整的rolling_summary和chunk_summary文本,不得进行硬编码的字符截断,以免多 chunk 的话题上下文被截断。
TOPIC_SHIFT/精彩集锦:话题转变时,刷新此前的上下文并标记该转变。默认输出 1 个时间戳,每个 chunk 最多输出 2 个(间隔 $\ge$45 秒)。- 主题分段分组:第二轮摘要器将时间戳按总体主题类别分组为连续的整数编号分段(
ส่วนที่ 1, 2, 3...,通常共 4–6 段),并使用find_best_boundary将分段边界对齐到主播的转场提示(例如สรุป... และเตรียมเปลี่ยนไปคุย、เตรียมเริ่มเล่นเกม)。不允许过度拆分成 10–18 个微型分段;连贯的话题讨论(例如完整的系列评测或游戏环节)应保持在同一段中,方便观众浏览。连续的同一游戏刷任务内容会在 10 分钟内合并;谈话/新闻子话题则使用 4 分钟的时间窗口。
模式 2:固定窗口分组(--mode group,替代方案)
每组结合 4 个 chunk(约 16–20 分钟),并采用按时间顺序排列的循环断点和冲突防护。
核心流水线与快速参考
快速命令
0. 降噪与预归一化(自动)
在进行任何信号检测或大模型分析之前,clean_transcript_noise() 会自动清理 ASR 伪影(>>、[เพลง]、♪、字符重复),并应用来自 garbled_replacements.json 和 default_mappings.json 的 2000 多条 Whisper 真实内容映射。无需手动调用。
0.5 知识自读取与实体词汇表(阶段 0.5,自动)
处理 chunk 之前,run_knowledge_discovery() 会检查 signals.json,自行读取 anibon-world-identity/references/*.md 中匹配的 Markdown 参考资料,查询本地数据库(atlas_fgo.db、pokemon.db),并生成 <workspace>/entity_glossary.json。Chunk 提示词会自动将相关实体筛选后(上限约为 300 个 token)加入提示词上下文。
- 若要绕过实体词汇表发现:传入
--no-knowledge-reader。
1. 下载与分块(如果 chunks/chunk_00.txt 存在则跳过)
macOS / Linux:
python3 scripts/prepare_video.py "https://www.youtube.com/watch?v=<VIDEO_ID>" \
--workspace "~/youtube_<VIDEO_ID>_workspace" \
--format txt --block 300 --overlap 30
Windows(PowerShell / 命令提示符):
python scripts\prepare_video.py "https://www.youtube.com/watch?v=<VIDEO_ID>" --workspace "$HOME\youtube_<VIDEO_ID>_workspace" --format txt --block 300 --overlap 30
2. 直接运行 Timestamper(前台)
macOS / Linux:
python3 -X utf8 scripts/process_chunks_local.py "~/youtube_<VIDEO_ID>_workspace" \
--mode recursive --lang th
Windows(PowerShell):
python -X utf8 scripts\process_chunks_local.py "$HOME\youtube_<VIDEO_ID>_workspace" --mode recursive --lang th
提示
单条评论字节数限制(
--byte-cap): 如果需要确保每个分段严格少于 3,500 字节,以便粘贴到 YouTube 单条评论中,请传入--byte-cap。默认情况下会禁用字节数限制,以保留连贯的宏观主题分组(4–6 段)。
2.1 流水线内视觉验证(可选)
在第二轮摘要之前,使用本地视觉模型检查屏幕视频帧,以确认含糊不清或模糊的时间戳(指示代词、缺失的游戏名称、[?] 标记):
python -X utf8 scripts\process_chunks_local.py "$HOME\youtube_<VIDEO_ID>_workspace" --mode recursive --lang th --vision-verify
2.2 使用故事板关键帧进行多模态分块分析(默认:启用)
在第一遍处理中,将每个分块的高分辨率故事板关键帧直接采样到 VLM(例如 Gemma 4 12B Vision、Qwen-VL)中,同时提供转录文本。默认通过 config.json("multimodal_chunks": true)启用。可避免错误归属游戏标题,并实时为事件/章节字幕提供依据:
# Enabled by default (Adaptive Scene-Change Mode):
python3 scripts/process_chunks_local.py ~/youtube_<VIDEO_ID>_workspace --mode recursive --lang th
# To tune visual sensitivity or evaluation batch size:
python3 scripts/process_chunks_local.py ~/youtube_<VIDEO_ID>_workspace \
--eval-batch-size 8192 \
--max-chunk-frames 16 \
--scene-delta-threshold 0.06
# To disable adaptive scene deduplication (fallback to legacy fixed 3-5 frames):
python3 scripts/process_chunks_local.py ~/youtube_<VIDEO_ID>_workspace --no-scene-dedup
# To disable all multimodal analysis and run in text-only mode:
python3 scripts/process_chunks_local.py ~/youtube_<VIDEO_ID>_workspace --no-multimodal
自适应场景变化关键帧选择器(scene_dedup=True):
- 静态画面:将静态的谈话头像/等待画面减少到 1–2 帧(节省物理批次计算量和提示词 token)。
- 动态动作:每当发生视觉场景转换时,自动将每个 5 分钟分块的帧数扩展到最多 16 帧,并受
--eval-batch-size(默认8192)限制。 - 泰语指示线索定位:当 Pu Boat 使用指示性表达(
"ดูอันนี้"、"ในจอ"、"ตรงนี้"、"[?]")时,定位精确的视觉帧。 - RGB 旁路缓存:自动将 16×9、432 字节的缩采样缓冲区(
tile_XXXXXX.rgb)与.jpg瓦片一同持久化,避免在比较和重新运行时重复产生ffmpeg子进程开销。 - 清空后重新运行
--no-resume:传入--no-resume时,会自动删除过期的recursive_outputs/chunk_*.json文件,确保干净执行,不受残留分块的影响。
在保留先前结果的同时重新运行现有工作区(例如:从纯文本切换到多模态):
cd ~/youtube_<VIDEO_ID>_workspace
cp -a . ~/youtube_<VIDEO_ID>_workspace_text_backup
cp anibon_timestamps.md anibon_timestamps_text_only.md
cp all_timestamps.txt all_timestamps_text_only.txt
mv recursive_outputs recursive_outputs_text_only && mkdir -p recursive_outputs
cp anibon_timestamper_state.json anibon_timestamper_state_text_only.json
rm -f anibon_timestamper_state.json all_timestamps.txt anibon_timestamps.md timestamper.pid
3. 分离式后台启动(3 类操作系统)
在后台分离运行推理,避免 Agent 会话或超时终止运行。
macOS(Zsh / Bash):
./scripts/launch_local.zsh ~/youtube_<VIDEO_ID>_workspace 100.115.25.30 auto th
Linux(Bash):
./scripts/launch_local.sh ~/youtube_<VIDEO_ID>_workspace 100.115.25.30 auto th
Windows(PowerShell):
powershell -ExecutionPolicy Bypass -File "scripts\launch_local.ps1" -Workspace "$HOME\youtube_<VIDEO_ID>_workspace" -Endpoint "100.115.25.30"
Windows(CMD 批处理):
scripts\launch_local.bat "%USERPROFILE%\youtube_<VIDEO_ID>_workspace" 100.115.25.30 auto th
说明
端点自动探测与回退规则:所有运行器和 Python 客户端(
anibon.lmstudio.resolve_endpoint())都会自动通过 1.0s TCP 套接字测试探测http://100.115.25.30:1234。如果无法连接(表示正在本地主机上执行),它们会立即、安全地回退到http://127.0.0.1:1234。
提示
远程/TokenMe 端点支持: 通过在环境中传入
TOKENME_API_KEY(或LM_API_KEY)或使用--api-key,即可指定 TokenMe 等远程 OpenAI 兼容端点(--endpoint https://api.tokenme.limited/v1或api.tokenme.limited)。
- 客户端会设置标准的
Authorization: Bearer <KEY>和浏览器User-Agent标头,以绕过 Cloudflare WAF 代码 1010。nvidia/Gemma-4-26B-A4B-NVFP4等远程模型开箱即支持通过 base64image_url载荷进行多模态视觉检查。
提示
配置(
config.json和--config): 数值常量、token 限制、超时、温度、剪枝边界和默认端点由skills/anibon-timestamper-local/config.json管理,并由anibon/config.py自动加载,无需任何依赖。
- 密钥(如
TOKENME_API_KEY或LM_API_KEY)应放在.env中(该文件已加入 gitignore)。- 若要针对特定运行或硬件配置自定义参数,请复制或创建 JSON 配置文件,并传入
--config /path/to/config.json(或使用向后兼容的--env-file)。- 环境变量(
ANIBON_CHUNK_MAX_TOKENS、ANIBON_TEMPERATURE等)会无缝覆盖config.json中的值,无需修改文件。
4. 含糊语音收集器与 Whisper 真实标注(自动后处理)
anibon_timestamps.md 摘要汇总完成后,process_chunks_local.py 会自动检查 <workspace>/garbled_notes_raw/ 中残留的语音识别错乱内容,并调用 whisper_dispatcher.py,使用本地 whisper.cpp 切分音频并更新 garbled_replacements.json。
- 若要传入视频 URL,以便即时切分流媒体而无需下载完整音频:
python3 -X utf8 scripts/process_chunks_local.py "~/youtube_<VIDEO_ID>_workspace" \ --video-url "https://www.youtube.com/watch?v=<VIDEO_ID>" - 若要禁用自动含糊语音收集:
python3 -X utf8 scripts/process_chunks_local.py "~/youtube_<VIDEO_ID>_workspace" \ --no-garbled-collector - 若要随时手动运行含糊语音收集:
python3 scripts/whisper_dispatcher.py ~/youtube_<VIDEO_ID>_workspace \ --video-url "https://www.youtube.com/watch?v=<VIDEO_ID>" --verbose python3 ../cleaning-auto-transcripts/scripts/update_garbled_dictionary.py \ --from-notes ~/youtube_<VIDEO_ID>_workspace/garbled_notes.json \ --workspace ~/youtube_<VIDEO_ID>_workspace
5. 世界身份与事实核查审计(强制步骤)
生成 all_timestamps.txt 和 anibon_timestamps.md 后立即执行:
- 加载
anibon-world-identity:根据本地知识库扫描所有生成的时间戳标题和描述:- FGO 从者/职阶:查询
atlas_fgo.db(不要将 Ashiya Douman 与 Ascalon/Asclepius 混淆)。 - 宝可梦实体:查询
pokemon.db,并优先采用泰国社群/官方名称(例如แบกซ์แคลิเบอร์ (Baxcalibur))。 - 动画/抽卡游戏标题:根据
references/*.md核实(例如Chaos_Zero_Nightmare.md、Genshin_Impact.md、Honkai_Star_Rail.md、Wuthering_Waves.md)。 - 新竞技游戏(Deadlock 等):通过网络搜索或补丁说明交叉核对英雄名称(Baba / Baba Yaga、Celeste、Abrams)。
- FGO 从者/职阶:查询
- 修正实体:直接在
anibon_timestamps.md中修正语音识别偏差、误听标题或大模型幻觉。 - 保存知识:
- 将已确认的语音识别偏差模式(例如
เคราสเซียร์นี้แม่→Chaos Zero Nightmare、อัชเฉร้อน→อาชิยะ โดมัน)添加到根目录和技能资源中的garbled_replacements.json。 - 将新核实的系列/角色添加到
anibon-world-identity/references/。
- 将已确认的语音识别偏差模式(例如
规范与反合理化
本地处理铁律
NEVER TIME-LOCK TOPICS TO ARBITRARY MINUTE BOUNDARIES
直播内容自然流动。使用递归滚动摘要状态机来检测真正的内容转换,而不是每隔 $N$ 分钟就生成一个时间戳。
合理化说辞对照表
| 合理化说辞 | 实际情况 | 应对措施 |
|---|---|---|
| “单个分块运行起来更快。” | 会生成 35 个以上的微型时间戳,让评论区显得杂乱。 | 使用带滚动摘要的 --mode recursive。 |
| “我可以像 [วิเคราะห์] 这样自创标签,因为它符合内容。” | 前沿基准测试会拒绝非标准标签;评论解析器也会因此失效。 | 规范化器会自动将 [วิเคราะห์] 映射为 [Talk]。 |
| “我直接用一个提示词总结整段 3 小时的转录文本。” | 超出上下文限制,并降低 12B 模型的实体召回能力。 | 顺序滚动状态机可将提示词控制在 2k 个 token 以下。 |
| “我们写个自定义 Python 脚本来加快处理。” | 临时脚本会破坏状态跟踪、恢复逻辑和编码。 | 严格使用 process_chunks_local.py 参数。 |
| “时间戳看起来够好了,不用检查世界身份。” | 会虚构截止日期之后的游戏,或使用未转换为泰语转写的纯英文宝可梦名称。 | 最终交付前必须严格通过 /anibon-world-identity 检查。 |
危险信号——停止并重置
- 未根据
/anibon-world-identity核实系列实体,就向用户交付时间戳。 - 转录恢复流程尚未 100% 完成并验证(
whisper-corruption-recovery),就尝试运行时间戳生成器。 - 2 小时直播的输出文件包含 35 个以上的时间戳(微型时间戳症状)。
- 输出标签包含非白名单词语(
[วิเคราะห์]、[ชำแหละ]、[เปิดตัว])。 - 将话题过度拆分成过多的微型部分(单场直播超过 6–8 部分)。观众导航和主题连贯性优先于人为设定的评论字节数限制。
- 脚本因
UnicodeEncodeError: 'charmap'崩溃(忘记使用-X utf8)。 - 结束分块被标记为续接时,遗漏了结尾部分。务必核实最后 5 分钟是否有结束时间戳。
- 新游戏启动后,仍将终局机制(“หอรี”、“เฟ้อกว่าเวเนซุเอลา”)归到之前讨论的游戏上。
- 仅因预训练中对某个系列的关联,就虚构未提及的背景设定/章节标题(例如 “Lostbelt”)。
- 将带自定义头像的观众打赏提醒标记为实际的产品测评或手办展示(
[Talk] 展示手办)。
直播结束 / 收尾不变量
在 --mode recursive 模式下,长时间连续的游戏内容或收尾环节不得让 is_continuation=True 吞掉直播收尾。
必须始终检查转录文本最后 5 分钟,查找结束语标记(ขอบคุณครับ、ลงไลฟ์、ราตรีสวัสดิ์、เจอกัน、บ๊ายบาย),并输出:
- SuperChat / 生日祝福:读取捐赠者名单、SuperChat 和会员生日祝福时使用
[Donation](HH:MM:SS - [Donation] ปู่โบ๊ตขอบคุณผู้ชม ผู้สนับสนุนโดเนท และอวยพรวันเกิดสมาชิก)。 - 结束告别:最终总结发言和下次直播预告使用
[Ending](HH:MM:SS - [Ending] ปู่โบ๊ตกล่าวปิดสตรีม...)。 - 固定直播安排防护规则:Pu Boat 经常安排 22:00 的特摄直播(“ไลฟ์โทกุ”“คอนเทนต์โทกุ 3 เรื่อง 3 รส”)。语音识别中的语音转写错误(
โทกกู、ทั่วกุ、คอนเทนทุกคึ)必须严格映射为โทคุซัตสึ (Tokusatsu),绝不能映射为“Tokyo Ghoul”。
宏观主题分段不变量(不得因 3,500 字节上限而过度拆分)
时间戳必须严格按宽泛、连贯的宏观主题分段(长直播通常分为 4–6 个部分)。
优先考虑观众浏览和主题连贯性:相关讨论(例如完整的系列评述、媒体观看会或游戏环节)应合并在一个部分中,而不是为了适配单条评论的字节数限制而随意切分成 10–18 个微型部分。
默认情况下,assemble_parts() 和 run_local_summarizer_pass() 不会强制执行字节数上限。enforce_byte_cap() 仅作为可选工具保留,只有在明确要求拆分单条评论时才使用。
核心精选时间戳选择不变量
从长时间直播(4–8 小时)生成时间戳时,请遵循以下操作标准:
- 主要输出重点:将精选精华版作为主要结果呈现(7–8 小时的直播约 40–60 个时间戳,或每个宏观主题部分约 8–15 个时间戳)。
- 自动精简精华内容(
prune_essential):对于生成超过 60 个时间戳的直播,finalize_and_assemble_timestamps()会自动调用本地模型,提炼出约 40–60 个核心节点,包括关键节点、新闻、游戏里程碑和核心结论。该流程会严格确保时间戳内容与原始时间戳逐字匹配、保留开场和[Ending]时间戳,并在 LLM 调用失败时平稳回退。
- 自动精简精华内容(
- 精华内容筛选标准:
- 主要话题的开始或转折点(话题转换 / 转折)。
- 官方新闻、公告、发行信息或统计数据(官方新闻、发行信息、数据)。
- 深入分析结论和核心要点(深入分析与核心要点)。
- 关键游戏里程碑(教程开始、探索新角色 / 技能、关键道具制作、Boss 出现、精彩战斗、胜利 / 失败)。
- 直播收尾和结束致谢(直播收尾)。
- 精简零碎时间戳:
- 精简短时间内重复同一谈话要点的零碎时间戳(例如,主播花 5–10 分钟分析某个观点时,不要每 2 分钟就添加一个时间戳)。
- 精简不会影响核心叙事的闲聊、无关紧要的玩笑或插科打诨。
- 双文件存储:
- 将精选精华时间戳文件保存为
anibon_timestamps_essential.md(或anibon_timestamps.md)。 - 保留完整、按时间顺序排列的时间戳日志至
anibon_timestamps_full.md(以及all_timestamps.txt),供参考和归档检索。
- 将精选精华时间戳文件保存为
宏观主题边界对齐不变量
主要领域 / 主题转换(例如泰国政治 → 动漫 / 系列评述、游戏 → SuperChat 问答)不得以 1–4 个残留时间戳开头,这些时间戳属于前一个无关主题部分的末尾。
assemble_parts() 会使用 find_best_boundary() 自动将分段边界对齐到转换标记(สรุปการพูดคุย... และเตรียมเปลี่ยนไปคุย、เตรียมเริ่มเล่นเกม、เตรียมเข้าสู่ช่วง)。这样可以确保主题分组整洁清晰,方便观众浏览,避免出现残留内容。
时间戳开场语与类比归属不变量
- 开场锚点:时间戳的起始时间必须锚定主题的开场句。绝不要将时间戳标在关键词于句中出现时或之后,确保点击链接的观众不会错过早在 10–20 秒前说出的关键背景。
- 顺带提及的类比规则:绝不要把仅在一带而过的 1–2 句话中提及的作品、人物或地点名称,作为类比或修辞比较,放在时间戳的主标题中。
- 错误示例:
Comparing standards... with Frieren(当主题是批评《One Punch Man》第 3 季,而 Frieren 只在一句对比性的话中被提及时)。 - 正确示例:
Critiquing One Punch Man Season 3 and J.C.Staff's 'watchable' standard (noted that it cannot compare to major productions like Frieren)。
- 错误示例:
世界身份核验不变量
在对所有专有名词、游戏标题和角色名称执行 anibon-world-identity 核验之前,绝不要交付最终时间戳输出。Thai Whisper 的输出是语音转写;本地 LLM 在听到不熟悉的游戏名称(CZN、Deadlock)时,会臆造知名游戏名称(Genshin、Dota)。本地参考资料(references/*.md)和卡片/实体数据库(atlas_fgo.db、pokemon.db)的优先级高于模型记忆。process_chunks_local.py 会在完成后,自动根据 <workspace>/entity_glossary.json 核验生成的 anibon_timestamps.md,并替换已确认的语音变体。
直播标题词条锚定不变量
直播自身 YouTube 元数据(info.json 的标题、描述)中的专有名词、模组名称和系列标题是事实锚点。
- 标题词条优先:当输出的时间戳描述中包含某实体的语音近似词或截短形式,而该实体出现在直播标题中时(例如 ASR 转写为
Vity,而标题明确写着Verity,或Nania与Narnia),处理流程必须确定性地匹配到标题中的规范拼写。 - 标题与 ASR 语音偏移:直播标题反映了主播有意设定的直播主题。视频中的 ASR 语音偏移绝不能覆盖或降低标题中已核实实体的准确性。
常见错误与故障排查
-
LM Studio 模型卸载:
- 症状:LM Studio 卸载 Gemma 4 并加载另一个模型,导致停顿 60 秒。
- 解决方法:保留
--model auto。resolve_model会自动锁定当前内存中的活动模型。
-
Gemma 4 思考令牌陷阱:
- 症状:输出时间戳为空或被截断。
- 原因:模型将令牌预算用在了
reasoning_content中。 - 解决方法:内置系统提示词将思考限制在少于 2 句话;正则提取器会直接从 content 或 reasoning 中提取结构化 JSON。
-
ASR 语音识别偏差:
- 症状:出现“นครโตะ”这类名称,而不是“Naucrate (นอคราเต้)”。
- 解决方法:
process_chunks_local.py会加载resources/default_mappings.json,并在生成提示词前运行 TF-IDF 信号检测。
-
视觉提示词缺少多模态投影器(
mmproj):- 症状:图像验证或分镜检查时,回复 "I cannot see an image or video"。
- 原因:模型 GGUF 包含多模态提示词令牌,但加载到 LM Studio /
llama.cpp时未搭配其对应的mmproj-*.gguf文件。 - 解决方法:在 LM Studio 模型设置中明确指定
mmproj文件,或使用llama-server --mmproj,也可以切换到统一的视觉模型,例如Qwen2.5-VL-7B。
-
使用修改后/恢复后的转录文本重新运行:
- 症状:时间戳工具在 1 秒内完成,并显示
[skip] chunk_XX (already processed)。 - 原因:脚本会将每个分块的响应缓存到
<workspace>/recursive_outputs/chunk_XX.json以及anibon_timestamper_state.json中。 - 解决方法:传入
--no-resume,并删除recursive_outputs/和anibon_timestamper_state.json。
- 症状:时间戳工具在 1 秒内完成,并显示
-
结尾被连续处理陷阱吞掉:
- 症状:输出时间戳在视频结束前 30–60 分钟停止,遗漏主播的结束语。
- 原因:递归滚动模式中的
is_continuation=True将最后一场直播当作未中断的游戏环节,丢弃了结尾部分。 - 解决方法:结尾不变式 — 最后 5 分钟必须始终扫描
[Ending]/ 告别时间戳。
-
Storyboard MHTML 使用 WebP Content-Type:
- 症状:尽管已下载
storyboard.mhtml(20MB 以上),prepare_storyboard_slides()仍提取出 0 张幻灯片。 - 原因:YouTube 的
yt-dlp经常将多部分分镜幻灯片打包为Content-type: image/webp(RIFF...WEBP),而不是image/jpeg。 - 解决方法:
anibon/multimodal.py会检查image/jpeg和image/webp。FFmpeg 可从任一格式裁剪图块并输出高分辨率 JPEG,无需 PIL。
- 症状:尽管已下载
-
yt-dlpStoryboard--skip-download陷阱与空幻灯片目录:- 症状:
download_storyboard()以 0 退出,但没有生成.mhtml文件;或者prepare_storyboard_slides()返回空的slides_clean/目录。 - 原因:与
--write-auto-subs --skip-download不同,storyboard(-f sb0/sb1/sb2/sb3)是主要格式;传入--skip-download会完全跳过它的下载。若只检查clean_dir.exists(),而不使用 glob 查找slide_*.jpg,也会误判为空目录。 - 解决方法:使用
-f sb0/sb1/sb2/sb3下载时,绝不要传入--skip-download;并始终验证clean_dir.is_dir() and any(clean_dir.glob("slide_*.jpg"))。
- 症状:
-
多模态端点缺少
/v1/chat/completions(KeyError: 'choices'):- 症状:向
call_multimodal()传入裸http://host:1234端点时,会引发KeyError: 'choices'。 - 原因:
urllib.request请求的是 LM Studio 根端点,而不是/v1/chat/completions。 - 解决方法:在
call_multimodal()中始终规范化url;如果其中尚未包含/v1/chat/completions,则追加该路径。
- 症状:向