跳到正文

目录

yt-dlp:命令行音视频下载工具使用与架构指南

yt-dlp:命令行音视频下载工具使用与架构指南

目标读者:需要批量下载视频、提取音频、嵌入字幕或写元数据的工程师;想在脚本、服务或流水线里调用下载能力的开发者。 核心问题:怎么装、怎么挑格式、怎么排反爬、报错时改哪里。架构部分为排查服务,不要求先读完。 事实边界:命令、选项与架构依据 yt-dlp/yt-dlp 仓库 README 整理;站点支持与反爬策略随网站变动,文中数字以标注日期为准。

需要从 YouTube、Bilibili、TikTok 等站点批量下载视频、提取音频、嵌入字幕或写元数据时,命令行工具比图形界面更可控、可脚本化、可复现。yt-dlp 是这一场景下维护最活跃的开源实现,覆盖超过一千个站点,从 youtube-dl fork 而来并持续合并上游修复。

阅读导航

  • 想先上手:直接看「安装」和「最小示例」
  • 想挑格式:看「功能详解 → 格式选择」
  • 想排反爬:看「网络与反封锁」和「常见问题」
  • 想嵌入代码:看「Python API」
  • 报错后想定位:看「架构解析」和「常见问题」

学习目标

读完本文,你应该能:

  • 在 Linux / macOS / Windows 上装好 yt-dlp 与 ffmpeg,并验证安装
  • -f-S 按清晰度、编码、文件大小等维度挑格式,说清两者的区别
  • 处理字幕、元数据、缩略图、章节与播放列表的常见场景
  • 被反爬拦截时,按顺序尝试更新、伪装、代理与 Cookie
  • 用 Python API 在代码里取元数据、下载并挂进度回调
  • 根据报错位置(Extractor / Downloader / PostProcessor)判断该改什么

一条下载命令的完整路径

先看一次下载请求会经过哪些环节。后面排查时,报错出现在哪一段,答案基本就在那一段:

URL
Extractor        匹配 URL、向站点请求并解析视频信息
                 (站点改版常报 "Unable to extract ...")
Format Selector  按 -f / -S 规则筛出要下载的流
Downloader       按协议下载(HTTP / HLS / DASH,可并发分片)
                 (网络问题常报 HTTP 403 / 429)
PostProcessor    ffmpeg 合并音视频、嵌字幕、写元数据
                 (环境问题常报 ffmpeg not found)
输出文件

各阶段的报错与改法对应关系,在「架构解析」里展开。

项目概览

指标
GitHubyt-dlp/yt-dlp
Stars / Forks183k / 16k(2026-08-06 实时)
语言Python 3.10+(推荐 3.11+)
许可证Unlicense
维护状态活跃,master 日常推送

yt-dlp 能做的事集中在这几类:

  • 支持超过一千个站点的视频提取,每个站点对应一个 Extractor 类
  • 格式选择与多维度排序(-f 按格式 ID,-S 按分辨率/codec/文件大小等维度)
  • 字幕下载、嵌入与格式转换
  • 元数据写入与缩略图嵌入
  • 插件扩展(自定义 Extractor 和 PostProcessor)
  • 内置自动更新通道(stable / nightly / master)

相比原版 youtube-dl,yt-dlp 的改动重点在跟得上网站节奏:YouTube 的 n-sig 反混淆、Shorts、Clips,格式排序的粒度,分片并发,以及插件系统。这也是当前 youtube-dl 生态里更新最频繁的分支。


安装

二进制文件(推荐)

直接下载对应平台的二进制文件,无需安装 Python:

# Linux/macOS
sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
sudo chmod a+rx /usr/local/bin/yt-dlp

# Windows(PowerShell)
irm https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe -o yt-dlp.exe

# macOS
sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos -o /usr/local/bin/yt-dlp
sudo chmod a+rx /usr/local/bin/yt-dlp

pip 安装

python -m pip install -U yt-dlp

通过 pip 安装后,更新命令为:

python -m pip install -U --pre yt-dlp

依赖:ffmpeg(必须)

yt-dlp 的多数能力依赖外部工具 ffmpeg,包括:

  • 合并分离的视频和音频流
  • 转换容器格式
  • 提取和嵌入字幕
  • 缩略图转换

