# 怎么用 YouTube 视频字幕做一个 RAG 问答机器人？

> 按主题收集 YouTube 视频，拉取带时间戳的字幕，按时间切块，回答时直接链接到视频里的那一秒。流程、费用和 Python 代码。

网页版：https://okdata.online/zh/answers/youtube-transcripts-rag-chatbot/

**简短回答：**先用 YouTube 视频搜索找到要收录的视频（每页约 20 条，$0.004），再逐个拉取带时间戳的字幕（每个视频 $0.004），按时间窗口切块后存进任意向量库。收录 200 个视频大约花 $0.84，每个回答都能链接到出处的那一秒。

一家做健身教练培训的公司，自己有 200 个长视频，都是教练在回答学员问题，另外还想收进同行里讲得最好的一批演讲。他们要的机器人是这样的：有人问大重量深蹲前怎么热身，它用两句话回答，再给一个链接，点开直接跳到某个视频的 14:32。这就是一条 RAG 流水线，只多一个讲究：时间戳要从头保留到尾，因为一个能跳到那一刻的链接，比一段总结更有用。

## 整体流程

1. **收集视频 ID。** 用 [YouTube 视频搜索](/zh/apis/youtube/videos/search/)按主题关键词搜，或者用频道名加主题词搜。目前没有列出某个频道全部视频的接口，自己的频道可以直接从 YouTube Studio 里复制视频 ID。
2. **拉字幕。** [YouTube 视频字幕](/zh/apis/youtube/videos/transcript/get/)接收 11 位视频 ID 和可选的 `lang`，返回 `segments`（开始时间、结束时间、文字）和完整的 `text`。
3. **按时间切块。** 把相邻片段合并成 60 到 90 秒的窗口，每块都带上 `video_id`、标题和窗口的起始秒数。
4. **向量化入库。** 用你现成的工具就行：LlamaIndex、LangChain、pgvector、Qdrant 都可以。
5. **回答带出处。** 用块里的元数据拼出 `https://youtu.be/<id>?t=<起始秒>`，要求模型在回答里引用。

## 第 1 到 3 步的 Python 代码

```python
import json, os, requests

API = "https://api.okdata.online"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}

def get(path, **params):
    body = requests.get(API + path, headers=H, params=params, timeout=90).json()
    if body["code"] != "ok":
        raise RuntimeError(f"{body['code']}: {body['message']}")
    return body["data"]

videos = get("/v1/youtube/videos/search", query="squat warm up coaching",
             fields="id,title,url")["items"]

with open("chunks.jsonl", "w", encoding="utf-8") as out:
    for v in videos:
        try:
            tr = get("/v1/youtube/videos/transcript/get", id=v["id"], lang="en")["item"]
        except RuntimeError as err:  # 没字幕、私密、已删除：都不扣费
            print("跳过", v["id"], err)
            continue
        window, start = [], None
        for seg in tr["segments"]:
            start = seg["start"] if start is None else start
            window.append(seg["text"])
            if seg["end"] - start >= 75:
                out.write(json.dumps({"video_id": v["id"], "title": v["title"], "start": int(start),
                                      "text": " ".join(window)}, ensure_ascii=False) + "\n")
                window, start = [], None
        if window:
            out.write(json.dumps({"video_id": v["id"], "title": v["title"], "start": int(start),
                                  "text": " ".join(window)}, ensure_ascii=False) + "\n")
```

`chunks.jsonl` 里的每一行都可以直接拿去做向量化。

## 收录要花多少

| 知识库规模 | 调用次数 | 费用 |
|---|---|---|
| 50 个视频 | 搜 3 次 + 50 份字幕 | $0.212 |
| 200 个视频 | 搜 10 次 + 200 份字幕 | $0.84 |
| 1,000 个视频 | 搜 50 次 + 1,000 份字幕 | $4.20 |

更新比新建便宜得多：每月跑一次，只给还没入库的视频 ID 拉字幕。

## 容易出问题的地方

- 自动生成的字幕常把人名和术语听错。在回答的提示词里放一份术语表，或者入库前先替换掉。
- 没有字幕的视频会调用失败，不扣费。这些视频如果重要，要另外对音频做转写。
- 用 `lang` 指定你入库的语言，一个索引里混着几种语言会拖累检索效果。
- 字幕的版权属于创作者。内部用来答疑问题不大，原样转载发布就是另一回事了。

## 其他做法

LlamaIndex 的 YoutubeTranscriptReader 和 LangChain 的 YoutubeLoader 免费，底层都是 youtube-transcript-api。在自己电脑上跑效果不错，但在云服务器和 Serverless 环境里，它们的 issue 里有很多被封 IP、拿不到字幕的反馈。如果是你自己的频道，YouTube Studio 和 YouTube Data API 能拿到你上传过的字幕。完全没有字幕的视频，可以下载音频用 Whisper 转写，代价是下载和算力。这类需求的更多做法见[视频转文字方案](/zh/solutions/transcripts/)。

## 用到的接口

- [YouTube 视频搜索](https://okdata.online/zh/apis/youtube/videos/search/) `youtube.videos.search`：$0.004/次 · 每页约 20 条视频
- [YouTube 视频字幕](https://okdata.online/zh/apis/youtube/videos/transcript/get/) `youtube.videos.transcript.get`：$0.004/次

更新于 2026-11-12
