

# 長いYouTube講義で1つの概念の説明を見つける方法

字幕の時刻情報から、概念を探すための小さな索引を作ります。次に、候補となる各区間を動画で視聴します。語句の一致から、その概念への言及は見つかります。ただし、説明されていることまでは証明できません。

この索引は、目的の箇所へ移動するために自分で作るものです。動画の投稿者が作ったチャプター一覧ではありません。切り抜き動画でもありません。動画全体の要約でも、検索用に分割する単位を決める計画でもありません。

## 1. まず、学びたいことを質問文にする

文字起こしを調べる前に、質問を1文で書きます。知りたい概念を明記します。講師が使いそうな別の語句も挙げます。必要な回答の種類も明記します。

回答の種類は、次のように分けます。

- 定義：概念の意味や、その実践方法を示します。
- 解き方を示す具体例：1つの事例を手順に沿って解きます。
- 手順：行うことを順番に示します。
- 比較：2つの概念を並べて比べます。
- 限界：その概念を適用できる範囲の限界を示します。

「測定に言及している」と「測定方法を説明している」は、明確に区別します。どちらが必要なのかを、質問文に明記してください。

## 2. 字幕トラックを1つ取得する

字幕は、動画にあらかじめ保存されている、時刻情報付きのテキストです。文字起こしは、1本の動画の字幕をすべてまとめたものです。セグメントは、時刻情報付きの1行です。各セグメントには、テキスト、開始時刻、継続時間があります。継続時間とは、その行が続く長さです。

区間は、1つの概念について自分で選ぶ開始時刻と終了時刻の範囲です。セグメントを読んだ後で選びます。

Actorは、取得元のデータ行を収集する、ホスト環境で動くプログラムです。取得元のデータ行は、動画1本分の取得結果です。Taskは、保存済みの入力設定です。Actorが行うのはデータ行の収集だけです。そのデータ行から概念を調べる作業は、自分で行います。

