问答

几百个 YouTube 视频的字幕怎么批量下载?

简短回答

把视频 ID 列成清单,开几个并发逐个调用 YouTube 视频字幕接口;和 YouTube 打交道的是 okdata,你这边没有 IP 会被封。每份字幕 $0.004,1,000 个视频最多 $4.00,没有字幕的视频不收费。

一位做传播研究的老师手里有一张 800 个讲座视频的表格,想在周五前把字幕都放进一个文件。用 youtube-transcript-api 跑,几十个视频之后就报 429 Too Many Requests,大家加的重试逻辑又往往对着同一个 IP 继续猛发。这种规模的批量任务要准备好三样东西:一份干净的 ID 清单,一个懂得退让的客户端,以及断点续跑。

第一步:拿到 ID 清单

  • 手里已经有链接。 取 v= 后面的值,或者 youtu.be/、/shorts/ 后面那一段。字幕接口要的是 11 位视频 ID。
  • 手里只有一个主题。 YouTube 视频搜索每页返回约 20 个视频,带播放量和频道,凑 100 个候选花 $0.02。
  • 手里有一个频道。 官方 Data API 对频道的上传列表调用 playlistItems.list,每页最多 50 个视频,只消耗 1 个配额单位,列出整个频道这样最省。

第二步:能续跑的脚本

import json, os, time, requests
from concurrent.futures import ThreadPoolExecutor

URL = "https://api.okdata.online/v1/youtube/videos/transcript/get"
KEY = os.environ["OKDATA_API_KEY"]
OUT = "transcripts.jsonl"

def fetch(vid):
    while True:
        r = requests.get(URL, params={"id": vid}, timeout=90, headers={
            "Authorization": f"Bearer {KEY}", "Idempotency-Key": f"transcript-{vid}"})
        body = r.json()
        if body["code"] == "rate_limited":
            time.sleep(body.get("retry_after_seconds") or 2)
            continue
        return vid, body

ids = [line.strip() for line in open("video_ids.txt") if line.strip()]
done = {json.loads(l)["video_id"] for l in open(OUT)} if os.path.exists(OUT) else set()

with ThreadPoolExecutor(max_workers=4) as pool, open(OUT, "a", encoding="utf-8") as out:
    for vid, body in pool.map(fetch, [i for i in ids if i not in done]):
        if body["code"] == "ok":
            out.write(json.dumps(body["data"]["item"], ensure_ascii=False) + "\n")
        else:
            print(vid, body["code"])  # not_found 表示没有字幕,不扣费

中途崩了就再跑一遍,已经拿到的视频会跳过。带上 Idempotency-Key 之后,24 小时内重试一个其实已经成功的请求,会直接返回原结果,不会扣两次钱。

整批要花多少

批量 最多花费
100 个视频 $0.40
800 个视频 $3.20
1,000 个视频 $4.00

没有字幕的视频和出错的请求都不收费,实际账单只会更低。新 key 自带 0.10 的额度,够先拿一小部分视频把脚本跑通。

限制

  • 4 个并发是比较稳妥的起点。key 的突发上限写在 X-RateLimit-Limit 响应头里,rate_limited 不扣费。
  • 不做语音转文字,没有字幕的视频要对你有权使用的音频跑 Whisper。
  • 每次调用只返回一种语言,以响应里的 lang 为准。

什么情况换个做法

量小、偶尔跑一次的,在家里的网络上用 youtube-transcript-api,每次调用之间停一停,通常能跑完。自己频道的视频,用官方 API 直接下载字幕文件。从搜索到摘要的完整流程,见视频转文字方案。

更新于