通过逆向 DownSub.com 前端 API,实现的 YouTube 字幕下载命令行工具。
- ✅ 单视频下载 — 下载任意 YouTube 视频的字幕
- ✅ 播放列表下载 — 一键下载整个播放列表的字幕(支持 100+ 视频)
- ✅ 多格式支持 — SRT / VTT / TXT 三种字幕格式
- ✅ 多语言 — 支持所有 YouTube 提供的字幕语言
- ✅ 自动翻译字幕 — 下载 YouTube 自动生成的字幕
- ✅ 双语字幕 — 同时下载两种语言
- ✅ 失败重试 — 自动重试临时错误(503/429),失败记录可单独重试
- ✅ 备选下载源 — DownSub 失败时自动切换到 yt-dlp 直下字幕
- ✅ SSL 代理兼容 — 支持 Clash 等代理环境
用户输入 YouTube URL
↓
解析 URL → 提取 videoId / playlistId
↓
AES-256-CBC 加密 ID(兼容 DownSub 前端加密)
↓
调用 DownSub API → 获取字幕列表
↓
构建下载 URL → 下载字幕文件
核心是通过逆向 DownSub 前端的 JavaScript 代码,复现了其 AES 加密流程和 API 调用逻辑,不依赖浏览器,也不依赖 DownSub 网站本身。
- Python 3.10+
- pip
# 1. 安装依赖
pip install -r downsub_crawler/requirements.txt
# 2. 验证安装
python -m downsub_crawler --helpyt-dlp — 用于两个场景:
- 播放列表枚举:获取超过 50 个视频的大播放列表(DownSub API 分页有 Bug)
- 备选字幕下载:当 DownSub 下载失败时自动切换
pip install yt-dlp
# yt-dlp 不是必须的,未安装时自动回退到 DownSub APIpython -m downsub_crawler "https://www.youtube.com/watch?v=dQw4w9WgXcQ"默认下载所有语言,保存到当前目录的 .srt 文件。
python -m downsub_crawler \
"https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" \
--lang en --format txt -o ./subtitles| 参数 | 简写 | 说明 |
|---|---|---|
url |
— | YouTube 视频/播放列表 URL(--retry-failed 模式下可选) |
--lang |
-l |
字幕语言代码,如 en、zh、ja(默认全部) |
--output |
-o |
输出目录(默认当前目录) |
--format |
-f |
字幕格式:srt、vtt、txt(默认 srt) |
--list-langs |
— | 仅列出可用语言,不下载 |
--bilingual |
— | 下载双语字幕 |
--playlist |
-p |
强制以播放列表模式下载 |
--max-videos |
-m |
最多下载前 N 个视频(0=全部) |
--retry-failed |
— | 读取 retry_failed.json 重试失败视频 |
--ytdlp-cookies |
— | cookies.txt 文件路径(用于 yt-dlp 绕过 YouTube bot 检测) |
--ytdlp-cookies-browser |
— | 从浏览器读取 cookies,如 chrome、edge、brave |
--verbose |
-v |
显示详细日志 |
--verbose |
-v |
显示详细日志 |
--debug |
— | 显示调试日志 |
指定语言和格式:
python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --lang zh --format vtt指定输出目录:
python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --lang en -o ./subtitles列出可用语言(不下载):
python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --list-langs下载播放列表前 10 个视频:
python -m downsub_crawler \
"https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" \
--lang en --format txt --max-videos 10 -o ./subtitles下载双语字幕(英文 + 中文):
python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ" --bilingual使用 cookies 绕过 bot 检测:
# 方式 A:使用 cookies.txt 文件
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies ./cookies.txt
# 方式 B:直接从 Chrome 读取 cookies
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser chrome如果你的环境通过代理(如 Clash)上网,Python 的 requests 库可能遇到 SSL 错误。
# 方案 1:使用 curl 替代 requests(推荐)
DOWNSUB_USE_CURL=1 python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ"
# 方案 2:自动回退(不设置环境变量,requests 失败会自动切 curl)
python -m downsub_crawler "https://youtu.be/dQw4w9WgXcQ"下载播放列表时,临时失败(503/SSL 错误)的视频会自动记录:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
总计: 110 | ✓ 88 | ✗ 22 | 耗时 33:12
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ 22 个视频下载失败
失败记录已保存: subtitles/retry_failed.json
重试命令:
python -m downsub_crawler --retry-failed subtitles/retry_failed.json --lang en --format txt -o subtitles
使用 --retry-failed 重试失败视频:
# 单独重试失败的视频(不重新下载已成功的)
python -m downsub_crawler --retry-failed ./subtitles/retry_failed.json --lang en --format txt -o ./subtitlesretry_failed.json 文件格式:
[
{
"url": "https://www.youtube.com/watch?v=1GI2uB5CpnE",
"title": "Video Title",
"reason": "503 Server Error",
"index": 4,
"timestamp": "2026-06-07T12:34:56"
}
]当 DownSub API 下载失败时(如 503 错误),程序会自动尝试用 yt-dlp 直接从 YouTube 下载字幕。
# 确保 yt-dlp 已安装
pip install yt-dlp
# 正常运行即可,备选下载会在 DownSub 失败时自动触发
DOWNSUB_USE_CURL=1 python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en注意: YouTube 可能对程序化访问有 bot 检测,导致备选下载失败。解决方法见下方的 yt-dlp Cookies 配置指南。
当 yt-dlp 报 "Sign in to confirm you're not a bot" 错误时,需要提供浏览器 cookies 来证明你是人类用户。
步骤 1:安装 cookies 导出扩展
在 Chrome 浏览器中安装以下任一扩展:
- Get cookies.txt LOCALLY(推荐,数据不离开本地)
- cookies.txt(简单直接)
步骤 2:登录 YouTube
在 Chrome 中访问 youtube.com 并登录你的 Google 账号(如果有的话)。
步骤 3:导出 cookies
点击扩展图标 → 选择 Export → 将文件保存为 cookies.txt
⚠️ 确保只导出了youtube.com的 cookies。一些扩展允许按域名筛选。
步骤 4:将 cookies.txt 放到 WSL 中
Windows 的 Chrome 下载目录通常可以通过 WSL 访问:
# 方法 A:直接从 Windows 下载目录复制
cp /mnt/c/Users/btroops/Downloads/cookies.txt ~/coding/cookies.txt
# 方法 B:直接放到项目目录
# 在 Windows 文件管理器中,将 cookies.txt 复制到 \\wsl.localhost\Ubuntu\home\btroops\coding\步骤 5:使用 cookies 运行爬虫
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies ~/coding/cookies.txt如果一切正常,yt-dlp 备选下载就能绕过 bot 检测,成功下载字幕。
步骤 6(可选):验证 cookies 是否生效
yt-dlp --cookies ~/coding/cookies.txt --write-sub --sub-lang en --skip-download \
--convert-subs srt --print after_move:filepath "https://www.youtube.com/watch?v=1GI2uB5CpnE"没有 "Sign in to confirm" 错误即为成功。
⚠️ 安全提示: cookies.txt 包含你的登录凭证,不要分享给他人,用完可删除。⚠️ 有效期: YouTube cookies 大约 6-12 个月有效,过期后重新导出一份即可。
如果你在 WSL 中安装了 Chrome/Edge,yt-dlp 可以直接读取浏览器的 cookies:
# 从 Chrome 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser chrome
# 从 Edge 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser edge
# 从 Brave 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser brave注意: 在 WSL 中,这只对安装在 Linux 端的浏览器有效。Windows 端的 Chrome 无法直接被 WSL 读取。
如果扩展导出不方便,可以手动创建一个包含最少必要 cookies 的 cookies.txt 文件。
格式为 Netscape cookie 格式:
# Netscape HTTP Cookie File
.youtube.com TRUE / TRUE 0 CONSENT YES+shp.gws-20250606+1
最少需要的字段:CONSENT cookie(用于绕过 YouTube 的年龄/地区确认)。
从浏览器开发者工具中获取:
- 打开 YouTube,按 F12 打开 DevTools
- 进入 Application → Storage → Cookies →
https://www.youtube.com - 找到
CONSENT和__Secure-3PSID等关键 cookie - 按 Netscape 格式写入 cookies.txt
如果 Chrome 安装在 Windows 端,可以用以下方法让 WSL 中的 yt-dlp 读取它:
# 安装 WSL 的 chrome 读取工具
sudo apt install python3-pip
pip install browsercookie
# 或者使用 yt-dlp 的 Windows 路径映射
# 启动 yt-dlp 时指定 Windows Chrome 的 cookie 路径
yt-dlp --cookies "/mnt/c/Users/btroops/AppData/Local/Google/Chrome/User Data/Default/Cookies" ...但这种方式需要解密 Chrome 的加密 cookie 存储,比较复杂。推荐使用方式一(扩展导出)。
Q: 导出的 cookies.txt 不起作用?
- 确保导出前已登录 YouTube
- 确保 cookies.txt 是 Netscape 格式(扩展导出默认就是)
- 检查文件路径是否正确:
--ytdlp-cookies $(pwd)/cookies.txt
Q: 使用 cookies 后仍然被检测?
- YouTube 有时会对新 IP 进行额外验证
- 尝试使用
--ytdlp-cookies-browser chrome方式 - 如果都不行,可能是代理 IP 被 YouTube 标记,尝试关闭代理
Q: cookies 会不会泄露?
- cookies.txt 包含你的登录凭证,用完即删
- 不要提交到 Git:
# 添加到 .gitignore
echo "cookies.txt" >> .gitignore当 URL 中包含 list= 参数时,自动以播放列表模式运行:
# 以下两条命令等效
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --playlist --lang en如果 URL 中含有 list= 但只想下载当前视频,可以手动指定 --max-videos 1。
subtitles/
├── retry_failed.json # 失败记录(仅失败时生成)
├── 播放列表标题/ # 播放列表模式
│ ├── 01_视频标题_en.txt
│ ├── 02_视频标题_en.txt
│ └── ...
└── (单视频模式直接输出到根目录)
{序号}_{视频标题}_{语言代码}.{格式}
│ │ │ │
├─ 序号(播放列表模式才有,如 01_、02_)
├─ 视频标题(安全文件名,最长 100 字符)
├─ 语言代码(如 en、zh,重复时自动加 _auto/_orig)
└─ 文件扩展名(srt/vtt/txt)
如果同一视频同时有原始字幕和自动翻译字幕(相同语言代码),文件名会自动区分:
视频标题_en.txt— 原始字幕视频标题_en_auto.txt— 自动翻译字幕视频标题_en_orig.txt— 如果en出现三次以上
现象: requests 报 SSL 错误,程序自动重试后失败。
解决:
DOWNSUB_USE_CURL=1 python -m downsub_crawler "https://www.youtube.com/watch?v=dQw4w9WgXcQ"设置环境变量后使用 curl 命令行发送请求,绕过 Python 的 SSL 问题。
现象: 下载过程中出现 503 Server Error。
原因: DownSub 后端依赖 YouTube API,有频率限制。
解决:
- 程序会自动重试 5 次(指数退避,从 1s 到 16s)
- 大部分 503 重试后可恢复
- 如果始终失败,使用
--retry-failed稍后重试
现象: 429 Too Many Requests。
原因: DownSub API 限流。
解决:
- 程序会自动重试(从 3s 开始指数退避)
- 播放列表模式下视频间有 3~5 秒延迟,降低触发概率
现象: 返回 "播放列表共 50 个视频",但 YouTube 上实际有更多。
原因: DownSub 后端分页 API 已损坏,翻页返回 500。
解决: 安装 yt-dlp:
pip install yt-dlp安装后自动切换到 yt-dlp 枚举播放列表,不受数量限制。
原因: YouTube 对程序化访问有 bot 检测,yt-dlp 需要浏览器 cookies 来通过验证。
解决: 配置 yt-dlp cookies,详见上方的 yt-dlp Cookies 配置指南。
# 快速方案:用 --ytdlp-cookies-browser 直接从 Chrome 读取
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies-browser chrome
# 推荐方案:用 cookies.txt 文件
python -m downsub_crawler "https://www.youtube.com/watch?v=1GI2uB5CpnE&list=PLd-GbuZ_m7RJ1X216NfmQm3vgMB107YQW" --lang en --ytdlp-cookies ./cookies.txt即使不配置 cookies,程序也不会阻塞——备选下载失败时会自动记录到 retry_failed.json,不影响主流程。
现象: 只有自动翻译字幕无法下载。
原因: DownSub 的自动翻译功能需要 Premium 会员。
解决: 指定原始字幕语言 --lang en,不下载自动翻译。
downsub_crawler/
├── __init__.py # 包入口
├── __main__.py # python -m 入口
├── cli.py # 命令行参数解析
├── crypto.py # AES-256-CBC 加密(兼容 CryptoJS)
├── parser.py # YouTube URL 解析
├── api.py # DownSub API 客户端
├── downloader.py # 字幕下载协调器
└── requirements.txt # 依赖列表
CLI 参数
↓
downloader.download_playlist() / download()
↓
parser.process_url() → 提取 videoId, playlistId
↓
crypto.encrypt() → AES 加密 videoId
↓
api.get_video_info() → GET get-info.downsub.com/{id} → 字幕列表
↓
api.build_subtitle_download_url() → 构建下载 URL
↓
api.download_subtitle_file() → HTTP GET → 保存文件
↓
(失败时)api.download_subtitle_via_ytdlp() → yt-dlp 备选
↓
downloader._save_failed_json() → 记录失败到 retry_failed.json
| 端点 | 方法 | 用途 |
|---|---|---|
get-info.downsub.com/{encrypted_id} |
GET | 视频信息 + 字幕列表 |
get.downsub.com/?type=playlist |
GET | 播放列表 |
subtitle.downsub.com/{type}/{url}/ |
GET | 下载字幕文件 |
get.downsub.com/ |
POST | 非 YouTube 源(未实现) |
- 算法: AES-256-CBC
- 密钥:
zthxw34cdp6wfyxmpad38v52t3hsz6c5 - 密钥派生: OpenSSL EVP_BytesToKey(基于 MD5),非 PBKDF2
- 序列化格式:
{ct: base64(ciphertext), iv: hex(iv), s: hex(salt)}→ JSON → Base64URL
pycryptodome>=3.0 # AES 加密
requests>=2.28 # HTTP 客户端
yt-dlp>=2024.0 # 可选:播放列表枚举 + 备选下载
- 踩坑记录 — 开发过程中遇到的问题和解决方案