YouTube Transcriptのバージョン0.1.43を使います。Actorは[YouTube Transcript Scraper](https://apify.com/chronometrica/youtube-transcript-scraper)です。公開Taskは[YouTube Transcript Data for Video Chapter Generation](https://apify.com/chronometrica/youtube-transcript-scraper/examples/youtube-chapters)です。

このTaskは、入力設定の出発点です。概念のラベルを付けてくれるものではありません。保存されている一覧はサンプル動画であり、自分が学ぶ講義ではありません。一覧全体を、内容を知っている公開講義動画1本に置き換えてください。サンプル一覧を学習対象にしないでください。そこから語句をコピーしないでください。

Actorには公開動画のURLを入力できます。11文字の動画IDも入力できます。IDは、動画を識別する短いコードです。入力は最大1,000件まで送信できます。この作業では、動画を1本だけ送信します。同じ動画IDを繰り返し入力しても、処理されるのは1回です。

開始URLには、通常の視聴リンク、youtu.beリンク、Shortsリンク、ライブ配信リンク、埋め込みリンクを使えます。埋め込みリンクは、別のページにプレーヤーを表示するためのリンクです。Actorは、チャンネル、再生リスト、検索ページから動画を探しません。

読み取るのは、[既存の公開字幕](/ja/articles/youtube-%E6%96%87%E5%AD%97%E8%B5%B7%E3%81%93%E3%81%97%E3%81%AE%E5%8F%96%E5%BE%97-%E5%AD%97%E5%B9%95%E3%81%AE%E7%A2%BA%E8%AA%8D/)だけです。音声から新しく文字起こしを作ることはありません。翻訳もしません。チャプター、ラベル、要約も作成しません。

英語の字幕トラックが必要な場合は、次の入力を使います。

```json
{
  "startUrls": ["https://www.youtube.com/watch?v=YOUR_PUBLIC_VIDEO"],
  "preferredLanguages": ["en"],
  "outputFormats": ["json"],
  "includeFailedInputDetails": true
}
```

2. 字幕トラックを1つ取得する

YOUR_PUBLIC_VIDEOを、内容を知っている公開動画に置き換えます。各セグメントの時刻情報を保持するには、`outputFormats`を`["json"]`にする必要があります。`preferredLanguages`を`["en"]`に設定すると、英語を要求します。英語がない場合は、その言語を利用できないことが結果に示されます。通知せずに別の言語を返すことはありません。

利用可能なものの中から最適な字幕トラックを取得したい場合は、言語リストを空にします。

```json
{
  "startUrls": ["https://www.youtube.com/watch?v=YOUR_PUBLIC_VIDEO"],
  "preferredLanguages": [],
  "outputFormats": ["json"],
  "includeFailedInputDetails": true
}
```

2. 字幕トラックを1つ取得する

リストを空にしても、英語になるとは限りません。実行後に必ず`transcriptLanguageCode`を確認します。失敗した入力を確認できるように、`includeFailedInputDetails`はtrueのままにします。

## 3. 検索する前に結果を確認する

取得元のデータ行で、次の名前の項目を確認します。フィールドとは、名前の付いた1つの値です。

- `videoId`
- `videoUrl`
- `transcriptLanguageCode`
- `isAutoGenerated`
- `segments`。各セグメントには`text`、`startSeconds`、`endSeconds`、`durationSeconds`があります。
- `segmentCount`
- `status`
- `statusReason`
- `scrapedAt`

`videoDurationSeconds`は欠損している場合があります。欠損は不明を意味します。不明な値を0と記録しないでください。

`isAutoGenerated`は、字幕トラックの作成方法を示します。Trueは、字幕が自動生成されたことを意味します。Falseは、人が字幕トラックを提供したことを意味します。手動の字幕トラックにも、誤った語句が含まれることがあります。動画の視聴による確認は、やはり必要です。

`status`は、その字幕の読み取りが成功したかどうかを示します。`statusReason`は、その理由を示します。`scrapedAt`は観測時刻です。動画ID、URL、言語、自動生成か手動かを示すフラグ、`scrapedAt`をメモと一緒に保存します。

次に、OUTPUTという名前の実行概要を確認します。

- `successfulTranscriptRows`
- `rowsWritten`
- `failedInputs`
- `statusCounts`
- `errorCodeCounts`
- `failedInputDetails`

失敗した入力は、文字起こしのデータ行にはなりません。`status`が成功を示していなければ、作業を止めます。要求した言語を利用できなければ、検索は未解決のままにします。テキストが一致しなくても、その概念が動画にないとは証明できません。語句が画面にだけ表示されている可能性があります。必要な言語の字幕トラックがない可能性もあります。字幕の読み取りが失敗した可能性もあります。この制約は、確認した字幕トラックだけに当てはまります。動画全体に当てはまるものではありません。

バージョン0.1.43のあるテストでは、特定の公開動画IDを1つ指定しました。文字起こしが1件返されました。字幕トラックは英語で、手動で作成されたものでした。時刻情報付きのセグメントが4,530件ありました。OUTPUTは成功を示し、失敗した入力はありませんでした。これで確認できるのは、その1つの取得元で時刻情報付きセグメントを取得できたことです。概念のラベルの正しさを証明するものではありません。語句が完全に正しいことも証明しません。すべての動画で同じ結果になることも証明しません。各区間を必ず動画と照合してください。

`transcriptSpanSeconds`と、最初と最後の時刻の値が示すのは、字幕トラックの範囲だけです。概念が最後まで説明されていることを証明するものではありません。

## 4. 元のセグメントをすべて保持する

元のセグメントをすべて保持します。字幕の各単語を、それぞれ独立した概念として扱わないでください。目的の概念と、先ほど挙げた別の語句を探します。見つかったら、その直前と直後のセグメントも読みます。

キーワード検索では、候補を見つけられます。候補とは、該当する可能性のある区間であり、確認済みの区間ではありません。検索だけで、検証済みのラベルが付くわけではありません。ラベルを書くのは、動画を視聴した後です。

## 5. 候補となる区間を決める

説明が始まる最初のセグメントを、区間の開始点にします。質問への回答が続いている最後のセグメントを、区間の終了点にします。

最後のセグメントについては、返された`endSeconds`を優先して使います。`durationSeconds`が分かっている場合は、`endSeconds`が`startSeconds`と`durationSeconds`の合計に等しいことを照合します。`endSeconds`が分かっていても、`durationSeconds`がnullの場合があります。nullはそのまま保持します。推測で0にしないでください。次のセグメントの開始時刻を終了時刻として使わないでください。セグメント同士は重なることがあります。間に空白があることもあります。最後の字幕の終了時刻は、動画の終了時刻ではありません。

必要な語句の定義が前のセグメントにある場合は、そのセグメントも含めます。定義される語句は、ある値の名称である場合もあります。講師が前の概念に戻って説明するときは、区間が重なっても構いません。動画全体を、途切れのない一連の区間に分ける必要はありません。

## 6. 動画を視聴し、回答にラベルを付ける

元の動画で、候補となる区間を開きます。話している言葉を聞きます。図、画面上のコード、参照先も確認します。これらは字幕に含まれていない場合があります。

次の簡単な分類から、ラベルを1つ付けます。

- `mention_only`は、概念に言及しているものの、説明はしていないことを意味します。
- `explains_definition`は、その区間で意味や方法を説明していることを意味します。
- `worked_example`は、その区間で1つの事例を手順に沿って解いていることを意味します。
- `comparison`は、その区間で物事を比較していることを意味します。
- `unresolved`は、今回の視聴では回答を確認できないことを意味します。

これらのラベルは、自分で内容を分類するためのものです。Actorの出力ではありません。その区間が学びたいことへの回答になる理由、または回答にならない理由を書きます。

## 7. 索引の1行を保存する

索引の1行は、確認した1区間について自分で書く記録です。次の項目を含めます。

- 概念のラベル
- 学びたいことを表す質問
- 動画IDとURL
- 字幕の言語
- 開始時刻と終了時刻の秒数
- 分と秒で表した開始時刻
- 説明の種類
- `checked_at`
- 根拠のメモ
- 確信度

終了時刻も保存します。確信度は、自分で明記する確認評価です。モデルが算出したスコアではありません。区間の境界が不明なら、不明のままにします。

## 8. 開始時刻へのリンクを開き、その区間で学ぶ

パソコンで「共有」を開き、次に「開始位置」を選びます。開始時刻を入力します。リンクをコピーします。コピーしたリンクを開きます。必要な文脈が分かる位置の近くから再生が始まることを確認します。この操作については、YouTubeの[動画やチャンネルを共有する](https://support.google.com/youtube/answer/57741?hl=en&ref_topic=9257102)で説明されています。

開始時刻へのリンクでは、再生の停止時刻は指定されません。終了時刻は索引に保存します。架空のサンプルURLを、再生できることを確認済みの動画として扱わないでください。

確認済みの区間を学習に使います。説明を確認できなければ、`no_confirmed_explanation_in_checked_track`と記録します。確認した字幕トラックを明記し、確認範囲を示すメモを添えます。その後、別のソースを調べます。不確かな字幕検索が1回うまくいかなかっただけで、動画全体に回答がないと判断しないでください。

## 架空の講義：庭の花壇の寸法を測る

以下は、この記事のために作った架空の例です。区間の時間計算を学ぶためのものです。Actorの取得結果ではありません。実在する動画URLもありません。この例へのリンクがあっても、再生できるものとして扱わないでください。

架空の講義の題名は「庭の花壇の寸法を測る」です。この架空の講義は12分間です。講義内容の区間は次のとおりです。

- 0秒から120秒：準備
- 120秒から330秒：測定の説明
- 330秒から570秒：計算の具体例
- 570秒から720秒：制約

幅の概念に関わる箇所には、次の3つの架空のセグメントがあります。

| 開始時刻（秒） | 継続時間（秒） | 終了時刻（秒） | テキスト |
| --- | --- | --- | --- |
| 120 | 30 | 150 | 内側の端から端までの幅を測ります |
| 150 | 45 | 195 | 長さと幅には同じ単位を使います |
| 300 | 30 | 330 | 測定値を記録する前に、読み取った値を確認します。 |

学びたいことを表す質問は、「幅を同じ単位で測るにはどうすればよいですか？」です。

120秒の行は、行うことを示しています。150秒の行は、単位を統一することを加えています。300秒の行で、方法の説明が終わります。そのため、定義を説明する区間には3行すべてを含めます。区間は120秒から330秒までです。

最後のセグメントの終了時刻：300 + 30 = 330秒。区間の長さ：330 - 120 = 210秒。210秒は3分30秒です。分と秒で表すと、開始時刻は2:00、終了時刻は5:30です。

この架空の講義を人が視聴して確認した後のラベルは、`explains_definition`です。根拠のメモには、内側の端が映されていると記されています。ラベルを確定する根拠になるのは、この視聴による確認です。セグメントのテキストだけでは確定できません。

計算の区間は、概念の種類が異なります。330秒から570秒までです。570 - 330 = 240秒。240秒は4:00です。分と秒で表した開始時刻は5:30です。`worked_example`のラベルを付けます。定義の区間にまとめないでください。

4つの講義区間の長さは、120秒、210秒、240秒、150秒です。120 + 210 + 240 + 150 = 720秒。これらを合わせると、この架空の講義全体を網羅します。時間全体を網羅していても、すべての概念が説明されているとは限りません。

「測定」という語は600秒にも出てきます。分と秒で表すと10:00です。この時刻は制約の区間内にあり、注意を促す内容です。`mention_only`、または限界を示す内容として記録します。主となる定義の開始時刻を600秒に移さないでください。

この架空の例には、人が判断する必要のある境界がもう1つあります。あるセグメントが310秒に始まり、30秒間続きます。終了時刻は310 + 30 = 340秒です。次の区間は330秒に始まります。340 - 330 = 10秒が重複します。この重複を残すか、視聴した後で境界を移します。境界をきれいにそろえるためだけに、330秒で言葉を途中で切らないでください。

この例では実際の字幕トラックを読み取っていないため、`scrapedAt`は不明です。`videoDurationSeconds`も不明です。720秒という値は、架空の区間の長さから得たものです。動画の長さを示すフィールドの値ではありません。不明なものは不明のままにします。

### 架空の4区間の時間計算

| 内容 | 開始時刻（秒） | 終了時刻（秒） | 長さ |
| --- | --- | --- | --- |
| 準備 | 0 | 120 | 120 |
| 幅の定義 | 120 | 330 | 330 - 120 = 210 |
| 計算 | 330 | 570 | 570 - 330 = 240 |
| 制約 | 570 | 720 | 720 - 570 = 150 |
| 合計 | 0 | 720 | 120 + 210 + 240 + 150 = 720 |

### 同じ架空の例で、区間の境界などの判断が必要になるケース

| ケース | 計算 | 判断 |
| --- | --- | --- |
| 定義を説明する最後のセグメント | 300 + 30 = 330 | この終了時刻を、幅の区間の終了点にします。 |
| 330秒を超える重複 | 310 + 30 = 340、かつ340 - 330 = 10 | 10秒の重複を残すか、視聴後に変更します。 |
| 後半の600秒に出てくる語句 | 600は570から720の範囲内 | 限界に関する`mention_only`です。定義ではありません。 |

### 確認済みの架空の索引

| 概念 | 学びたいことを表す質問 | 動画 | 字幕の言語 | 開始時刻（秒） | 終了時刻（秒） | 開始時刻 | 終了時刻 | 種類 | 確認日時 | 根拠のメモ | 確認評価 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 講義の準備 | 測定前に何をしますか？ | 架空の題名のみ。実在するURLはありません。 | en、説明用のラベルのみ | 0 | 120 | 0:00 | 2:00 | unresolved | 説明用の確認のみ | 準備という名称が付いています。セグメントのテキストが示されていないため、その内容は未確認です。 | 視聴するまで不明 |
| 同じ単位で測る幅 | 幅を同じ単位で測るにはどうすればよいですか？ | 架空の題名のみ。実在するURLはありません。 | en、説明用のラベルのみ | 120 | 330 | 2:00 | 5:30 | explains_definition | 説明用の確認のみ | 最後の終了時刻は300 + 30 = 330。視聴メモ：内側の端が映されています。 | この架空の例での確認では確定 |
| 花壇の計算 | 1つの計算をどのように示していますか？ | 架空の題名のみ。実在するURLはありません。 | en、説明用のラベルのみ | 330 | 570 | 5:30 | 9:30 | worked_example | 説明用の確認のみ | 別の種類です。570 - 330 = 240秒、つまり4:00です。 | 具体例であることのみ確認済み |
| 後半の測定に関する注意 | 後半に出てくる語句は、幅を説明していますか？ | 架空の題名のみ。実在するURLはありません。 | en、説明用のラベルのみ | 570 | 720 | 9:30 | 12:00 | mention_only | 説明用の確認のみ | 600秒では、その語句は注意を促す内容に含まれています。限界を示す内容として記録します。 | 言及のみ |

幅についての質問には、120秒から330秒の行を選びます。2:00から視聴し、5:30を確認の終了時刻とします。開始時刻へのリンク、終了時刻、根拠のメモを保存します。この架空の行には、実在するリンクはありません。実際の動画では、「共有」、次に「開始位置」を使い、コピーしたリンクを開いて、見た内容を記録します。

この架空の例には、学習速度を測定した結果はありません。数値は、区間の時間計算を学ぶためだけのものです。

## 次に行うこと

サンプル一覧全体を、内容を知っている公開講義動画1本に置き換えます。[YouTube Transcript Scraper](https://apify.com/chronometrica/youtube-transcript-scraper) Actorの[YouTube Transcript Data for Video Chapter Generation](https://apify.com/chronometrica/youtube-transcript-scraper/examples/youtube-chapters) Taskを使います。`outputFormats`を`["json"]`に設定します。元の動画で、候補となる区間を1つ視聴します。その開始時刻へのリンク、終了時刻、短い根拠のメモを保存します。

## 出典と参考資料

- [YouTube Transcript Scraper](https://apify.com/chronometrica/youtube-transcript-scraper)
- [YouTube Transcript Data for Video Chapter Generation](https://apify.com/chronometrica/youtube-transcript-scraper/examples/youtube-chapters)
- [動画やチャンネルを共有する](https://support.google.com/youtube/answer/57741?hl=en&ref_topic=9257102)
- [長い講義動画についての体験メモ](https://www.reddit.com/r/chrome_extensions/comments/1vhu5aj/built_a_lightweight_extension_that_attaches/)