dsh-bilibili-subtitles 是做什么的?
Turn a Bilibili video link into a readable, searchable, and deliverable subtitle document.
Core principle: Prefer existing subtitles first, only fall back to ASR or OCR. Do not immediately download video/audio for Whisper; Bilibili platform subtitles (including AI subtitles) are typically higher quality and faster.
When to Use
Use this skill when:
- The user provides a Bilibili video link, BV/av number, episode/ep/ss link for anime, or b23.tv short link and asks to "extract subtitles" / "create a document" / "export to Word/Markdown".
- The user has a local video file with external subtitles that need batch conversion to documents.
- The user needs timestamped, bilingual aligned, or multi-P merged subtitle transcripts.
- The user requires a subtitle quality report to assess if manual proofreading is worthwhile.
Do not use for:
- Translating subtitles: this skill only performs bilingual alignment, not machine translation.
- Precise speaker diarization: automatic diarization is not enabled; only existing
[speaker]markers in subtitles are preserved. - Bypassing Bilibili login/pay/region restrictions: ask the user to provide cookies they are authorized to use, or switch to local files.
Installation & Invocation
- Plugin: https://github.com/Chenfan2/dsh-bilibili-subtitles (In DSH desktop, go to "Plugins → Add Plugin" and paste the URL, or run
dsh plugin --profile web add github:Chenfan2/dsh-bilibili-subtitles). - Plain skill: Copy the entire directory into DSH's skills directory (or run
install.ps1).
After installation, execute from within the directory:
python main.py "https://www.bilibili.com/video/BV1xx411c7mD" --format md,docx
If you only need it temporarily, you can run main.py directly from the skill directory without full installation.
One-Command Example
python main.py "https://www.bilibili.com/video/BV1xx411c7mD" --format md,docx
Outputs in output/:
Title_BVnumber.mdTitle_BVnumber.docxTitle_BVnumber.quality.json(quality report)Title_BVnumber.segments.json(cleaned, structured subtitles)_manifest.json(summary of the run)
Input / Output Contract
Inputs
| Type | Example |
|---|---|
| Bilibili video | https://www.bilibili.com/video/BV1xx411c7mD?p=2 |
| BV / av number | BV1xx411c7mD, av80433022 |
| Anime episode | https://www.bilibili.com/bangumi/play/ep123456, .../ss28747 |
| Short link | https://b23.tv/xxxxxx |
| Local video | input.mp4, input.mkv |
| External subtitles | --subtitle input.srt (also supports .ass / .vtt / .json / .txt) |
| Directory/batch | python main.py ./videos --format md,docx |
Outputs
- Document file paths (Markdown/Word/PDF/TXT/SRT).
- Structured subtitles:
[{start, end, text, speaker?, lang?, confidence?, translation?}]. - Quality report: subtitle source, language, coverage, low-confidence segments, warnings, head/middle/tail samples.
- Processing attempt log: per-provider success/failure/skip with reasons.
Subtitle Source Priority
The following sources are tried in order; failures cause automatic fallback unless explicitly disabled:
- User external subtitles (
--subtitle): Highest quality, fully controllable. - Bilibili platform subtitles / AI subtitles: Retrieved via
x/player/v2; requiresSESSDATA. - Local video embedded subtitles: Detected with
ffprobe, extracted withffmpegto SRT. - Hardcoded subtitle OCR: Local video only, enabled via
--ocr; experimental. - Whisper ASR: Enabled with
--asror as automatic fallback; downloads model on first use.
Without login, Bilibili typically does not return subtitle lists. In this case, you will get
LOGIN_REQUIREDalong with a prompt to provide a Cookie or enable ASR. This is a platform restriction, not a link error.
Bilibili Login (Required for Platform Subtitles)
The platform subtitle API only returns subtitle_url for logged-in sessions. Environment variables are recommended to avoid exposing credentials in command history:
$env:BILIBILI_SESSDATA = "your SESSDATA"
python main.py "https://www.bilibili.com/video/BV1xx411c7mD" --format md,docx
How to obtain: Log in to bilibili.com in your browser → Developer Tools → Application → Cookies → bilibili.com → Copy the value of SESSDATA.
Alternative methods:
python main.py URL --sessdata "SESSDATA value"
python main.py URL --cookie "SESSDATA=...; bili_jct=..."
python main.py URL --cookies cookies.txt
- Cookies are equivalent to account credentials: do not commit them to repositories, documents, or public channels.
- This skill uses cookies in memory only; logs and reports are sanitized.
- When cookies expire, re-copy them from the browser.
Common Parameters
| Parameter | Description |
|---|---|
--format md,docx,pdf,txt,srt,json | Output formats, comma separated; default md |
-o, --output PATH | Specify output file when single input + single format |
--out-dir DIR | Output directory, default output |
--title TEXT | Override document title (default is video title / filename) |
--subtitle PATH | External subtitle file or directory (highest priority) |
--language zh | Preferred subtitle/transcription language; platform subtitles matched by language |
--bilingual | Bilingual alignment: if two tracks exist, align by time; with single track, try line-based splitting |
--timestamps / --no-timestamps | Show [00:12] timestamps in body; default on |
--merge-sentences / --no-merge-sentences | Merge hard-cut short sentences; default on |
--no-auto-punctuation | Disable automatic punctuation for ASR/OCR (default on) |
--pages auto/all/1,3-5 | Select multiple parts; default processes only the part specified in URL, otherwise P1 |
--template default/minimal/file.md | Markdown template |
--quality-report PATH | Path for quality report JSON |
--no-quality | Skip generating quality report; also omit processing metadata from documents |
--glossary terms.json | Term replacement, e.g., {"DeepSeek":"深度求索"} |
--json-summary | Output machine-readable summary to stdout (for agent consumption) |
--asr / --no-asr | Enable / disable Whisper fallback; default auto (only if already installed) |
--asr-model small | tiny / base / small / medium; default small |
--model-dir DIR | Whisper model cache directory (default ./.vsub-models-cache) |
--ocr | Perform OCR on hardcoded subtitles in local video (experimental) |
--ffmpeg PATH | Specify ffmpeg / ffprobe path |
--strict | Return non-zero exit code if any input fails or quality is fail |
Full parameter list: python main.py --help.
Recommended Workflow (for Agents)
-
Determine input type:
- Bilibili link / BV / av → run directly.
- Local video → check for a matching
.srt / .vtt / .assfile; if found, use--subtitle; otherwise try embedded subtitles. - Subtitle file only → can be used directly as input.
-
Run default output first; do not enable ASR before examining the quality report:
python main.py "<link>" --format md,docx --out-dir output -
If
LOGIN_REQUIREDis returned:- Inform the user that platform subtitles require
SESSDATA, and provide setup instructions; do not retry repeatedly. - If the user does not have a cookie, suggest
--asr(explaining the model download, time cost, and potential recognition errors).
- Inform the user that platform subtitles require
-
Inspect
<stem>.quality.json:status=ok: deliver directly.status=warn: checkwarnings(especially coverage, overlaps, low confidence); include a note in the delivery summary.status=fail: do not pretend success; report the failure reason and suggest external subtitles / ASR / OCR.
-
Use
presentto deliver the.md/.docxfile as the final artifact; attach the quality report only if the user requests it.
Execution environment:
-
Prefer using the Python returned by
load_workspace_dependencies(it includespython-docx). -
Windows PowerShell invocation:
& "C:\...\python.exe" main.py "<link>" --format md,docx --out-dir output -
All outputs and temp files must be placed inside the session workspace; do not use system temp directories (may be blocked by sandbox).
Quality Report Fields
{
"status": "ok | warn | fail",
"score": 96.5,
"source": "bilibili",
"language": "zh",
"segments": 320,
"paragraphs": 86,
"duration": 1260.0,
"duration_covered": 0.96,
"coverage_span": 0.99,
"overlaps": 0,
"low_confidence_segments": 3,
"duplicate_segments": 1,
"gaps_over_10s": 2,
"warnings": ["..."],
"samples": {"head": [], "middle": [], "tail": []}
}
duration_covered: Relative to full video duration; may be lower if intro/outro ads were removed.coverage_span: Relative to content interval between first and last subtitle; better reflects whether speech portions are covered.samples: Up to 5 segments each from head, middle, and tail for manual spot-checking.- Common
status=failreasons: no segments, coverage below 30%, all parts failed.
Failures & Fallback
| Situation | Behavior |
|---|---|
| External subtitle parse failure | Log failure, continue to platform/embedded subtitles |
Platform subtitle LOGIN_REQUIRED | Prompt to set SESSDATA; if faster-whisper is installed and ASR allowed, automatically transcribe |
| No platform subtitle track | Prompt NO_SUBTITLE; can try --asr or --subtitle |
| Embedded subtitle is PGS/VobSub bitmap | Cannot convert directly to SRT; suggest OCR or external subtitles |
| ASR not installed | Skip and give pip install faster-whisper; does not silently fail |
| One output format fails | Other formats continue; recorded in quality.warnings; only report RENDER_FAILED if all fail |
| Batch partial failures | Successful items still output; failures recorded in _manifest.json and *.error.json |
Exit codes:
0Success (batch: at least one succeeded)2Input/link/API/parse error3No subtitles, login required, quality failure4Missing dependency (ffmpeg/Whisper/docx, etc.)5Document rendering failure1Unexpected error
Examples
# Basic: platform subtitles → Markdown + Word
python main.py "https://www.bilibili.com/video/BV1xx411c7mD" --format md,docx
# Just Word, with custom filename
python main.py "BV1xx411c7mD" --format docx -o "PaperNotes.docx"
# Multi-part + timestamps + quality report
python main.py "https://www.bilibili.com/video/BV1xx411c7mD?p=1" --pages all --format md
# External subtitles priority
python main.py "input.mp4" --subtitle "input.srt" --format md,docx
# Bilingual (auto-align when platform has two tracks)
python main.py "BV1xx411c7mD" --bilingual --language zh --format md,docx
# No login, fallback to ASR (downloads model first time)
python main.py "BV1xx411c7mD" --asr --asr-model small --format md,docx
# Batch directory
python main.py "./videos" --format md,docx --out-dir output/batch
# Local hardcoded subtitle OCR (experimental)
python main.py "input.mp4" --ocr --ocr-fps 2 --format md
Limitations
- Platform subtitle availability depends on the video, account, region, and uploader settings; this skill cannot bypass permissions.
- AI subtitles may contain errors, missing sentences, or timeline drift; the quality report can only flag issues, not replace manual proofreading.
- Bilingual mode uses "time alignment", not translation; it only aligns tracks in different languages.
- Automatic speaker diarization is not implemented; only existing markers like
[Zhang San],【Zhang San】,Zhang San:are parsed. - OCR applies only to local videos, by default the bottom 30% of the frame; for animations, vertical videos, or drifting subtitle position, adjust with
--ocr-cropor--ocr-full-frame. - PDF output requires LibreOffice or
reportlab; otherwise, a clear error is thrown without affecting md/docx. - ASR for long videos may be slow; the
smallmodel first download is about 460MB.
Copyright & Privacy
- Only process videos/subtitles the user has rights to; do not use this skill to bulk scrape copyrighted content.
- Subtitle documents retain the original video title, uploader, and link for traceability.
- Cookies and signed CDN URLs are not written to logs/quality reports; it is still recommended that users not paste cookies in public.
- Temporary audio/frame files are stored by default under
.vsub-tmpin the output directory and are automatically cleaned after execution; use--keep-tempto retain for debugging.
File Structure
dsh-bilibili-subtitles/
├── SKILL.md
├── README.md
├── main.py # CLI entry point
├── vsub/
│ ├── bilibili.py # URL/API/subtitles/audio
│ ├── input_adapter.py # Input adaptation
│ ├── pipeline.py # Five-layer pipeline orchestration
│ ├── providers/ # external/bilibili/embedded/ocr/asr
│ ├── parsers/ # srt/vtt/ass/bilibili-json/plain
│ ├── cleaners/ # cleaning, merging, bilingual, glossary
│ ├── renderers/ # md/docx/pdf/txt/srt/json
│ └── quality.py # Quality validation
├── templates/
├── tests/
└── requirements.txt