之所以依赖外部 ffmpeg 而非内置,是因为 ffmpeg 本身体积大(数十 MB)、维护独立、且涉及大量编解码专利问题,作为独立进程调用更利于各自升级。yt-dlp 只负责抓取和调度,编解码与容器操作全部交给 ffmpeg,两者通过子进程通信。

建议从 yt-dlp/FFmpeg-Builds 下载预编译版本。安装后运行 yt-dlp --version 确认安装成功。

⚠️ 注意:PyPI 上有个名为 ffmpeg 的 Python 包,和 ffmpeg 命令行工具不是同一个东西,别装错了。

更新通道

yt-dlp 提供三个发布通道:

通道特点适用场景
stable每月一次正式发布一般用户
nightly每日构建,推荐日常使用多数用户首选
master每次 push 触发构建追求最新功能的开发者
# 更新到 nightly(推荐)
yt-dlp --update-to nightly

# 更新到 master
yt-dlp --update-to master

# 切换回 stable
yt-dlp --update-to stable

超过 90 天未更新的版本会提示更新警告,可用 --no-update 抑制。

由于视频站点经常调整反爬策略,yt-dlp 的 Extractor 需要持续跟进修复。遇到原本能下载的站点突然失败,第一步通常是更新到 nightly 再试。

验证安装

装完后确认两个程序都在 PATH 里:

yt-dlp --version
ffmpeg -version | head -n 1

预期输出分别是 2026.07.04 之类的版本号和 ffmpeg version ...yt-dlp --version 能跑通说明程序本身可用;ffmpeg 缺失不影响下载单文件流,但合并分离的音视频流、嵌入字幕这类操作会失败,建议一起装好。


最小示例

下载单个视频用一条命令:

yt-dlp "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

不指定格式时,yt-dlp 会按内置默认排序选最佳兼容格式。要显式指定质量最高的可用格式:

yt-dlp -f "bv*+ba/b" "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

bv* 匹配最佳视频流(含纯视频和音视频合一),ba 匹配最佳音频流,/b 是兜底选项。YouTube 等站点的高码率流通常是视频和音频分离的——这是 DASH(Dynamic Adaptive Streaming over HTTP)和 HLS 自适应流媒体的标准做法:分离后客户端可以根据带宽单独选择视频清晰度和音频码率,避免低带宽用户被迫下载高码率音频。代价是下载后需要 ffmpeg 把两条流合并成单个文件。

下载成功时终端会出现 [download] 100% of ... 的进度行,文件落在当前目录。若出现以 ERROR: 开头的行,说明本次下载中止,具体改法见「常见问题」。

功能详解

格式选择

格式选择是 yt-dlp 用起来和别的下载工具差别最大的地方。同一视频在不同站点、不同清晰度下往往有多个可用格式,-f-S 提供两种互补的控制方式:-f 按格式 ID 或过滤表达式精确指定,-S 按多个维度排序后取最优。

列出可用格式

yt-dlp -F "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

输出示例(截取部分):

ID  EXT   RESOLUTION │   FPS │   CODECS    │   BR    │   SIZE
────────────────────────────────────────────────────────────
sb2 mhtml   images                │         │ unknown
18  mp4    426x240    24 │ av01   72kbps │ ~1MB
22  mp4    1280x720   22 │ avc1   ~2MB

第一列 ID 是后续 -f 选择格式的依据。

选择特定格式

# 按格式 ID 选择
yt-dlp -f 18 "URL"

# 组合视频+音频
yt-dlp -f "18+251" "URL"

# 选择最佳视频,不带音频
yt-dlp -f "bv" "URL"

格式排序(Format Sorting)

yt-dlp 在 -S 参数上提供格式排序机制,按多个维度排序后取最优:

# 优先选择分辨率高、codec 新的格式
yt-dlp -S "res:1080,codec:avc" "URL"

# 先按文件大小排序,再选最佳画质
yt-dlp -S "filesize:desc,res:desc" "URL"

# 优先选择 av1 编码
yt-dlp -S "codec:av01" "URL"

默认排序依次考虑 langqualityresfpshdrvcodecchannelsacodecsizebrasrprotoext 等维度,其中 hasvidie_pref 始终优先。用 -S "" 可以查看当前生效的默认顺序。

