mcpField
A
anibon-timestamper-local

anibon-timestamper-local

github.com/zenithth创意与媒体172 次安装今天更新
代码仓库

关于 anibon-timestamper-local

用于将 YouTube 长直播整理为时间戳和主题摘要的本地处理技能。它支持递归或分组分块处理,并结合转录清理、本地多模态分析与校验步骤。

主要功能

  1. 01递归与分组处理模式
  2. 02转录清理和实体词表生成
  3. 03本地文本与视觉模型分析
  4. 04按主题归组时间戳
  5. 05时间戳审计与规范化

适用场景

  1. 01为长直播生成章节时间戳
  2. 02使用本地模型总结直播
  3. 03根据画面和参考资料核验模糊主题
  4. 04发布前规范转录错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/zenithth/anibon-stream-synthesis --skill anibon-timestamper-local

安装后在 Claude Code 中输入/anibon-timestamper-local确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

config.json
references/
timestamper-handoff.md
scripts/
launch_local.bat
launch_local.ps1
launch_local.sh
launch_local.zsh
prepare_video.py
process_chunks_local.py
signal_detector.py
scripts/anibon/
__init__.py
config.py
domain_db.py
knowledge_reader.py
lmstudio.py
multimodal.py
parity_gates.py
phonetic_bridge.py
prompts.py
state.py
summarizer.py
timestamps.py
topic_scanner.py
transcript_source.py
vision_verify.py
world_sanitizer.py
tests/
__init__.py
test_config.py
test_domain_db.py
test_knowledge_reader.py
test_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. 第 1 层:元数据与标题信号摄取(signal_detector.py)

    • 通过 extract_metadata_signals() 从 info.json 摄取视频标题、描述和标签。
    • 通过 discover_reference_games() 动态发现 anibon-world-identity/references/*.md 中的所有参考游戏。
    • 在推理前锚定直播上下文,防止将特定游戏误认为通用类别。
  2. 第 2 层:推理前缓冲区标准化与清理(state.py)

    • 在 load_chunk_file() 加载分块时,自动清理 ASR 说话人漂移(ปู่บอท、ลุงบอท、ปู่โบต → ปู่โบ๊ต)。
    • 在将文本传递给 LLM 提示词前,应用 default_mappings.json 中的语音映射。
  3. 第 3 层:反猜测与不变量提示词指令(prompts.py)

    • 强制执行 STREAMER IDENTITY 不变量:主播只能是 'ปู่โบ๊ต' (Boat)。绝不写作 'ปู่บอท'、'ลุงบอท' 或 'ปู่โบต'。
    • 强制执行 ANTI-GUESSING CONSTRAINT:绝不随意将泰语语音借词翻译成新的英文拼写。如果未在 VERIFIED DOMAIN ENTITIES 中找到,则使用泰语音译或用泰语描述动作。绝不编造新的英文专有名词。
    • 强制执行 POKÉMON NAMING RULE:Pokémon 实体必须严格遵循 '泰语名称 (English Name)' 格式(先写泰国社群/官方名称,再在括号中写英文名称)。
  4. 第 4 层:第 5 阶段确定性自动清理(process_chunks_local.py)

    • 在 Pass 2 摘要组装期间自动执行 sanitize_and_audit_timestamps()。
    • 确定性修正残留的说话人拼写错误和规范词典模式(garbled_replacements.json,例如 Archen → Arcane、Victor → Viktor)。
    • 根据白名单标签和术语表审查时间戳行中的未验证大写拉丁词,并对可疑幻觉发出确定性审查警告。

执行模式

模式 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 等远程模型开箱即支持通过 base64 image_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 后立即执行:

  1. 加载 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)。
  2. 修正实体:直接在 anibon_timestamps.md 中修正语音识别偏差、误听标题或大模型幻觉。
  3. 保存知识:
    • 将已确认的语音识别偏差模式(例如 เคราสเซียร์นี้แม่ → 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 分钟,查找结束语标记(ขอบคุณครับ、ลงไลฟ์、ราตรีสวัสดิ์、เจอกัน、บ๊ายบาย),并输出:

  1. SuperChat / 生日祝福:读取捐赠者名单、SuperChat 和会员生日祝福时使用 [Donation](HH:MM:SS - [Donation] ปู่โบ๊ตขอบคุณผู้ชม ผู้สนับสนุนโดเนท และอวยพรวันเกิดสมาชิก)。
  2. 结束告别:最终总结发言和下次直播预告使用 [Ending](HH:MM:SS - [Ending] ปู่โบ๊ตกล่าวปิดสตรีม...)。
  3. 固定直播安排防护规则: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 小时)生成时间戳时,请遵循以下操作标准:

  1. 主要输出重点:将精选精华版作为主要结果呈现(7–8 小时的直播约 40–60 个时间戳,或每个宏观主题部分约 8–15 个时间戳)。
    • 自动精简精华内容(prune_essential):对于生成超过 60 个时间戳的直播,finalize_and_assemble_timestamps() 会自动调用本地模型,提炼出约 40–60 个核心节点,包括关键节点、新闻、游戏里程碑和核心结论。该流程会严格确保时间戳内容与原始时间戳逐字匹配、保留开场和 [Ending] 时间戳,并在 LLM 调用失败时平稳回退。
  2. 精华内容筛选标准:
    • 主要话题的开始或转折点(话题转换 / 转折)。
    • 官方新闻、公告、发行信息或统计数据(官方新闻、发行信息、数据)。
    • 深入分析结论和核心要点(深入分析与核心要点)。
    • 关键游戏里程碑(教程开始、探索新角色 / 技能、关键道具制作、Boss 出现、精彩战斗、胜利 / 失败)。
    • 直播收尾和结束致谢(直播收尾)。
  3. 精简零碎时间戳:
    • 精简短时间内重复同一谈话要点的零碎时间戳(例如,主播花 5–10 分钟分析某个观点时,不要每 2 分钟就添加一个时间戳)。
    • 精简不会影响核心叙事的闲聊、无关紧要的玩笑或插科打诨。
  4. 双文件存储:
    • 将精选精华时间戳文件保存为 anibon_timestamps_essential.md(或 anibon_timestamps.md)。
    • 保留完整、按时间顺序排列的时间戳日志至 anibon_timestamps_full.md(以及 all_timestamps.txt),供参考和归档检索。
宏观主题边界对齐不变量

主要领域 / 主题转换(例如泰国政治 → 动漫 / 系列评述、游戏 → SuperChat 问答)不得以 1–4 个残留时间戳开头,这些时间戳属于前一个无关主题部分的末尾。 assemble_parts() 会使用 find_best_boundary() 自动将分段边界对齐到转换标记(สรุปการพูดคุย... และเตรียมเปลี่ยนไปคุย、เตรียมเริ่มเล่นเกม、เตรียมเข้าสู่ช่วง)。这样可以确保主题分组整洁清晰,方便观众浏览,避免出现残留内容。

时间戳开场语与类比归属不变量
  1. 开场锚点:时间戳的起始时间必须锚定主题的开场句。绝不要将时间戳标在关键词于句中出现时或之后,确保点击链接的观众不会错过早在 10–20 秒前说出的关键背景。
  2. 顺带提及的类比规则:绝不要把仅在一带而过的 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 的标题、描述)中的专有名词、模组名称和系列标题是事实锚点。

  1. 标题词条优先:当输出的时间戳描述中包含某实体的语音近似词或截短形式,而该实体出现在直播标题中时(例如 ASR 转写为 Vity,而标题明确写着 Verity,或 Nania 与 Narnia),处理流程必须确定性地匹配到标题中的规范拼写。
  2. 标题与 ASR 语音偏移:直播标题反映了主播有意设定的直播主题。视频中的 ASR 语音偏移绝不能覆盖或降低标题中已核实实体的准确性。

常见错误与故障排查

  1. LM Studio 模型卸载:

    • 症状:LM Studio 卸载 Gemma 4 并加载另一个模型,导致停顿 60 秒。
    • 解决方法:保留 --model auto。resolve_model 会自动锁定当前内存中的活动模型。
  2. Gemma 4 思考令牌陷阱:

    • 症状:输出时间戳为空或被截断。
    • 原因:模型将令牌预算用在了 reasoning_content 中。
    • 解决方法:内置系统提示词将思考限制在少于 2 句话;正则提取器会直接从 content 或 reasoning 中提取结构化 JSON。
  3. ASR 语音识别偏差:

    • 症状:出现“นครโตะ”这类名称,而不是“Naucrate (นอคราเต้)”。
    • 解决方法:process_chunks_local.py 会加载 resources/default_mappings.json,并在生成提示词前运行 TF-IDF 信号检测。
  4. 视觉提示词缺少多模态投影器(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。
  5. 使用修改后/恢复后的转录文本重新运行:

    • 症状:时间戳工具在 1 秒内完成,并显示 [skip] chunk_XX (already processed)。
    • 原因:脚本会将每个分块的响应缓存到 <workspace>/recursive_outputs/chunk_XX.json 以及 anibon_timestamper_state.json 中。
    • 解决方法:传入 --no-resume,并删除 recursive_outputs/ 和 anibon_timestamper_state.json。
  6. 结尾被连续处理陷阱吞掉:

    • 症状:输出时间戳在视频结束前 30–60 分钟停止,遗漏主播的结束语。
    • 原因:递归滚动模式中的 is_continuation=True 将最后一场直播当作未中断的游戏环节,丢弃了结尾部分。
    • 解决方法:结尾不变式 — 最后 5 分钟必须始终扫描 [Ending] / 告别时间戳。
  7. 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。
  8. yt-dlp Storyboard --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"))。
  9. 多模态端点缺少 /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,则追加该路径。

评论

支持 Markdown