| name | bilibili-content |
| description | extract subtitles and transcribe audio from bilibili videos for structured summarization. use when the user provides a bilibili.com video url, bv id, or asks to summarize, extract, organize, outline, or analyze a b站/bilibili video. prefer official subtitles first, then fall back to authenticated audio download and whisper transcription when subtitles are unavailable. |
Bilibili Content Tool
Extracts content from Bilibili videos: official subtitles first, Whisper transcription as fallback. Output is a transcript file + metadata JSON. Summarization is done by Hermes/AI, not by the scripts.
When to use
Use when the user shares a Bilibili video URL, provides a BV number, or asks to summarize/extract/analyze B站 content.
Pipeline
Always run analyze_bilibili.py as the single entry point.
analyze_bilibili.py
├─ 1. fetch_subtitle.py
│ ├─ success → transcript.txt → Hermes summarizes
│ ├─ API/cookie error → status: failed (do NOT suggest Whisper)
│ ├─ multi-P → status: needs_page_selection → user picks --page N
│ └─ no subtitles + no --flag → status: needs_confirmation → ask user
│ └─ with --whisper/--auto → continue to 2
│ └─ with --force-whisper → skip to 2
├─ 2. fetch_audio_playurl.py
│ ├─ success → continue to 3
│ ├─ multi-P + no --page → error (requires --page N)
│ └─ fail → report phase (cookie/playurl/download/ffmpeg)
└─ 3. transcribe_whisper.py
success → transcript.txt → Hermes summarizes
Error distinction (important)
The script distinguishes three kinds of failures — do NOT confuse them:
| Subtitle result | Script outputs | Hermes should |
|---|
status: "error" | Cookie/API/BV/invalid-page failure | Report phase + message, do NOT suggest Whisper |
is_multi_p: true | Needs page selection | Ask user which P, re-run with --page N |
has_subtitles: false | Genuinely no subtitles | Ask user if they want Whisper (default) or auto-transcribe (--whisper/--auto) |
Prerequisites
Bilibili Cookies (required)
BILIBILI_SESSDATA=your_sessdata_here
BILIBILI_BILI_JCT=your_bili_jct_here
BILIBILI_DEDE_USERID=your_dedeuserid_here
Get from: Browser DevTools → Application → Cookies → bilibili.com
Dependencies
pip install requests python-dotenv openai-whisper
Whisper model downloaded on first use (~466MB) to ~/.hermes/whisper/models/.
Optional: ffmpeg (for audio conversion)
Required for Whisper fallback. The script downloads .m4s and converts to 16kHz mono .wav.
winget install ffmpeg
choco install ffmpeg
Scripts
| Script | Role |
|---|
analyze_bilibili.py | Single entry point. Modes: default (ask), --whisper, --auto, --force-whisper. Also --timestamps, --language, --whisper-language, --page. |
fetch_subtitle.py | Extract official subtitles via Bilibili API. |
fetch_audio_playurl.py | Download audio stream via playurl API. |
transcribe_whisper.py | Transcribe downloaded audio with Whisper. |
Usage Strategy
| Scenario | Recommended Mode | Rationale |
|---|
| 普通短视频、快速浏览 | 默认 (无 flag) | 字幕优先,最快最省 |
| 技术教程、课程、项目榜 | --verify-subtitle | B站 AI 字幕常错位,检测后决定是否 Whisper |
| 字幕明显错位/内容重要 | --force-whisper | 跳过字幕,直接从音频转写 |
| 多 P 课程 | --page N --verify-subtitle | 选指定分P + 校验 |
| 想完全省心 | --auto --verify-subtitle | 字幕→Whisper 自动兜底 + 检测 |
Subtitle verification
When --verify-subtitle is active, the script checks for:
- 歌词特征 — ♪/♫ 符号或大量短重复句
- 内容-标题不匹配 — 技术类标题但字幕无任何技术关键词
- 字幕过短 — 明显少于正常内容量
If suspicious, returns status: subtitle_suspicious with reason and suggests --force-whisper.
Usage
SKILL_DIR = /d/AI/Hermes/skills/media/bilibili-content
python SKILL_DIR/scripts/analyze_bilibili.py "https://www.bilibili.com/video/BVxxxxxx"
python SKILL_DIR/scripts/analyze_bilibili.py "BVxxxxxx" --whisper
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --auto
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --force-whisper
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --timestamps --auto
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --language zh,en --auto
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --auto --whisper-language auto
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --verify-subtitle
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --auto --verify-subtitle
python SKILL_DIR/scripts/analyze_bilibili.py "URL" --language zh,en --auto --whisper-language auto
Output files are saved to SKILL_DIR/output/:
{bvid}_p{N}_{title}.txt — transcript (pN for multi-P)
{bvid}_p{N}_{title}.json — metadata
Multi-P video handling
When a video has multiple episodes (分P):
- Script returns
status: "needs_page_selection" with the list of pages.
- Tell the user and ask which episode they want.
- Re-run with
--page N (e.g. --page 2 for the second episode).
--force-whisper also requires --page for multi-P videos — if none given, it errors.
Workflow for Hermes
-
Run analyze_bilibili.py with the user's URL or BV number (default: conservative mode).
-
Read the JSON output:
status | Meaning | Hermes action |
|---|
success | Transcript ready | read_file the transcript_file, then summarize |
needs_confirmation | No subtitles, user needs to decide | Tell user, ask permission, re-run with --whisper |
needs_page_selection | Multi-P video | Show page list, ask user, re-run with --page N |
failed | Error occurred (API/cookie/network/whisper) | Report the phase and message to user |
Handling "no subtitles"
Default behavior (no special flag):
- Extract subtitles. If none found,
status: "needs_confirmation" → ask the user.
- Do NOT auto-start Whisper without user consent. The
next_command preserves all flags (--page, --language, etc.).
User says yes — re-run with --whisper:
python SKILL_DIR/scripts/analyze_bilibili.py "BVxxxx" --whisper
User explicitly wants full automation (e.g. "完整分析这个视频"):
python SKILL_DIR/scripts/analyze_bilibili.py "BVxxxx" --auto
User wants to bypass subtitles entirely (e.g. "不要字幕直接转写"):
python SKILL_DIR/scripts/analyze_bilibili.py "BVxxxx" --force-whisper
Language handling
Two independent language settings:
| Parameter | Purpose | Example |
|---|
--language zh,en | Subtitle language priority (Bilibili API) | --language zh,en |
--whisper-language auto | Whisper transcription language | --whisper-language auto |
For non-Chinese videos, use --whisper-language auto so Whisper auto-detects the spoken language.
Chunking (for long transcripts)
If the transcript exceeds ~50K characters, split into overlapping chunks of ~40K chars with ~2K overlap. Summarize each chunk separately, then merge the summaries into a final result. This prevents context window overflow and lossy compression.
Default summary format
📺 视频标题
━━━━━━━━━━━━━━━━━━
• 要点1
• 要点2
• 要点3
💡 结论
Output formats (user can request)
Key points, quotes with context, chapter summaries, full transcript, blog post.
Error Handling
| Phase | Meaning | Action |
|---|
cookie | Bilibili cookies not configured | Guide user to get cookies from DevTools |
extract | Could not parse BV number from URL | Verify URL format |
video_info | Bilibili API rejected video info request | Video may be private/deleted/region-locked |
subtitle_api | Subtitle API returned error (may be rate limit or auth) | Try again later; check cookies |
page_selection | Multi-P video with no --page | Re-run with --page N |
playurl | Can't get audio stream URL | Cookie expired / 会员视频 / 区域限制 |
download | Audio stream download failed (HTTP error or empty) | Network issue; check cookie validity |
ffmpeg | Audio conversion failed | Install ffmpeg or provide pre-converted .wav |
whisper | Transcription failed (model error, OOM, audio issue) | Try --device cpu or a smaller model (tiny/base) |
Env variable overrides
| Variable | Default | Purpose |
|---|
WHISPER_MODEL_DIR | ~/.hermes/whisper/models | Whisper model storage location |
WHISPER_TEMP | ~/.hermes/whisper/temp | Audio download temp directory |
WHISPER_MODEL | small | Default Whisper model name |
WHISPER_DEVICE | cuda | torch device for Whisper |
Notes
- ~90% of videos have AI subtitles (instant, zero cost)
- ~10% need Whisper fallback (~4 min GPU time per 42 min video)
- Whisper small model (466MB) stored at
~/.hermes/whisper/models/small.pt
- Audio download uses the same cookies as subtitle extraction
- Does NOT handle: member-only videos, geo-restricted content, expired cookies
- Cookie errors and API errors are reported as failed, not as no subtitles — do not suggest Whisper when the root cause is credential/API failure
- Bilibili subtitle API is non-deterministic: same video returns different content per call. See references/bilibili-api-quirks.md for details.