关于 yt2bb
yt2bb 是将 YouTube 视频或播放列表处理为适合发布到 Bilibili 的视频技能,可烧录中英双语字幕并生成 publish_info.md。流程涵盖下载、转录、翻译、字幕校验与样式设置、视频渲染和发布信息准备。
主要功能
- 01下载视频和播放列表
- 02转录并翻译字幕
- 03校验、检查并合并 SRT 文件
- 04用 ASS 设置双语字幕样式
- 05将字幕烧录到视频
- 06生成 Bilibili 发布信息
适用场景
- 01为发布到 Bilibili 准备 YouTube 视频
- 02为英文视频添加双语字幕
- 03将视频内容改编给中文受众
- 04生成视频上传所需信息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agents365-ai/ 365-skills --skill yt2bb安装后在 Claude Code 中输入/yt2bb确认已加载。
附带文件srt_utils.py
详细介绍
yt2bb — YouTube 到 Bilibili 的视频再利用
概述
六步工作流:下载 → 转录 → 翻译 → 合并 → 烧录字幕 → 生成发布信息。生成的视频带有硬编码的中英双语字幕,并附带包含 Bilibili 上传元数据的 publish_info.md。
适用场景
- 用户提供 YouTube URL(单个视频或播放列表),并希望获得可直接上传到 Bilibili 的版本
- 用户需要将中英双语字幕烧录到视频中
- 用户希望将英文视频内容重新制作,面向中文观众发布
快速参考
| 步骤 | 工具 | 命令 | 输出 |
|---|---|---|---|
| 0. 更新 | git | 自动检查技能更新 | — |
| 1. 下载 | yt-dlp | yt-dlp --cookies-from-browser chrome -f ... -o ... | {slug}.mp4 |
| 2. 转录 | whisper* | 先运行 srt_utils.py check-whisper,然后转录 | {slug}_{lang}.srt |
| 2.5 验证 | srt_utils.py | srt_utils.py validate / fix | {slug}_{lang}.srt(已修复) |
| 3. 翻译 | AI | 感知 SRT 结构的分批翻译 | {slug}_zh.srt |
| 4. 合并 | srt_utils.py | srt_utils.py merge ... | {slug}_bilingual.srt |
| 4.5 样式 | srt_utils.py | srt_utils.py to_ass --preset netflix|clean|glow | {slug}_bilingual.ass |
| 5. 烧录 | ffmpeg | ffmpeg -c:v libx264 -vf ass=... | {slug}_bilingual.mp4 |
| 6. 发布 | AI | 分析内容并生成元数据 | publish_info.md |
确定技能目录
确定后续工作流步骤使用的 SKILL_DIR:
# Find the skill dir: a 'yt2bb' folder that actually contains SKILL.md.
# Works whether installed flat (~/.claude/skills/yt2bb) or pulled from this repo (skills/yt2bb).
SKILL_DIR="$(find ~/.claude/skills ~/.openclaw/skills ~/.hermes/skills ~/.pi/agent/skills ~/.agents/skills ~/myagents/myskills -type d -name 'yt2bb' -exec test -f '{}/SKILL.md' \; -print 2>/dev/null | head -1)"
工作流详情
步骤 1:下载
单个视频:
slug="video-name" # or: slug=$(python3 "$SKILL_DIR/srt_utils.py" slugify "Video Title")
mkdir -p "${slug}"
yt-dlp --cookies-from-browser chrome \
-f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]" \
-o "${slug}/${slug}.mp4" "https://www.youtube.com/watch?v=VIDEO_ID"
播放列表 / 系列:
yt-dlp --cookies-from-browser chrome \
-f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]" \
-o "%(playlist_index)03d-%(title)s/%(playlist_index)03d-%(title)s.mp4" \
"https://www.youtube.com/playlist?list=PLAYLIST_ID"
下载完成后,将每个文件夹重命名为简洁的 slug,然后依次对每个视频运行步骤 2–6。
-f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]":确保输出为 mp4,避免使用 webm%(playlist_index)03d:使用零填充索引,以保留播放列表顺序- 如果
--cookies-from-browser失败,请先导出 cookies——参见“故障排除”
步骤 2:转录
先运行环境检查,以检测你的平台并获取针对性推荐的 whisper 命令:
python3 "$SKILL_DIR/srt_utils.py" check-whisper
此命令会自动检测操作系统、GPU(CUDA/Metal/CPU)、内存和已安装的后端,然后针对你的硬件推荐最佳后端和模型。如果无法检测内存,则会采用保守的备用方案,而不会假设设备内存不足。请使用它打印出的命令。
手动备用方案(openai-whisper,适用于所有平台):
src_lang="en" # Change to ja/ko/es/etc. based on source video
whisper_model="medium" # check-whisper recommends the best model for your hardware
whisper "${slug}/${slug}.mp4" \
--model "$whisper_model" \
--language "$src_lang" \
--word_timestamps True \
--condition_on_previous_text False \
--output_format srt \
--max_line_width 40 --max_line_count 1 \
--output_dir "${slug}"
mv "${slug}/${slug}.srt" "${slug}/${slug}_${src_lang}.srt"
支持的后端:
| 后端 | 适用场景 | 安装 |
|---|---|---|
mlx-whisper | macOS Apple Silicon(速度最快) | pip install mlx-whisper |
whisper-ctranslate2 | Windows/Linux CUDA,或 CPU(速度约快 4 倍) | pip install whisper-ctranslate2 |
openai-whisper | 通用备用方案 | pip install openai-whisper |
模型选择(由 check-whisper 自动推荐):
tiny— 快速草稿,准确度较低,适合 CPU(约 1 GB)medium— 默认,兼顾速度与准确度(约 5 GB)large-v3— 准确度最高,推荐用于日语/韩语/中文源视频(约 10 GB)
注意:
--language:显式指定语言以避免误检测;支持en、ja、ko、es等--word_timestamps True:获得更精确的字幕时间--condition_on_previous_text False:防止产生幻觉式循环- 如果输出乱码或内容重复,请添加防幻觉参数——参见“故障排除”
步骤 2.5:验证与修复(可选)
python3 "$SKILL_DIR/srt_utils.py" validate "${slug}/${slug}_${src_lang}.srt"
# If issues found:
python3 "$SKILL_DIR/srt_utils.py" fix "${slug}/${slug}_${src_lang}.srt" "${slug}/${slug}_${src_lang}.srt"
第 3 步:翻译
读取 {slug}_{src_lang}.srt 并翻译成中文。关键规则:
这些规则参考了 Netflix 简体中文计时文本风格指南;请遵循这些规则,制作出可达到广播级质量的字幕。
- 保持 SRT 格式不变——索引编号和时间戳(
-->行)必须原样保留 - 条目一一对应——每个源条目必须恰好对应一个译文条目(数量相同)
- 优化底部字幕——尽可能让每条中文字幕保持 1 行,以便最终双语字幕在画面底部保持紧凑
- 每行最多 16 个全角字符(Netflix 简体中文规范)。优先控制在 12–16 个字符;如果字幕很短(< 1 s),则进一步压缩,确保阅读速度 ≤ 9 个字符/秒
- 酌情精简,不要机械删减——删除填充词、重复主语、语气较弱的感叹词和多余的客套话,再考虑删减关键信息
- 匹配字幕时长——字幕行应能在屏幕显示时间内轻松读完;如果字幕很短,则进一步压缩
- 中文字幕末尾不加标点——去掉句末的
。、!、?;仅在有助于理解时保留句中的,、、、; - 字幕内使用全角中文标点(
,。!?、;:);内层引号使用 「」,不要使用""或'' - 数字和拉丁字符使用半角——数字、单位、产品名称和代码标识符均保持半角(
GPT-4、30fps、2026);只有标点使用全角 - 每条字幕都是完整、独立的一行——每个显示行都应是完整句子或简短语义单元,绝不能是被截断的从句,就像电影或电视剧中的双语字幕一样。实际操作中:不要在功能词(
的、了、吗、呢、吧、啊)后断行;不要将英语短语拆开;修饰语要与中心语放在一起 - 保持术语一致——技术术语、名称、产品名称和反复出现的短语在各批次中应采用相同译法。必要时维护一份行内术语表
- 灵活翻译,不要音译——优先保留语体、语气和意图,而非逐字对应;用自然的中文表达习语
- 每批翻译 10 条——以有效的 SRT 格式输出每批内容,然后继续翻译
- 不要合并或拆分条目——保持原有分段
- 保存为
{slug}/{slug}_zh.srt
第 4 步:合并
python3 "$SKILL_DIR/srt_utils.py" merge \
"${slug}/${slug}_${src_lang}.srt" "${slug}/${slug}_zh.srt" "${slug}/${slug}_bilingual.srt"
第 4.25 步:Netflix 校验(推荐)
对合并后的双语 SRT 运行 lint,检查 validate 未覆盖的 Netflix 计时文本风格指南违规项,包括阅读速度(CPS)、每行长度、字幕间隔和行数。
python3 "$SKILL_DIR/srt_utils.py" lint "${slug}/${slug}_bilingual.srt"
默认值(均可通过标志覆盖):
| 规则 | 阈值 | 标志 |
|---|---|---|
| 阅读速度(英语) | ≤ 17 CPS | --max-cps-en |
| 阅读速度(简体中文) | ≤ 9 CPS | --max-cps-zh |
| 最短字幕时长 | 833 ms(5/6 秒) | --min-duration-ms |
| 最长字幕时长 | 7000 ms | --max-duration-ms |
| 最短字幕间隔 | 83 ms(24 fps 下 2 帧) | --min-gap-ms |
| 每行最多字符数(英语) | 42 | --max-chars-en |
| 每行最多字符数(中文,全角) | 16 | --max-chars-zh |
| 每条字幕最多行数 | 2 | — |
严重性模型:
- 错误(退出代码 2):时长超出限制、CPS 超限、每条字幕超过 2 行。这些问题会导致无法通过 Netflix 验收,应在烧录字幕前修复。
- 警告(若无错误则退出代码为 0):每行长度、间隔过短。这些是建议项——可行时请予以处理,但不会阻止交付。
出现 CPS 错误时,问题几乎总是出在上游——返回第 3 步,重写不符合时间窗口要求的中文条目。不要通过延长字幕时长,使其超出源音频的语音时长来解决 CPS 问题。
便于 Agent 使用的输出:
python3 "$SKILL_DIR/srt_utils.py" lint "${slug}/${slug}_bilingual.srt" --format json
返回 {ok, error_count, warning_count, issues: [{index, code, severity, message}, ...]},以便进行程序化筛选。
步骤 4.5:样式 — 转换为 ASS
将双语 SRT 转换为 ASS 文件。ASS 支持逐行设置颜色、字体大小和发光效果,而这些效果无法通过 SRT 的 force_style 实现。布局规则:字幕始终位于底部。默认排列:中文在底部字幕堆叠的上行,英文在下行。这些预设经过调整,旨在确保字幕块易于阅读,同时降低与屏幕下方内容重叠的风险。
重要 — 继续之前请先询问。 向用户展示下方预设表格,并询问他们偏好哪种样式。不要擅自选择默认样式。如果用户没有偏好,请使用
clean。
可用预设:
| 预设 | 效果 | 适用场景 |
|---|---|---|
netflix | 纯白文字、细黑描边、柔和投影、无底框 — 参考 Netflix Timed Text Style Guide | 专业、广播级观感。纪录片、访谈、长内容,以及任何需要呈现“原生流媒体平台”质感的内容都适用。Linux 上搭配 --font "Source Han Sans SC",macOS 上搭配 "PingFang SC",可获得最接近 Netflix Sans 的观感 |
clean | 灰色底框上的黄色文字 — 金黄色中文 + 浅黄色英文,搭配半透明浅灰色背景 | 适用于画面繁杂或亮度混杂的素材,作为可读性保障,避免 netflix 仅靠描边的文字在视觉上难以辨认。灰色底框可确保文字周围有清晰的对比区域 |
glow | 黄色中文 + 白色英文,并带彩色发光效果 — 亮黄色中文 + 白色英文、模糊的外发光、无底框 | 适用于娱乐内容、Vlog 和节奏活跃的剪辑。最吸睛,但在明亮或繁杂的背景上效果最弱 |
向用户提问的示例:
字幕有三套样式可选:
netflix— 纯白字体 + 细黑描边 + 柔和阴影(默认推荐,Netflix 专业观感,适合纪录片/访谈/长内容)clean— 黄色字体 + 灰色半透明底框(亮背景或花背景的兜底选项,底框保证对比度)glow— 黄色/白色字体 + 彩色外发光(更抢眼,适合娱乐/Vlog)- 自定义 — 提供
.ass样式文件,完全控制字体、颜色、大小(可用 Aegisub 可视化编辑)选哪个?默认推荐
netflix;如果画面特别花哨或底部信息多,可改用clean。
# Netflix-grade default (white + outline + soft shadow), ZH on top
python3 "$SKILL_DIR/srt_utils.py" to_ass \
"${slug}/${slug}_bilingual.srt" "${slug}/${slug}_bilingual.ass" \
--preset netflix
# Gray-box fallback for busy backgrounds, EN on top
python3 "$SKILL_DIR/srt_utils.py" to_ass \
"${slug}/${slug}_bilingual.srt" "${slug}/${slug}_bilingual.ass" \
--preset clean --top en
# Vibrant glow (B站 entertainment style)
python3 "$SKILL_DIR/srt_utils.py" to_ass \
"${slug}/${slug}_bilingual.srt" "${slug}/${slug}_bilingual.ass" \
--preset glow
自定义样式文件 — 如需完全控制样式,可提供包含自定义 [V4+ Styles] 区段的外部 .ass 文件。文件中必须包含名为 EN 和 ZH 的样式,否则 to_ass 会在前期校验时失败并报错。你可以使用 Aegisub 直观地设计样式并导出。
python3 "$SKILL_DIR/srt_utils.py" to_ass \
"${slug}/${slug}_bilingual.srt" "${slug}/${slug}_bilingual.ass" \
--style-file my_styles.ass
也可以在 .ass 文件中添加 ; en_tag= 和 ; zh_tag={\blur5} 注释行,为每种语言注入 ASS 覆盖标签。
字体 — 省略 --font 可根据操作系统自动选择最佳的已安装中日韩字体;传入 --font 可覆盖自动选择结果(使用 --style-file 时会忽略此选项):
| 平台 | 自动选择 |
|---|---|
| macOS | PingFang SC |
| Linux | Noto Sans CJK SC(已安装字体中的最佳选择) |
| Windows | Microsoft YaHei |
其他选项:
--top zh|en— 指定哪种语言位于底部字幕堆叠的上行(默认:zh)--res WxH— 视频分辨率(默认:1920x1080)--fade <ms>— 淡入/淡出时长,单位为毫秒(默认150;0表示禁用)。使用柔和的电影式淡入淡出,而非硬切--reflow— 将每条字幕拆分为完整句子行(规则 10),确保显示的每一行都不是被截断的片段--safe-area <frac>— 底部保留区域占画面高度的比例(默认0.06),避免字幕遮挡平台界面或进度条
所有预设的可读性说明:
- 预设始终在底部对齐;不会自动移至顶部
- 字体大小、描边和垂直边距会随
--res缩放,确保 720p 和 1080p 下的视觉平衡相近 - 如果必须确保字幕在每个镜头中都位于底部,
clean是最安全的选择
步骤 5:烧录字幕
使用 ass= 滤镜(不要使用 subtitles=)——所有样式都来自 ASS 文件。
ffmpeg -i "${slug}/${slug}.mp4" \
-vf "ass='${slug}/${slug}_bilingual.ass'" \
-c:v libx264 -crf 23 -preset medium \
-c:a copy "${slug}/${slug}_bilingual.mp4"
-c:v libx264 -crf 23:在画质良好与文件大小合理之间取得平衡-preset medium:平衡速度与压缩效果(需要更快编码时可使用fast)- 无需
force_style— 样式已嵌入 ASS 文件中
步骤 6:生成发布信息
根据视频内容(来自 {slug}_{src_lang}.srt 和 {slug}_zh.srt),生成 {slug}/publish_info.md。
此文件中的所有内容都必须使用中文(面向 Bilibili 观众)。
# Publish Info
## Source
{YouTube URL}
## Titles (5 variants)
1. {Suspense/question style — spark curiosity}
2. {Data/achievement driven — emphasize results}
3. {Controversial/opinion style — spark discussion}
4. {Tutorial/practical style — emphasize utility}
5. {Emotional/relatable style — connect with audience}
## Tags
{~10 comma-separated keywords covering topic, technology, domain}
## Description
{3-5 sentences summarizing core content and highlights}
## Chapter Timestamps
00:00 {chapter name}
...
生成规则:
- 标题风格需符合 Bilibili 惯例:语气轻松,设置悬念,灵活使用符号(【】、?、!)
- 标签应同时涵盖中英文关键词,以便用户发现
- 从
{slug}_bilingual.srt中提取主题转换点的时间戳 - 描述需要有吸引力的开头——前两句话决定用户是否会展开阅读
输出结构
{slug}/
├── {slug}.mp4 # Source video
├── {slug}_{src_lang}.srt # Source language subtitles
├── {slug}_zh.srt # Chinese subtitles
├── {slug}_bilingual.srt # Merged bilingual
├── {slug}_bilingual.mp4 # Final output
└── publish_info.md # Bilibili upload metadata
工具:srt_utils.py
python3 "$SKILL_DIR/srt_utils.py" merge en.srt zh.srt output.srt # Merge bilingual
python3 "$SKILL_DIR/srt_utils.py" merge --dry-run en.srt zh.srt output.srt # Pre-check without writing
python3 "$SKILL_DIR/srt_utils.py" validate input.srt # Check timing issues
python3 "$SKILL_DIR/srt_utils.py" fix input.srt output.srt # Fix timing/overlaps (multi-pass)
python3 "$SKILL_DIR/srt_utils.py" slugify "Video Title" # Generate slug
python3 "$SKILL_DIR/srt_utils.py" to_ass input.srt output.ass # Convert to styled ASS (default: clean, ZH on top)
python3 "$SKILL_DIR/srt_utils.py" to_ass --dry-run input.srt output.ass # Pre-check without writing
python3 "$SKILL_DIR/srt_utils.py" to_ass input.srt output.ass --preset glow --top en
python3 "$SKILL_DIR/srt_utils.py" to_ass input.srt output.ass --style-file custom.ass # User-defined styles
python3 "$SKILL_DIR/srt_utils.py" check-whisper # Detect platform, recommend whisper backend + model
常见错误
- 条目数不匹配:默认情况下合并会失败——请修复翻译,或使用
--pad-missing补齐 - 未找到字体:请确保已安装 PingFang SC(macOS 默认字体),或使用替代字体(参见故障排查)
故障排查
yt-dlp:Cookie 身份验证失败
--cookies-from-browser chrome 要求关闭 Chrome(或使用配置文件快照)。如果失败:
# Export cookies once, then reuse the file
yt-dlp --cookies-from-browser chrome --cookies cookies.txt --skip-download "URL"
yt-dlp --cookies cookies.txt -f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]" -o "${slug}/${slug}.mp4" "URL"
对于 429 / 速率限制错误,请添加 --sleep-interval 3 --max-sleep-interval 8。
whisper:语言错误或出现幻觉循环
症状:重复短语、乱码字符,或尽管音频清晰,生成的 SRT 几乎为空。
whisper "${slug}/${slug}.mp4" \
--model medium \
--language "$src_lang" \
--condition_on_previous_text False \
--no_speech_threshold 0.6 \
--logprob_threshold -1.0 \
--compression_ratio_threshold 2.0 \
--output_format srt \
--output_dir "${slug}"
如果仍然误判语言,音频中可能有长时间静音或非语音片段——请添加 --vad_filter True 将其过滤掉。
ffmpeg:未找到字体 / 中文字符显示为方框
在 to_ass 步骤(步骤 4.5)中通过 --font 指定正确的字体。ASS 文件会嵌入字体名称,因此 ffmpeg 在烧录时需要已安装该字体。
| 平台 | 字体 | 安装方式 |
|---|---|---|
| macOS | PingFang SC | 预装 |
| Linux | Noto Sans CJK SC | sudo apt install fonts-noto-cjk |
| Linux(替代) | WenQuanYi Micro Hei | sudo apt install fonts-wqy-microhei |
| Windows | Microsoft YaHei | 预装 |
使用正确的 --font 参数重新生成 ASS 文件,然后重新运行烧录步骤。
隐私与数据流
- 浏览器 Cookie:步骤 1 使用
yt-dlp --cookies-from-browser chrome访问有年龄限制或私有视频。此操作会在本地读取 Chrome Cookie——不会将 Cookie 发送到 YouTube 自身服务器以外的任何地方。若要避免此操作,请先将 Cookie 导出到文件(参见上方的故障排查)。 - 转录文本与翻译:步骤 3(翻译)和步骤 6(发布信息)由对话中的 AI Agent 完成。转录文本会发送给 Agent 所使用的模型 / 服务(例如 Claude API)。如果视频包含敏感内容,请在这些步骤中使用本地模型。
- 无遥测:
srt_utils.py不会发出网络请求。所有处理(SRT 解析、合并、ASS 生成、硬件检测)均完全在本地进行。