-S-f 的区别:-f 是硬过滤,不满足条件的格式直接排除;-S 是软排序,所有格式都参与,只是按指定维度排先后。需要严格限制清晰度时用 -f 加过滤表达式,需要在多个维度间权衡时用 -S

格式过滤器

# 只选择大于 720p 的视频
yt-dlp -f "bestvideo[height>=720]+bestaudio/best[height>=720]" "URL"

# 排除 webm 格式(用过滤器 [ext!=webm])
yt-dlp -f "bestvideo[ext!=webm]+bestaudio[ext!=webm]/best[ext!=webm]" "URL"

字幕处理

# 下载所有字幕
yt-dlp --write-subs "URL"

# 下载指定语言字幕
yt-dlp --write-subs --sub-langs "en,zh-cn" "URL"

# 嵌入字幕到视频文件
yt-dlp --embed-subs "URL"

# 下载自动生成的字幕
yt-dlp --write-auto-subs --embed-auto-subs "URL"

--write-subs 把字幕作为独立文件保存,--embed-subs 通过 ffmpeg 把字幕轨道写入容器(mp4/mkv)。两者可以同时使用:既保留独立字幕文件,又嵌入到视频里。

元数据与缩略图

# 写入元数据 JSON
yt-dlp --write-info-json "URL"

# 嵌入缩略图
yt-dlp --embed-thumbnail "URL"

# 全部写入
yt-dlp --write-description --write-info-json --write-thumbnail --embed-thumbnail "URL"

--write-info-json 保存的视频元数据(标题、上传者、时长、格式列表等)可以后续被 --load-info-json 重新加载,避免重复请求站点 API。批量下载时先抓 info-json 再决定下载哪些格式,能显著降低被站点限速的风险。

下载时间范围与章节

# 只下载第 10 秒到第 60 秒
yt-dlp --download-sections "*10-60" "URL"

# 按章节分割视频
yt-dlp --split-chapters "URL"

--download-sections 依赖 ffmpeg 的精确裁剪,会先下载完整流再裁剪,不会减少下载量但能减少输出文件体积。--split-chapters 按视频自带的章节标记切成多个文件。

播放列表处理

# 只下载播放列表前 10 个视频
yt-dlp -I 1:10 "PLAYLIST_URL"

# 随机顺序下载
yt-dlp --playlist-random "PLAYLIST_URL"

# 排除已下载的视频(archive)
yt-dlp --download-archive archive.txt "PLAYLIST_URL"

--download-archive 把已下载视频的 ID 写入归档文件,下次运行时跳过。批量下载长播放列表时配合使用,可以断点续传。


输出模板与文件组织

下载大量视频时,文件命名和目录结构决定了后续检索的难易度。yt-dlp 的输出文件名通过 -o 模板完全可定制,模板字段来自 Extractor 返回的元数据。

基本模板

# 默认模板:标题 [ID].扩展名
# Example: "Rick Astley - Never Gonna Give You Up [dQw4w9WgXcQ].mp4"

# 自定义文件名
yt-dlp -o "%(title)s-%(id)s.%(ext)s" "URL"

# 按日期组织
yt-dlp -o "%(upload_date>%Y/%m/%d)s/%(title)s.%(ext)s" "URL"

%(upload_date>%Y/%m/%d)s 里的 > 是格式化操作符,把原始的 YYYYMMDD 字符串重新格式化为目录路径。

模板字段速查

字段说明
%(title)s视频标题
%(id)s视频 ID
%(uploader)s上传者
%(upload_date)s上传日期(YYYYMMDD)
%(resolution)s分辨率
%(ext)s扩展名
%(playlist_title)s播放列表标题
%(playlist_index)03d播放列表序号(补零 3 位)

多路径配置

# 指定下载路径
yt-dlp -P "/path/to/download" "URL"

# 临时文件先下载到 temp,完成后移到 home
yt-dlp -P "home:/data/videos" -P "temp:/tmp/yt-dlp" "URL"

-Phome:temp: 前缀分别控制最终输出目录和临时文件目录。临时文件先落在 temp、处理完才移入 home,下载中断时目标目录不会留下残缺文件;把 temp 放到 SSD 也能加快分片写入。


网络与反封锁

视频站点识别非浏览器流量的常见手段包括 IP 地理限制、TLS 指纹检测、Cookie 验证和 UA 检查。yt-dlp 针对这些场景提供了对应的参数。

