问答
怎么拿到带时间戳的 YouTube 字幕,导出成 JSON 或 SRT?
简短回答
YouTube 视频字幕接口会把每一行字幕作为一个分段返回,带 start 和 end(单位秒),另附全文,每个视频 $0.004。JSON 可以直接存,也可以用十几行 Python 写成 SRT;时间戳不另外收费。
做播客切片的剪辑想找出嘉宾提到某个产品的所有地方,每处配一个能直接跳到那一秒的链接。光有文字稿不够,还得知道每句话是什么时候说的。YouTube 视频字幕在同一次调用里就把时间一起返回了。
JSON 长这样
字幕在响应的 data.item 里:
{
"video_id": "dQw4w9WgXcQ",
"lang": "en",
"text": "We're no strangers to love ...",
"segments": [
{ "start": 18.64, "end": 21.88, "text": "We're no strangers to love" },
{ "start": 22.64, "end": 26.92, "text": "You know the rules and so do I" }
]
}
时间是从视频开头算起的秒数。有些库给的是 duration,换算一下就是 end - start。
分段转成 SRT
import os, requests
body = requests.get(
"https://api.okdata.online/v1/youtube/videos/transcript/get",
headers={"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"},
params={"id": "dQw4w9WgXcQ", "lang": "en"}, timeout=60,
).json()
segments = body["data"]["item"]["segments"]
def srt_time(sec):
ms = int(round(sec * 1000))
return f"{ms // 3_600_000:02}:{ms // 60_000 % 60:02}:{ms // 1000 % 60:02},{ms % 1000:03}"
with open("dQw4w9WgXcQ.srt", "w", encoding="utf-8") as f:
for n, s in enumerate(segments, 1):
f.write(f"{n}\n{srt_time(s['start'])} --> {srt_time(s['end'])}\n{s['text']}\n\n")
要 WebVTT 的话,文件开头写 WEBVTT,毫秒前面的逗号换成点。
生成跳到某一秒的链接
https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=18s 会从第 18 秒开始播放。把 start 向下取整,AI 从字幕里摘出的每一句引用后面都能挂一个可点的出处,摘要对不对,点一下就知道。
价格
| 任务 | 费用 |
|---|---|
| 一个视频,文字加时间 | $0.004 |
| 100 期节目的存档 | $0.40 |
| 1,000 个视频 | $4.00 |
每份字幕都自带时间。没有字幕的视频返回 not_found,不扣费。
交付文件前要知道的事
- 自动字幕的分段经常重叠,上一行还没结束下一行就开始了。播放器报错的话,把每段的
end截到下一段的start。 - 分段是按 YouTube 切字幕的方式来的,都很短,和句子边界对不上。引用整句话之前,先把相邻分段拼起来。
- 接口收的是 11 位视频 ID,不收链接。
- 不返回样式、位置和说话人,只有文字和时间。
其他拿带时间字幕的办法
- 在你的网络上 yt-dlp 没被拦的话,
--write-subs --convert-subs srt能直接写出文件。 - 自己频道的视频,官方 Data API 可以通过
tfmt下载 SRT 格式的字幕。 - 视频没有字幕时,对你有权使用的音频跑 Whisper,也能得到带时间戳的文字。
整个频道批量处理的做法和费用见视频转文字方案。
更新于