yt2bb について
yt2bb は、YouTube の動画やプレイリストを Bilibili 向けに加工するスキルです。英語・中国語の字幕を動画に焼き込み、publish_info.md を作成します。ダウンロード、文字起こし、翻訳、字幕の検証とスタイル設定、動画出力、投稿情報の準備までを行います。
主な機能
- 01動画とプレイリストのダウンロード
- 02字幕の文字起こしと翻訳
- 03SRT ファイルの検証・校正・結合
- 04ASS による字幕スタイル設定
- 05動画への字幕焼き込み
- 06Bilibili 投稿情報の生成
活用シーン
- 01YouTube 動画を Bilibili 向けに準備
- 02英語動画に二言語字幕を追加
- 03中国語圏向けに動画を再利用
- 04動画の投稿情報を作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agents365-ai/ 365-skills --skill yt2bbインストール後、Claude Code で/yt2bbを入力して読み込まれたか確認します。
同梱ファイルsrt_utils.py
詳細
yt2bb — YouTube から Bilibili への動画再利用
概要
6 ステップのパイプラインです:ダウンロード → 書き起こし → 翻訳 → 結合 → 字幕の焼き付け → 公開情報の生成。二言語(EN/ZH)の字幕を映像に焼き付けた動画と、Bilibili へのアップロード用メタデータを記載した publish_info.md を生成します。
使用する場面
- ユーザーが YouTube の URL(単一の動画またはプレイリスト)を提示し、Bilibili 用の動画を作成したい場合
- 二言語の EN-ZH 字幕を動画に焼き付けたい場合
- 英語の動画コンテンツを中国語圏の視聴者向けに再利用したい場合
クイックリファレンス
| ステップ | ツール | コマンド | 出力 |
|---|---|---|---|
| 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"
ダウンロード後、各フォルダー名をわかりやすいスラッグに変更し、動画ごとにステップ 2~6 を順番に実行します。
-f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]":出力を mp4 にし、webm を避けます%(playlist_index)03d:プレイリストの順序を維持するため、インデックスをゼロ埋めします--cookies-from-browserが失敗する場合は、先に Cookie をエクスポートしてください。「トラブルシューティング」を参照してください
ステップ 2:書き起こし
まず環境チェックを実行し、プラットフォームを検出して環境に合わせた whisper コマンドを取得します:
python3 "$SKILL_DIR/srt_utils.py" check-whisper
OS、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— 最高精度。JA/KO/ZH のソースに推奨されます(約 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"
Step 3: 翻訳する
{slug}_{src_lang}.srt を読み、簡体字中国語に翻訳します。重要なルール:
これらのルールは、Netflix 簡体字中国語タイムドテキストスタイルガイドを参考にしています。放送品質の字幕を作成するため、従ってください。
- SRT 形式を維持する — インデックス番号とタイムスタンプ(
-->の行)はそのまま保持します - 1 対 1 で対応させる — 原文の各エントリーにつき、翻訳後のエントリーを必ず 1 つ作成します(件数は同じ)
- 画面下部の字幕に最適化する — 最終的な二言語字幕が画面下部でコンパクトに収まるよう、可能な限り中国語の各エントリーを 1 行にします
- 1 行あたり全角 16 文字まで(Netflix の簡体字中国語仕様)。12〜16 文字を推奨します。表示時間が非常に短い(1 秒未満)字幕は、読書速度が 1 秒あたり 9 文字以下になるよう、さらに短くします
- 機械的ではなく、適切に判断して短縮する — 重要な意味を削る前に、フィラー、繰り返される主語、意味の薄い感嘆詞、冗長な丁寧表現を削ります
- 字幕の表示時間に合わせる — 表示時間内に無理なく読める長さにします。表示時間が非常に短い場合は、さらに大幅に短縮します
- 中国語字幕の末尾に句読点を付けない — 文末の
。、!、?は削除します。明確さを保つのに必要な場合に限り、文中の,、、、;は残します - 字幕内では全角の中国語句読点を使う(
,。!?、;:)。引用符には""や''ではなく 「」 を使います - 数字とラテン文字は半角にする — 数字、単位、製品名、コード識別子は半角のままにします(
GPT-4、30fps、2026)。句読点のみ全角にします - 各字幕は、意味が完結した 1 行にする — 表示される各行は、映画やドラマの二言語字幕と同様に、完結した文または意味のまとまりにします。途中で切れた節にしてはいけません。具体的には、機能語(
的、了、吗、呢、吧、啊)の後で区切らないこと、英語の句動詞のまとまりを改行で分断しないこと、修飾語と被修飾語を離さないこと - 用語の一貫性を保つ — 技術用語、名前、製品名、繰り返し使われる表現は、バッチをまたいでも同じように翻訳します。必要に応じて用語集を作成します
- 音訳ではなく、自然に訳す — 逐語的な対応よりも、文体、口調、意図を保つことを優先します。慣用句は自然な中国語表現に置き換えます
- 10 エントリーずつ翻訳する — 各バッチを有効な SRT 形式で出力してから、次に進みます
- エントリーを結合または分割しない — 元の区切りを維持します
{slug}/{slug}_zh.srtとして保存します
Step 4: 結合する
python3 "$SKILL_DIR/srt_utils.py" merge \
"${slug}/${slug}_${src_lang}.srt" "${slug}/${slug}_zh.srt" "${slug}/${slug}_bilingual.srt"
Step 4.25: Netflix Lint(推奨)
結合した二言語 SRT に対して lint を実行し、validate では検出できない Netflix タイムドテキストスタイルガイドの違反(読書速度(CPS)、1 行あたりの長さ、字幕間の間隔、行数)を確認します。
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 |
| 1 行あたりの最大文字数(英語) | 42 | --max-chars-en |
| 1 行あたりの最大文字数(中国語、全角) | 16 | --max-chars-zh |
| 字幕あたりの最大行数 | 2 | — |
重大度モデル:
- エラー(終了コード 2):表示時間が範囲外、CPS が上限を超過、字幕が 2 行を超過。Netflix の受け入れ基準に違反するため、字幕の書き込み前に修正する必要があります。
- 警告(エラーもある場合を除き、終了コード 0):1 行あたりの長さ、間隔が短い。これらは推奨事項です。可能であれば対処してください。ただし、納品を妨げるものではありません。
CPS エラーが発生した場合、ほとんどの場合、修正が必要なのは上流の工程です。Step 3 に戻り、問題のある中国語のエントリーを、表示時間に収まるように書き直してください。字幕の表示時間を原文の発話時間より延ばして、CPS の問題を解決しないでください。
エージェント向けの出力:
python3 "$SKILL_DIR/srt_utils.py" lint "${slug}/${slug}_bilingual.srt" --format json
プログラムによるフィルタリング用に、{ok, error_count, warning_count, issues: [{index, code, severity, message}, ...]} を返します。
Step 4.5: スタイル — ASS に変換する
バイリンガルの SRT を ASS ファイルに変換します。ASS では、SRT の force_style では不可能な、行ごとの色、フォントサイズ、グロー効果を設定できます。レイアウトのルール:字幕は常に画面下部に表示します。デフォルトの配置:ZH は下部の字幕スタックの上段、EN は下段です。プリセットは、ブロックの読みやすさを保ちながら、画面下部のコンテンツと重なるリスクを減らせるよう調整されています。
重要 — 先に確認してください。 以下のプリセット表をユーザーに提示し、希望するスタイルを尋ねてください。黙ってデフォルトを選ばないでください。希望がない場合は
cleanを使用します。
利用可能なプリセット:
| プリセット | 見た目 | 最適な用途 |
|---|---|---|
netflix | 純白のテキスト、細い黒のアウトライン、柔らかなドロップシャドウ、背景ボックスなし — Netflix Timed Text Style Guide を参考にしています | プロフェッショナルで放送品質の見た目です。ドキュメンタリー、インタビュー、長尺コンテンツ、ストリーミングプラットフォームらしい雰囲気にしたいコンテンツに最適なデフォルトです。Netflix Sans に最も近い雰囲気にするには、Linux では --font "Source Han Sans SC"、macOS では "PingFang SC" を使用してください |
clean | グレーのボックス上の黄色いテキスト — ゴールドの ZH と淡い黄色の EN、半透明の薄いグレーの背景 | 画面が煩雑、または明暗が混在していて、netflix のアウトラインのみのテキストが見づらくなる場合の、読みやすさを確保する選択肢です。グレーのボックスが読みやすいコントラストの余白を確保します |
glow | 色付きのグローを施した黄色の ZH と白の EN — 鮮やかな黄色の ZH と白の EN、ぼかした外側のグロー、背景ボックスなし | エンターテインメント、Vlog、テンポの速い編集に適しています。最も目を引きますが、明るい背景や煩雑な背景では最も見づらくなります |
ユーザーへの質問例:
字幕には、次の3つのスタイルを選べます:
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 を省略すると、OS にインストールされている最適な CJK フォントが自動選択されます。上書きするには --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)。字幕がプラットフォームの UI やプログレスバーに重ならないようにします
すべてのプリセットに共通する読みやすさに関する注意:
- プリセットは常に画面下部に配置され、上部へ自動的に移動することはありません
- フォントサイズ、アウトライン、垂直方向の余白は
--resに合わせて拡大縮小されるため、720p と 1080p でも同程度の視覚的バランスが保たれます - どのショットでも字幕を画面下部に表示する必要がある場合は、
cleanが最も安全な選択肢です
Step 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から抽出します - 説明文には強力なフックを入れます。最初の 2 文で、視聴者が続きを読むかどうかが決まります
出力構成
{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:フォントが見つからない/CJK の文字が四角形になる
ステップ 4.5 の to_ass で --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 はローカルで読み取られます。YouTube 自体のサーバー以外に Cookie が送信されることはありません。これを避けるには、先に Cookie をファイルにエクスポートしてください(上記の「トラブルシューティング」を参照)。 - 文字起こしと翻訳:ステップ 3(翻訳)とステップ 6(公開情報)は、会話内で AI エージェントが実行します。文字起こしデータは、エージェントが使用するモデル/サービス(例:Claude API)に送信されます。動画に機密情報が含まれる場合は、これらの手順でローカルモデルを使用してください。
- テレメトリーなし:
srt_utils.pyはネットワークリクエストを行いません。すべての処理(SRT の解析、マージ、ASS の生成、ハードウェアの検出)は完全にローカルで実行されます。