代理

# HTTP/HTTPS 代理
yt-dlp --proxy "http://proxy.example.com:8080"

# SOCKS5 代理
yt-dlp --proxy "socks5://user:pass@127.0.0.1:1080"

伪装客户端(Impersonation)

部分网站通过 TLS 指纹识别机器人流量——即使 UA 和 Cookie 都对,TLS 握手的 cipher 列表和扩展顺序暴露了客户端不是真浏览器。yt-dlp 支持伪装成主流浏览器:

# 伪装成 Chrome
yt-dlp --impersonate "chrome" "URL"

# 伪装成 Edge (Windows)
yt-dlp --impersonate "chrome:windows-10" "URL"

# 查看所有支持的伪装目标
yt-dlp --list-impersonate-targets

底层使用 curl_cffi(curl-impersonate 的 Python 绑定)实现 TLS 指纹伪装。这是可选依赖:pip 安装用 pip install -U yt-dlp[curl-cffi],官方二进制已内置。

地理限制绕过

# 使用指定国家的 XFF 头
yt-dlp --xff "US" "URL"

# 使用代理验证 IP(针对某些需要二次验证的站点)
yt-dlp --geo-verification-proxy "http://proxy.example.com:8080" "URL"

--xff 通过添加 X-Forwarded-For 头模拟来自指定国家的请求,对部分只检查 HTTP 头的站点有效;对真正校验 IP 的站点仍需配合代理。


批量下载与自动化

批量文件

将 URL 写入文件,每行一个:

# urls.txt
https://www.youtube.com/watch?v=video1
https://www.youtube.com/watch?v=video2
https://www.youtube.com/watch?v=video3
yt-dlp -a urls.txt

-a 会顺序处理每个 URL。配合 --download-archive 可以跳过已下载项,配合 --ignore-errors 可以在某个 URL 失败时继续处理后续项。

预设别名(Preset Aliases)

yt-dlp 内置几个常用组合,用 --preset-alias 调用:

# 提取音频并转成 mp3
yt-dlp --preset-alias mp3 "URL"

# 下载为 mp4(优先 mp4 容器并嵌入元数据)
yt-dlp --preset-alias mp4 "URL"

内置预设包括 mp3mp4mkv 等。mp3 相当于 -x --audio-format mp3 --audio-quality 0mp4 相当于 -f bv*+ba -S ext:mp4,m4a --embed-metadata

更常用的组合用 --alias <名称> "<选项串>" 自定义,通常写进配置文件 ~/.config/yt-dlp/config,之后直接以 --<名称> 调用:

# 配置文件里定义
--alias my-audio "-x --audio-format m4a -S aext:m4a,abr"

# 命令行里调用
yt-dlp --my-audio "URL"

适合在团队内部统一下载规格:把规格写进共享配置,成员各自用 --<名称> 调用即可。

日志与输出

# 安静模式(只打印进度)
yt-dlp -q "URL"

# 打印 JSON 信息
yt-dlp -j "URL"

# 打印特定字段
yt-dlp -O "%(title)s - %(resolution)s" "URL"

# 进度模板
yt-dlp --progress-template "[%(playlist_index)d/%(playlist_count)d] %(title)s" "URL"

-j 输出的 JSON 可以管道给 jq 做批量处理,是脚本化场景下提取元数据的标准做法。


Python API:嵌入到代码中

yt-dlp 本身就是 Python 包,命令行能力全部通过 yt_dlp.YoutubeDL 类暴露。需要在 Web 服务、定时任务或数据处理流水线里调用下载能力时,直接用 Python API 比起 shell 调用命令行更可控——可以拿到结构化元数据、注入进度回调、动态调整选项。

基础调用

from yt_dlp import YoutubeDL

URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc']
with YoutubeDL() as ydl:
    ydl.download(URLS)

with 语句确保下载完成后正确释放网络连接和文件句柄。

配置选项

import yt_dlp

ydl_opts = {
    'format': 'm4a/bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'm4a',
    }],
    'outtmpl': '%(title)s.%(ext)s',
}

with YoutubeDL(ydl_opts) as ydl:
    ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])

ydl_opts 的字段与命令行参数一一对应,format 对应 -fouttmpl 对应 -opostprocessors 对应 --add-metadata--embed-subs 等后处理开关。

