Step 2: YouTube字幕ミニアプリを作ろう 🚀
┌─────────────────────────────────────────────────────────┐
│ 🎬 YouTube字幕ミニアプリ開発フロー │
├─────────────────────────────────────────────────────────┤
│ │
│ Step 1: 日本語字幕表示 → ✅ 成功! │
│ ↓ │
│ Step 2: ファイル保存 → ✅ 便利になった! │
│ ↓ │
│ Step 3: 英語でわざと失敗 → ❌ エラー体験 │
│ ↓ │
│ Step 4: 英語対応改善 → ✅ 完全版完成! │
│ │
└─────────────────────────────────────────────────────────┘
前回のレッスンで環境構築が完了しましたね。この章では、YouTube動画の字幕を取り出す超ミニアプリを作ります。
例のごとく、いきなり完璧なものを作るのではなく、まずは最小の芯から始めていきます。最初は日本語の動画から全文を画面に表示するところからスタート。次に同じ内容をファイルへ保存して便利度を上げます。続いて英語動画でわざと失敗を体験し、最後に英語にも対応させて完成です。
僕も普段からプログラミングする際は、必ずこの「まずは最小 → 少しずつ改善 → 失敗から学ぶ → 完成」の流れで進めています。この方法なら、問題が起きても原因を特定しやすく、確実にゴールに到達できるからです。ぜひ試してみてください🤗
この章で学ぶこと
- 日本語字幕を最小コードで取り出して表示する方法
- 同じ内容をテキストファイルに保存する実用技術
- 失敗を材料に要件を広げる考え方(英語で落としてから直す)
languages
で言語の優先順位を指定するフォールバック方法
事前準備(1回だけ)
YouTubeの字幕を扱うライブラリがインストールされているか確認しましょう。前回のレッスンで requirements.txt
からインストールしているはずですが、もし不安な場合は以下を実行してください:
- Windows/Mac共通:
pip install youtube-transcript-api
もしうまくいかない場合は python -m pip install youtube-transcript-api
を試してみてください。
Step 1: 日本語字幕を全文
画面に表示しよう
┌─────────────────────────────────────────────────────────┐
│ 📺 字幕表示システム │
├─────────────────────────────────────────────────────────┤
│ │
│ 動画ID: zsg6FmfWhGI │
│ ↓ youtube_transcript_api │
│ 日本語字幕取得: [{'text': '...', 'start': 1.2}, ...] │
│ ↓ for文で1つずつ取り出し │
│ 画面表示: │
│ こんにちは、今日は... │
│ データの前処理について... │
│ 機械学習の基本概念は... │
│ │
│ ✅ 字幕全文表示完了! │
└─────────────────────────────────────────────────────────┘
さて、それでは実際に字幕取得の最小バージョンを作ってみましょう。
日本語字幕がある動画1本から、字幕の全文を画面に表示するミニアプリです。使う動画は zsg6FmfWhGI
に固定します。タイムコードは付けません。まずは「出せた!」という成功体験を作ることが大切です。
これまでにプログラミングを経験された方なら、「いきなり全部の機能を作りたい」という気持ちになるかもしれませんが、まずは本当にシンプルな機能から始めることで、後で問題が起きても原因を特定しやすくなります。
その前に:YouTube動画IDって何?
突然 zsg6FmfWhGI
という文字列が出てきて「これは何?」と思われたでしょう。これが YouTube動画ID です。まずはこの仕組みを理解しておきましょう。
YouTubeの動画URLを見たことがありますよね。例えば:
https://www.youtube.com/watch?v=zsg6FmfWhGI
この長いURLの中で、v=
の後ろにある 11文字の英数字 zsg6FmfWhGI
が「動画ID」です。これは世界中のYouTube動画を一意に識別する「住所」のような役割を果たしています。
なぜ動画IDが重要かというと、youtube_transcript_apiは 長いURLではなく、この11文字の動画IDだけを使って 字幕を取得するからです。
動画IDの見つけ方:
1. YouTube動画のページを開く
2. アドレスバーのURLを確認
3. v=
の後ろの11文字をコピー
例:
- https://www.youtube.com/watch?v=zsg6FmfWhGI
→ 動画ID: zsg6FmfWhGI
- https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=30s
→ 動画ID: dQw4w9WgXcQ
💡 ポイント: &
以降の部分(&t=30s
など)は再生開始時間などのオプションなので、動画IDには含まれません。
今回は zsg6FmfWhGI
という動画ID固定で進めますが、このIDの意味が分かっていれば、後で他の動画でも試せるようになりますね。
最小バージョンを作ってみよう
以下の内容で 01_show_ja_subtitles.py
というファイルを作成してください。
ファイル名: 01_show_ja_subtitles.py
from youtube_transcript_api import YouTubeTranscriptApi
VIDEO_ID = "zsg6FmfWhGI"
segments = YouTubeTranscriptApi.get_transcript(VIDEO_ID, languages=['ja'])
for seg in segments:
print(seg['text'])
このコードの読み解き
さて、たった数行のコードですが、それぞれの行が重要な役割を果たしています。一緒に見ていきましょう。
from youtube_transcript_api import YouTubeTranscriptApi
これは「誰かが作ってくれた道具」を使う合図です。YouTubeTranscriptApi
という字幕を取ってくる係
を手元に呼び出しています。これがあることで、複雑なYouTubeの内部システムを意識せずに字幕を取得できるんです。
VIDEO_ID = "zsg6FmfWhGI"
どの動画を扱うか、名前を付けてメモしています。VIDEO_ID
という箱に動画IDという文字列を入れました。以後、この名前を使えば同じIDを参照できます。このように定数として定義しておくと、後で違う動画に変更する時も1箇所を変えるだけで済みます。
YouTubeTranscriptApi.get_transcript(..., languages=['ja'])
「この動画の字幕をください」とお願いしています。languages=['ja']
は**日本語の字幕が欲しい**
という指定です。返ってくる値は字幕の小さなかたまりが並んだリストです。イメージとしては、ノートの各行が {'text': '本文', ...}
の形で並んでいる感じです。
for seg in segments:
「字幕のかたまりを1つずつ順番に取り出す」という意味です。実際のデータ構造を見てみましょう:
segments = [
{'text': 'こんにちは、今日は', 'start': 0.0, 'duration': 2.5},
{'text': 'プログラミングについて', 'start': 2.5, 'duration': 3.1},
{'text': '説明していきます', 'start': 5.6, 'duration': 2.8},
...
]
つまり segments
は 辞書が並んだリスト です。for文で回すと:
1回目: seg = {'text': 'こんにちは、今日は', 'start': 0.0, 'duration': 2.5}
2回目: seg = {'text': 'プログラミングについて', 'start': 2.5, 'duration': 3.1}
3回目: seg = {'text': '説明していきます', 'start': 5.6, 'duration': 2.8}
...
print(seg['text'])
今取り出した1つの辞書からtextキーの値だけを画面に表示しています:
seg = {'text': 'こんにちは、今日は', 'start': 0.0, 'duration': 2.5}
↓
seg['text'] = 'こんにちは、今日は' ← これが表示される
実行してみる
仮想環境が有効になっていることを確認してから:
python 01_show_ja_subtitles.py
期待する結果
画面に字幕の文章が上から順にズラッと出てきます。
成功例:
こんにちは、今日は機械学習について説明します
データの前処理は重要なステップです
まず最初に、データを整理しましょう
...
🎊 おめでとうございます!まずは「日本語の字幕を出せた」という最初のゴールに到達です!
どうですか?思っていたより簡単だったでしょう?この小さな成功こそが、より複雑なアプリを作るための基盤となります。
Step 2: 同じ内容をファイルにも保存しよう
┌─────────────────────────────────────────────────────────┐
│ 📄 字幕ファイル保存システム │
├─────────────────────────────────────────────────────────┤
│ │
│ 字幕データ: [{'text': '...', 'start': 1.2}, ...] │
│ ↓ for文で処理 │
│ 📺 画面表示: print(text) │
│ 💾 ファイル保存: f.write(text + "\n") │
│ │
│ 結果: │
│ ✅ 画面に全文表示 │
│ ✅ transcript_ja.txt に保存完了 │
│ │
└─────────────────────────────────────────────────────────┘
前回は画面に表示できました。今度は「なぜファイル保存が必要なの?」という疑問にお答えしながら、保存機能を追加してみましょう。
画面に出すだけだと、後で使いづらいですよね。記事化・要約・検索などに活用するなら、テキストファイルとして残しておくと便利です。また、長い動画の字幕だと画面からスクロールして消えてしまうこともあります。
そこで登場するのが「ファイル保存」機能です。同じデータを画面にも出しつつ、ファイルにも残すことで、後からじっくり読み返したり、他のツールで処理したりできるようになります。
ファイル保存機能を追加してみよう
以下の内容で 02_save_ja_subtitles.py
というファイルを作成してください。
ファイル名: 02_save_ja_subtitles.py
from youtube_transcript_api import YouTubeTranscriptApi
VIDEO_ID = "zsg6FmfWhGI"
segments = YouTubeTranscriptApi.get_transcript(VIDEO_ID, languages=['ja'])
with open("transcript_ja.txt", "w", encoding="utf-8") as f:
for seg in segments:
line = seg['text']
print(line)
f.write(line + "\n")
このコードの読み解き
Step 1 からの変更点を中心に見ていきましょう。
with open("transcript_ja.txt", "w", encoding="utf-8") as f:
ここは「新しくファイルを開く」という行です。
"transcript_ja.txt"
はファイル名(このフォルダに作られます)"w"
は書き込みモードの印(write の頭文字)encoding="utf-8"
は日本語が文字化けしないための設定です
with ... as f
という書き方にすると、使い終わったら自動で閉じてくれるので安全です。これは Python のベストプラクティスの一つで、ファイルの閉じ忘れによるトラブルを防げます。
for seg in segments:
→ line = seg['text']
Step 1 と同じく、字幕のかたまりを1つずつ取り出して本文だけを line
という名前に入れています。変数名を line
にすることで、「1行のテキストデータ」という意味が分かりやすくなります。
print(line)
と f.write(line + "\n")
画面にも出しつつ、ファイルにも書くという2つの動きをしています。文字の最後に "\n"
を足しているのは、1行ごとに改行して読みやすくするためです。これがないと、全部の文章がつながって1行になってしまいます。
実行してみる
python 02_save_ja_subtitles.py
期待する結果
- 画面に Step 1 と同じように本文が出る
- 同じフォルダに
transcript_ja.txt
ができ、中身は字幕の全文
実行後、フォルダを確認してみてください。新しく transcript_ja.txt
というファイルができているはずです。このファイルをテキストエディタで開くと、字幕の全文が保存されているのが確認できます。
🎊 おめでとうございます!「表示」と「保存」の両方ができました!
これで、字幕データを後から活用できるようになりましたね。例えば、このテキストファイルを他の要約ツールに読み込ませたり、検索して特定の部分を見つけたりすることができます。
Step 3: 英語動画でわざと失敗
してみよう
┌─────────────────────────────────────────────────────────┐
│ ❌ 意図的な失敗体験システム │
├─────────────────────────────────────────────────────────┤
│ │
│ 動画ID: dQw4w9WgXcQ (英語動画) │
│ ↓ languages=['ja'] で日本語のみ要求 │
│ YouTube検索: 日本語字幕を探す... │
│ ↓ 見つからない! │
│ ❌ NoTranscriptFound エラー │
│ │
│ 💡 学習ポイント: │
│ 言語指定が厳格すぎると柔軟性がない │
│ │
└─────────────────────────────────────────────────────────┘
さて、今のコードは「日本語だけを見る」設定になっています。英語の動画に切り替えると落ちるはず。「え、わざと失敗させるの?」と思われるかもしれませんが、この失敗こそが、あとで改善するための大事な体験になるんです。
実際のプログラミング開発では、「想定していなかった状況」に遭遇することがよくあります。そんな時に慌てずに対処できるよう、今のうちに「失敗→原因分析→改善」の流れを体験しておきましょう。
僕も新しい技術を学ぶ時は、必ず「どんな時にエラーが出るのか」を確認してから本格的に使い始めます。これにより、後で同じ問題に遭遇しても冷静に対処できるようになるからです。
意図的にエラーを起こしてみよう
以下の内容で 03_en_fail.py
というファイルを作成してください。Step 2 からの変更点は動画ID だけです。
ファイル名: 03_en_fail.py
from youtube_transcript_api import YouTubeTranscriptApi
VIDEO_ID = "LxvErFkBXPk" # 英語の有名な動画
segments = YouTubeTranscriptApi.get_transcript(VIDEO_ID, languages=['ja'])
for seg in segments:
print(seg['text'])
実行してみる
python 03_en_fail.py
予想される結果
NoTranscriptFound
のようなエラーで止まります。
失敗例:
❌ python 03_en_fail.py
Traceback (most recent call last):
File "/Users/mitsutoshiyoshida/Desktop/youtube-summerizer/03_en_fail.py", line 5, in <module>
segments = YouTubeTranscriptApi.get_transcript(VIDEO_ID, languages=['ja'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
なぜこうなるの?
languages=['ja']
と書いているので、日本語字幕しか探していないからです。英語の動画には日本語字幕が無いことが多く、見つからないのでエラーになります。
OK!狙いどおりに失敗できました!
この体験により「言語指定が厳格すぎると、対応できない動画が出てくる」ということが理解できましたね。次のステップで、この問題を解決していきます。
⚠️ エラーが出なかった場合: もしエラーが出なかった場合は、その動画に日本語字幕が用意されている可能性があります。それはそれで正常な動作なので、別の英語動画のIDで試してみてください。
Step 4: 英語にも対応して成功させよう
┌─────────────────────────────────────────────────────────┐
│ 🌐 多言語対応字幕システム │
├─────────────────────────────────────────────────────────┤
│ │
│ 動画ID: LxvErFkBXPk │
│ ↓ languages=['ja','en','en-US','en-GB'] │
│ 優先度1: 日本語字幕を探す → なし │
│ 優先度2: 英語字幕を探す → あり! │
│ ↓ 英語字幕取得 │
│ 📺 画面表示 & 💾 ファイル保存 │
│ ↓ │
│ ✅ 成功!どんな動画でも対応可能 │
│ │
└─────────────────────────────────────────────────────────┘
前回は見事に失敗しました。今度はその問題を解決してみましょう。
探す言語の候補を増やすだけで解決できます。まず日本語を探し、無ければ英語(en
/ en-US
/ en-GB
)を順に探す、というフォールバックの考え方を使います。
「フォールバック」というのは、第一希望がダメなら第二希望、それもダメなら第三希望...というふうに代替案に落ちていく仕組みのことです。現実のWebアプリケーションではよく使われる考え方で、ユーザー体験を向上させる重要な技術です。
多言語対応版を作ってみよう
以下の内容で 04_support_en.py
というファイルを作成してください。
ファイル名: 04_support_en.py
from youtube_transcript_api import YouTubeTranscriptApi
VIDEO_ID = "LxvErFkBXPk"
segments = YouTubeTranscriptApi.get_transcript(
VIDEO_ID,
languages=['ja', 'en', 'en-US', 'en-GB']
)
with open("transcript.txt", "w", encoding="utf-8") as f:
for seg in segments:
line = seg['text']
print(line)
f.write(line + "\n")
このコードの読み解き
languages=['ja', 'en', 'en-US', 'en-GB']
「この順番で探して、見つかったらそれを使う」という意味です。まず日本語、無ければ標準英語、それもなければ米国英語、それもなければ英国英語...というふうに代替案に落ちていくので、フォールバック
と呼ばれます。
なぜこんなに英語の種類を入れているかというと、YouTubeでは字幕の言語コードが動画によって微妙に違うことがあるからです。en
で登録されている場合もあれば、en-US
で登録されている場合もあります。複数指定しておくことで、より多くの動画に対応できます。
あとは Step 2 と同じで、画面表示とファイル保存を同時に行っています。ファイル名を transcript.txt
(言語の指定なし)に変更したのは、日本語と英語のどちらが保存されるか分からないためです。
実行してみる
python 04_support_en.py
期待する結果
- 画面に英語字幕がズラッと表示
transcript.txt
に全文保存
成功例:
[MUSIC PLAYING]
[APPLAUSE AND CHEERING]
SUNDAR PICHAI: Hello, everyone.
Good morning.
Welcome to Google I/O.
We want to get our best
models into your hands
and our products, ASAP.
...
🎊 おめでとうございます!日本語だけでなく英語にも対応できました!
これで、日本語の動画でも英語の動画でも、柔軟に字幕を取得できるアプリが完成しました。「失敗から学んで改善する」という、プログラミングで最も重要なプロセスを体験できましたね。
⚠️ エラーが出た場合:
- ModuleNotFoundError
→ ライブラリが入っていません。pip install youtube-transcript-api
を実行
- NoTranscriptFound
→ その動画には字幕が一切ありません。別の動画IDで試してください
- VideoUnavailable
→ 動画が削除されているか非公開です
- 文字化け → encoding="utf-8"
が抜けていないか確認
今回学んだ重要なポイント
この段階的な学習で、以下の重要な概念を体得できました:
最小から始める重要性: いきなり完璧を目指さず、動く最小版から開始することで、問題の切り分けが容易になる
失敗からの学習: エラーを恐れるのではなく、意図的に失敗させることで、改善すべき点が明確になる
フォールバックの考え方: 第一希望がダメでも諦めず、段階的に代替案を試すことで、より多くの状況に対応できる
ファイル処理の基本: 画面表示だけでなく、ファイル保存も同時に行うことで、データの再利用性が向上する
言語コードの理解: ja
, en
, en-US
など、YouTubeの言語指定の仕組みを理解することで、国際的なアプリが作れる
次のStep 3では、このテキストデータをOpenAI APIに送信して、AI要約を生成する機能を作成していきます。今回作った基盤があるからこそ、次のステップがスムーズに進められますよ🤗