mcpField
Y
youtube-transcript

youtube-transcript

github.com/davidondrej生产力4.2k205 次安装今天更新
代码仓库

关于 youtube-transcript

youtube-transcript 是一项获取 YouTube 视频字幕并保存为纯文本的技能,优先使用 DeepAPI,失败时可改用 yt-dlp,也可提取带时间信息的字幕片段。

主要功能

  1. 01通过 DeepAPI 获取字幕
  2. 02使用 yt-dlp 作为备用方案
  3. 03保存清理后的字幕文本
  4. 04提取带时间信息的字幕片段
  5. 05指定字幕语言

适用场景

  1. 01将视频字幕保存到项目目录
  2. 02生成用于审阅的字幕文本
  3. 03获取带时间戳的字幕片段
  4. 04DeepAPI 不可用时继续获取字幕

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/davidondrej/skills --skill youtube-transcript

安装后在 Claude Code 中输入/youtube-transcript确认已加载。

详细介绍

YouTube 字幕转录(通过 DeepAPI,yt-dlp 作为后备方案)

获取 YouTube 视频的字幕转录,并保存为干净的原始 .txt 文件。首选方式是 DeepAPI POST /v1/scrape/youtube/transcript。该操作在服务端运行,因此可避免 yt-dlp 常见的本地 IP 机器人标记问题。

保存位置

  • 如果用户当前在一个实际的项目/工作目录中 → 保存到该目录。
  • 否则(未指定目录,或当前工作目录不合适)→ 保存到 ~/Downloads。
  • 文件名始终使用 Channel_Title,并将空格替换为 _(例如:David_Ondrej_title_of_video.txt)。如果无法获取元数据,则使用视频 ID。

首选方式 — DeepAPI

从环境变量中读取密钥;设置过程会将其写入 ~/.deepapi/env。切勿执行 source ~/.zshrc(会导致 shell 出错,退出码为 126):

[ -n "$DEEPAPI_API_KEY" ] || . ~/.deepapi/env
KEY=$DEEPAPI_API_KEY
BASE=${DEEPAPI_API_BASE_URL:-https://deepapi.co}

运行抓取操作(保留 Idempotency-Key;重试时必须使用同一个值):

IDK=$(uuidgen)
curl -s --max-time 120 "$BASE/v1/scrape/youtube/transcript" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDK" \
  -d '{"url": "VIDEO_URL", "maxCostUsd": "0.05", "waitForFinishSecs": 60}' \
  > /tmp/yt_transcript.json
  • 非英语视频:在请求体中添加 "language": "de"(或其他语言代码)。
  • status: running → 等待 next.afterSecs 指定的时间,然后运行 curl "$BASE$(jq -r '.next.path' /tmp/yt_transcript.json)" -H "Authorization: Bearer $KEY",直到状态变为 succeeded 或 failed。

提取文本并保存:

jq -r '.status' /tmp/yt_transcript.json                # succeeded | running | failed
jq -r '.output[0].text' /tmp/yt_transcript.json > "$OUT/$NAME.txt"

.output[0].segments 还包含带时间戳的片段(startSecs、durationSecs、text),如果用户需要时间戳可使用这些内容。output 为空表示视频没有字幕;告知用户,不要重试。

要生成 Channel_Title 文件名,可使用 yt-dlp --print "%(channel)s|%(title)s" --skip-download "URL" 快速获取元数据;如果失败,则使用视频 ID。

何时改用 yt-dlp

  • 未设置 DEEPAPI_API_KEY,且 ~/.deepapi/env 不存在。
  • HTTP 402 insufficient_credits(告知用户先前往 deepapi.co/credits 充值;只有在用户无法充值时才改用后备方案)。
  • DeepAPI 请求连续两次 failed。

每次改用后备方案时都要告知用户——这意味着 DeepAPI 未能满足一个实际使用场景。

后备方案 — yt-dlp(本地)

OUT="$(pwd)"            # or ~/Downloads if cwd makes no sense
META=$(yt-dlp --print "%(channel)s|%(title)s" --skip-download "URL")
NAME=$(echo "$META" | tr '| ' '__' | tr -cd '[:alnum:]_.-')   # "Channel_Title", spaces -> _, strip unsafe chars
yt-dlp --skip-download --write-subs --write-auto-subs \
  --sub-langs "en.*" --sub-format json3 \
  -o "$OUT/$NAME.%(ext)s" "URL"
  • 如果 channel 为 null,则依次改用 uploader → uploader_id。
  • --skip-download = 仅获取字幕。--write-subs + --write-auto-subs = 优先使用人工字幕,无可用时再使用自动字幕。
  • 始终使用 json3,绝不使用 VTT/SRT——自动生成的 VTT 会将每行重复两次(滚动字幕)。

将 json3 展平为原始文本:

python3 - "$OUT" <<'PY'
import json, html, re, glob, sys, pathlib
f = glob.glob(sys.argv[1] + "/*.json3")
if not f: sys.exit("no json3 file")
data = json.load(open(f[0], encoding="utf-8"))
parts = ["".join(s.get("utf8","") for s in e.get("segs") or []) for e in data.get("events", [])]
txt = re.sub(r"\s+", " ", html.unescape(" ".join(p.strip() for p in parts if p.strip()))).strip()
out = pathlib.Path(f[0]).with_suffix(".txt")
out.write_text(txt, encoding="utf-8"); print(out)
PY
yt-dlp 失败处理
  • 非英语/语言未知:先运行 yt-dlp --list-subs "URL",然后设置 --sub-langs。
  • 较新版本的 yt-dlp 可能需要将 deno 添加到 PATH,才能提取 YouTube 内容。
  • 首次失败时:运行一次 yt-dlp -U,重试一次,然后停止。
  • 429 / "Sign in to confirm you're not a bot" = IP 已被标记。立即停止——不要循环重试(情况会更糟)。
  • 除非用户明确要求,否则绝不改为下载音频并使用 Whisper。

输出

报告保存路径;如果文本较短,则打印文本。除非用户询问,否则不要报告费用。

评论

支持 Markdown