获取元数据(不下载)

import yt_dlp

with YoutubeDL({'quiet': True}) as ydl:
    info = ydl.extract_info('https://www.youtube.com/watch?v=BaW_jenozKc', download=False)
    print(f"标题: {info['title']}")
    print(f"时长: {info['duration']}秒")
    print(f"格式数: {len(info['formats'])}")

download=False 只提取元数据不下载文件,返回的 info 字典结构与 -j 命令行输出的 JSON 一致。批量场景下可以先 extract_info 拿到时长和格式列表,过滤后再决定是否下载。

进度钩子

import yt_dlp

def progress_hook(d):
    if d['status'] == 'downloading':
        print(f"进度: {d.get('_percent_str', 'N/A')}")
    elif d['status'] == 'finished':
        print('下载完成,进入后处理...')

ydl_opts = {
    'progress_hooks': [progress_hook],
}

with YoutubeDL(ydl_opts) as ydl:
    ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])

progress_hooks 接收一个回调列表,下载过程中每个状态变化都会触发。d['status'] 的取值包括 downloadingfinishederror,可用于实现自定义进度条、Webhook 通知或失败重试逻辑。


插件系统

yt-dlp 支持通过插件扩展功能,可加载自定义的 Extractor(提取器)和 PostProcessor(后处理器)。插件机制让自定义逻辑不必修改 yt-dlp 主仓库,便于在团队内分发和版本管理。

在插件系统出现之前,要支持一个新站点只能 fork 主仓库改代码再提 PR,等合并发版周期长,企业内部分站点的提取逻辑也不适合公开。插件系统把扩展点开放出来:自定义代码放在独立目录,yt-dlp 启动时自动扫描注册,主仓库升级不会覆盖插件,团队内部站点支持可以独立维护。

插件目录

在以下位置放置包含 yt_dlp_plugins 命名空间的包:

平台路径
Linux/macOS~/.config/yt-dlp/plugins/<pkg>/yt_dlp_plugins/
Windows%APPDATA%/yt-dlp/plugins/<pkg>/yt_dlp_plugins/
便携安装<yt-dlp.exe所在目录>/yt-dlp-plugins/<pkg>/yt_dlp_plugins/

插件示例

# myplugin/yt_dlp_plugins/extractor/_myplugin.py
from yt_dlp.extractor import GenericIE

class MySiteIE(GenericIE):
    _VALID_URL = r'https?://mysite\.com/watch/(?P<id>\w+)'
    _TESTS = [{
        'url': 'https://mysite.com/watch/abc123',
        'info_dict': {'id': 'abc123', 'title': 'My Video'},
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        # 自定义提取逻辑
        return self.url_result(f'https://mysite.com/api/video/{video_id}')

插件类名以 IE 结尾自动注册,以 _ 开头或包含在 __all__ 中则可控制导入行为。_VALID_URL 是匹配规则,_real_extract 是实际请求和解析逻辑,返回的字典结构与内置 Extractor 一致。


架构解析

下载失败时,判断问题出在 Extractor、Downloader 还是 PostProcessor,决定了该改 URL 格式、网络参数还是 ffmpeg 选项。下面拆解 yt-dlp 的三层结构和一次下载请求的完整流程。

模块结构

yt_dlp/
├── YoutubeDL.py       # 主引擎:调度下载流程
├── extractor/         # 1000+ 网站提取器
│   ├── _extractors.py # 所有提取器的注册表
│   ├── youtube.py     # YouTube 专用提取器
│   └── ...
├── downloader/        # 下载器实现
│   ├── http.py        # HTTP 下载
│   ├── hls.py         # HLS 流下载
│   ├── dash.py        # DASH 流下载
│   └── fragment.py    # 分片并发下载
├── postprocessor/    # 后处理器
│   ├── ffmpeg.py      # ffmpeg 封装(合并/转码/字幕)
│   ├── embedthumbnail.py
│   └── sponsorblock.py
├── networking/       # 网络层(curl_cffi/requests)
└── utils/             # 工具函数

extractor/ 目录是 yt-dlp 维护工作量最大的部分,每个站点对应一个 *.py 文件,注册表 _extractors.py 把所有 Extractor 类按字母序导入。站点改版或反爬升级时,通常改对应的那一个文件就够了。

下载流程

一次完整的下载请求流经以下阶段:

URL 输入 → Extractor.match_id()    # 匹配 URL,确定使用哪个提取器
        → Extractor._real_extract() # 向网站请求数据,解析视频信息
        → YoutubeDL.extract_info()  # 获取视频元数据(formats、字幕等)
        → Format Selector           # 根据用户选项筛选格式
        → Downloader                # 下载视频/音频流
        → Fragment Joiner           # 分片合并(HLS/DASH)
        → PostProcessor             # ffmpeg 合并、转码、字幕嵌入、元数据写入
        → Output

报错位置决定了排查方向:Unable to extract 错误出在 Extractor 阶段,通常是站点改版需要更新 yt-dlp;HTTP Error 403/429 出在 Downloader 阶段,需要加 --impersonate 或换代理;ffmpeg not found 出在 PostProcessor 阶段,是 ffmpeg 未安装或不在 PATH。

Extractor 机制

每个支持的网站都有一个对应的 Extractor 类,主要职责:

  1. match_id():从 URL 中提取视频 ID
  2. _real_extract():向目标网站发起请求,解析页面/API,返回视频信息字典
  3. url_result():将提取结果转换为标准化格式

以 YouTube 为例,其 Extractor 还需要处理 signature(签名)解密、n-sig(下一代签名)反混淆等逻辑。YouTube 会持续更新签名算法,yt-dlp 必须同步跟进,所以遇到 YouTube 下载失败时,第一反应先更新版本。

Downloader 分层

yt-dlp 支持多协议和多层并发:

下载层说明
HTTP Downloader基础 HTTP 下载,支持断点续传
HLS Downloader下载 .m3u8 清单文件,按 TS 分片下载
DASH Downloader下载 .mpd 清单文件,按 segment 下载
Fragment Downloader并发下载多个分片(-N 参数控制并发数)

默认 -N 1(单线程),对于 HLS/DASH 流可提升到 4-8 加快速度。并发数过高可能触发站点限速,需要根据目标站点的反爬策略调整。

PostProcessor 链路

后处理在下载完成后串行执行,典型链路:

FFmpegMergeDownloader  # 合并视频+音频流(若有)
  → FFmpegFixupStretched  # 修复拉伸的流
  → FFmpegFixupM4a        # 修复 M4a 元数据
  → FFmpegSubtitlesConvertor  # 字幕格式转换
  → FFmpegEmbedSubtitle   # 嵌入字幕到 mp4/mkv
  → FFmpegMetadata        # 写入元数据
  → EmbedThumbnail        # 嵌入缩略图
  → SponsorBlock          # 标记/移除赞助段落

每一步都是可插拔的 PostProcessor,通过 postprocessors 参数可以添加、移除或调整顺序。某一步失败不会阻塞后续步骤,但可能导致输出文件缺少对应的内容(如字幕没嵌入但视频正常)。


常见问题

Q: 下载视频被限速或拒绝?

按顺序尝试以下组合,从轻到重:

# 1. 先更新到 nightly(站点反爬更新频繁)
yt-dlp --update-to nightly

# 2. 加浏览器伪装
yt-dlp --impersonate "chrome" "URL"

# 3. 配合代理
yt-dlp --impersonate "chrome" --geo-verification-proxy "http://proxy:port" "URL"

如果仍然失败,检查是否需要登录 Cookie:用 --cookies-from-browser chrome 直接读取浏览器 Cookie,或用 --cookies cookies.txt 加载导出的 Cookie 文件。

Q: 只想下载音频?

yt-dlp -x --audio-format mp3 "URL"

-x 触发 FFmpegExtractAudio 后处理器,--audio-format 指定输出格式。需要更高音质时加 -S "abr:best" 选最高码率音频流。

Q: PyInstaller 打包的 exe 启动太慢?

yt-dlp 启动时会导入所有 Extractor,1000+ 个类的导入开销在 PyInstaller 冻结环境下尤其明显。构建时启用懒加载提取器:

python devscripts/make_lazy_extractors.py
python -m bundle.pyinstaller

这会把 Extractor 导入推迟到首次匹配 URL 时,启动时间可从数秒降到毫秒级。

Q: 报错 “No video formats”?

通常是站点反爬机制触发,可尝试:

yt-dlp --no-check-certificates --impersonate "chrome" "URL"

--no-check-certificates 跳过 TLS 证书校验,对使用了自签证书或证书过期的内部站点有用;--impersonate 解决 TLS 指纹检测问题。

Q: 如何查看所有支持网站?

yt-dlp --list-extractors

输出包含所有已注册 Extractor 的名称和匹配的 URL 模式。完整列表也可在 yt-dlp Supported Sites 查看。

Q: 文件名带特殊字符导致报错?

视频标题里的 /:| 等字符在文件系统中非法,默认输出模板会自动替换为 #。需要更精细控制时加 --restrict-filenames 把所有非 ASCII 字符和空格也替换掉,或用 --windows-filenames 强制兼容 Windows 命名规则。

yt-dlp --restrict-filenames -o "%(title)s.%(ext)s" "URL"

Q: 批量下载到一半被站点限速?

先降低并发再加重试。-N 控制分片并发,--retries 控制重试次数,--sleep-requests 在请求间加随机延迟:

yt-dlp -N 2 --retries 10 --sleep-requests 1 -a urls.txt

配合 --download-archive 跳过已下载项,可以安全地多次重跑同一批 URL 直到全部完成。

与 youtube-dl 的主要差异

yt-dlp 相比原版 youtube-dl 的主要改进(来自官方 README):

差异yt-dlpyoutube-dl
Python 版本3.10+(推荐 3.11+)2.6+/3.2+
格式排序默认按分辨率/codec默认按比特率
默认容错--no-abort-on-error中断
YouTube 支持n-sig 反混淆+Clips+Shorts基础
浏览器 Cookie支持所有主流浏览器有限
章节分割--split-chapters不支持
多线程下载--concurrent-fragments不支持
插件系统支持不支持

youtube-dl 的最后一次大版本更新已较久,对新站点和 YouTube 反爬更新的跟进明显慢于 yt-dlp。新项目应直接选 yt-dlp;已有 youtube-dl 脚本可以通过 yt-dlp 命令别名平滑替换,多数参数兼容。

适用边界与采用建议

yt-dlp 适合:批量下载视频、提取音频、归档播放列表、嵌入到自动化流水线、需要精确控制格式和元数据的场景。

不适合:实时流媒体录制(用 streamlink 或 OBS)、需要 GUI 的非技术用户(用 yt-dlg 等图形前端)、对下载速度有极致要求且站点支持 aria2c 加速的场景(yt-dlp 的并发主要在分片层,不如 aria2c 的多连接下载)。

遇到站点无法下载时,按以下顺序排查:

  1. 更新到 nightly 版本(站点反爬更新频繁,旧版本可能已失效)
  2. 查阅 yt-dlp Issues 是否有相同站点的已知问题
  3. -v 查看详细日志,定位失败发生在 Extractor、Downloader 还是 PostProcessor 阶段
  4. 站点不在支持列表时,考虑编写自定义 Extractor 插件

自测清单

能独立回答以下问题,说明本文内容基本消化:

  • 高码率视频为什么常下载视频、音频两条流再合并?合并依赖哪个外部工具?
  • -f "bv*+ba/b"-S "res:1080" 分别是哪种控制方式,什么时候用哪个?
  • 下载被限速时,按什么顺序尝试更新、伪装、代理、Cookie?
  • --write-info-json 对批量下载有什么价值?--load-info-json 解决什么问题?
  • 报错 Unable to extractHTTP Error 403ffmpeg not found 分别对应哪一层?
  • 下载纯音频为 mp3、给视频嵌入字幕、按章节切片,分别用哪条命令?
  • 站点不在支持列表时,最小成本的支持方式是改主仓库还是写插件?

进阶路径

  • 固化常用选项:把 --impersonate chrome --embed-thumbnail --write-info-json 这类固定参数写进 ~/.config/yt-dlp/config,省去每次输入。
  • 增量归档脚本:用 Python API 配合 --download-archive,实现只补新视频的播放列表增量同步。
  • 写自定义 Extractor:对照「插件系统」的示例为内部站点写提取器,理解 _real_extract 返回的字段结构。
  • 读源码:从 extractor/youtube.py 的 signature 解密与 n-sig 反混淆入手,理解反爬应对的边界。

参与讨论

使用 GitHub 登录。欢迎补充事实、异议与实践。