深色模式
把 yt-dlp 做成中文便携下载器:从 YouTube Music 歌单到普通视频播放列表
最初,我只是想把 YouTube Music 歌单里有权保存的歌曲,批量下载到本地,再放进 Navidrome 音乐库。
需求看起来很简单:输入一个链接,选择文件夹,开始下载。但实际使用时,遇到了私人歌单需要登录、Chrome Cookie 无法读取、歌曲名称变成拼音、文件分类不方便等问题。
后来,需求又扩展到了普通 YouTube 视频:不仅要下载单个视频,还要支持整张播放列表,尽量保留平台提供的原始画质。
最终,我们围绕开源项目 yt-dlp,做成了一个中文 Windows 便携下载器。它不需要 Codex 或 ChatGPT 持续参与运行,复制完整文件夹到兼容的 Windows 电脑,便可以独立使用。
图 1:2.2 版实际音频界面。设置区是主区域,格式、分类、命名同行排列,右侧任务详情可以按需展开。截图使用示例保存路径,未展示私人下载内容。
核心原理:界面负责组织,专业工具负责下载
这个程序没有重新实现一套 YouTube 下载引擎,而是在成熟工具外面增加了一层中文界面和任务管理。
用户输入链接后,程序先判断它是单个内容还是播放列表,再调用 yt-dlp 读取信息。检测通过后,逐项下载,并根据选择完成音频提取、视频合并、封面和标签处理,最后检查文件、整理名称、写入成功记录。
整个流程可以概括为:
txt
输入链接、选择设置
↓
读取内容信息、统计列表
↓
检查账号访问和所选格式
↓
逐项下载音频或视频
↓
提取、合并、封装及元数据处理
↓
检查最终文件
↓
整理名称和目录,写入完成记录界面负责让用户容易操作,下载和媒体处理交给专业工具。这种方式既减少了重复开发,也方便后续维护。
用到了哪些组件和插件?
这里需要先区分:yt-dlp、FFmpeg、Deno 并不是 Codex 插件,而是便携程序运行时使用的本地工具。真正定制的下载插件,是负责中文曲目资料处理的 MusicLocalize。
| 工具或插件 | 在项目中的作用 |
|---|---|
| yt-dlp | 解析链接、读取播放列表、选择音视频格式、读取授权的浏览器登录状态并下载 |
| FFmpeg | 提取或转换音频、合并视频和声音,以及处理封装和媒体元数据 |
| FFprobe | 检查最终文件是否包含预期的音频、视频轨道 |
| Deno | 为 yt-dlp 提供所需的 JavaScript 运行环境,参与部分 YouTube 解析流程 |
| MusicLocalize 自定义插件 | 按视频编号读取 YouTube Music 的中文显示资料,补全歌名、歌手等字段 |
| Python 与 Tkinter | 编写中文窗口、设置管理、任务队列和进度显示 |
| PyInstaller | 将界面程序及 Python 运行环境打包,免去目标电脑安装 Python 的步骤 |
开发过程中,Codex 承担代码编写、工具调用、打包和验证工作;桌面管理工具用于建立专用对话,电脑操作工具用于检查实际窗口和交互。
这些开发工具不会成为下载器的运行前提。成品在本地调用随包组件,不需要通过聊天窗口才能下载,也不会把“云端对话”误当成能够直接操作任意用户磁盘的程序。
登录问题:使用浏览器已有的授权状态
公开内容通常不需要登录,但私人歌单、“喜欢的音乐”等账号内容,需要对应账号的访问权限。
我们最初遇到过 Chrome Cookie 数据库无法复制的问题。继续依赖图形下载器的 Cookie 导入入口,还可能受到软件版本或会员功能限制。
最终采用的是 yt-dlp 自身支持的 Firefox 登录状态读取方式:
- 用户在真正的 Firefox 浏览器中登录。
- 程序查找本机 Firefox 档案。
- 用户选择正确档案,并勾选读取授权。
- yt-dlp 在本机读取登录状态,用于访问对应内容。
程序不提供 Google 密码输入框,也不要求用户上传 Cookie 文件。
图 2:登录授权、档案选择和刷新入口。这里显示的是浏览器档案名称,不是 Google 账号清单;截图中的授权框未勾选。
这里还有一个容易混淆的概念:Firefox 档案不是 Google 账号清单。 刷新档案只能找到浏览器配置,不能证明账号已经登录,更不能证明它拥有目标歌单的权限。真正的验证仍然是访问目标内容。
对于自动发现不到的档案,程序也提供了手动选择入口。
登录只是解决访问权限的一部分,并不意味着所有内容都能下载。地区限制、失效内容、平台验证以及 DRM 等情况,仍然可能阻止下载。
为什么网页是中文,下载后却成了拼音?
这是开发过程中一个有代表性的问题。
YouTube Music 页面显示“李玟 — 刀马旦”,下载后的文件却可能叫作:
txt
CoCo Lee - Dow Ma Dan.opus这不是中文编码损坏,也不是程序主动把中文转成拼音。实际核对发现,同一个视频编号,在不同显示语言下,平台会返回不同的曲目资料。
针对这首歌,中文请求返回的是“李玟”和“刀马旦”;英文请求返回的是另一套名称。
因此,我们增加了 MusicLocalize 插件。它通过 yt-dlp 的后处理器扩展机制,在单曲信息提取后、文件命名与后续处理前,按相同视频编号查询中文显示资料,并更新相关字段。
这里没有使用机器翻译,也没有根据拼音猜中文:
- 平台提供中文名称,就使用对应名称。
- 平台在中文界面仍提供英文名称,就保留英文。
- 查询失败或资料缺失,就回退到原来的信息。
这套机制使用的是平台内部接口,不是有稳定承诺的公开开发者接口,因此需要保留回退逻辑,不能保证未来一直不变。
插件也曾在歌单预览阶段触发歌手字段冲突。修复后,列表预览只负责枚举内容,中文补全放在实际单曲处理阶段,避免干扰 yt-dlp 对列表字段的整理。
音频与视频,处理方式有什么不同?
音频模式默认优先保留平台提供的音频编码,常见结果是 Opus 或 M4A。这样可以避免为了统一扩展名而进行额外的有损转换。
需要兼容旧设备时,可以选择 MP3。但把 Opus 转成 MP3,不会提升音质;即使选择更高码率,也无法恢复源音频已经丢失的信息。
图 3:音频设置局部图。格式、分类、命名同排,中文资料与视频编号分别设置。最终文件名不再额外添加格式字样。
视频则经常采用另一种结构:高画质画面和声音分开提供。下载器需要分别取得视频流、音频流,再通过 FFmpeg 合并。
程序提供两种主要视频模式:
| 模式 | 处理原则 |
|---|---|
| 原始画质 | 在清晰度上限内选择可用音视频,保留编码;分离的流进行无损合并 |
| 兼容 MP4 | 选择可用的 H.264 画面和 AAC 声音,合并为兼容性较好的 MP4 |
所谓“原始画质”,是保留 YouTube 提供的编码和画质,并不是取得上传者未经平台压缩的源文件。
图 4:切换到视频模式后的实际选项。原始画质、清晰度上限、封装格式分开设置,文件分类和命名也有对应的视频选项。
原始模式自动合并时可能生成 MKV。这是为了容纳不同编码,并不代表视频被重新压缩。用户也可以选择 MP4 或 WebM 封装;如果原编码不适合所选容器,程序提示失败,而不是悄悄转码。
真正有意义的进度,不能只放一个动画
早期版本的进度条只是来回移动,只能说明程序还在运行,不能告诉用户任务完成了多少。
新版把进度分成了两层。
整个任务的进度,按照已经处理的条目数计算:
txt
已处理 35 / 100 项
成功 30,重复跳过 4,失败 1
总进度 35%这里的 100% 表示任务已经处理结束,不能理解为全部下载成功。因此,成功、跳过、失败必须分别显示。
当前文件的进度,则读取 yt-dlp 输出的结构化下载信息,展示下载百分比、速度和预计时间。视频包含多路数据时,分别显示当前是哪一路。
合并、封装和写入标签需要额外时间,不能在数据刚传完时就算作最终成功。程序会显示正在处理的阶段,直到文件检查通过并保存后,才写入完成记录。
为了让总数稳定,程序先读取本次列表,再按这份固定队列执行。平台隐藏、没有返回的内容,无法纳入准确统计,这一点也需要向用户说明。
图 5:任务详情展开后的真实界面,包含任务总进度、当前文件进度、主要信息和“清空显示”。本图是空闲状态,用于展示布局,未伪造下载中的进度或日志。
去重、文件命名和重试,需要一起设计
最初的文件名包含视频编号,例如:
txt
李玟 - 刀马旦 [0Jq8-Ti285E].opus这些字符不是乱码,而是内容编号,有助于区分同名文件。但日常音乐库更适合简洁名称,所以后来改成了可选项,默认使用:
txt
李玟 - 刀马旦.opus遇到同名的不同内容时,自动追加 (2)、(3),避免覆盖。
音频转换时,临时文件与已经完成的文件也必须隔离。否则,将同一内容转换为另一种格式时,可能误用已经存在的原始音频作为中间文件。
去重记录则保存在输出目录的 .ytmusic 中。只有最终文件检查并保存成功,才记录为完成。
音频与视频使用不同的记录范围,避免“下载过音频,就把视频跳过”。不同画质和格式也需要区分,否则低画质的完成记录可能阻止用户后来下载高画质版本。
停止任务时,未完成项不计入成功。再次执行相同任务,可以利用保留的临时文件继续,并跳过已有的完成记录。
从“设置很多”到“只点一次下载”
界面经历了几次实际使用后的调整。
最初所有设置和日志上下排列,后来改为左右分区;再根据使用反馈,让左侧成为主要设置区,右侧进度与日志可以隐藏或展开。
音频和视频切换也移到了左侧。格式、分类、命名等设置同行排列,去掉了左侧整体滚动条。
右侧不再把全部技术信息逐行展示,只保留主要进展,例如:
txt
正在检测连接
已读取列表
正在下载当前文件
正在合并音视频
已保存文件
任务处理完成完整技术日志仍写入文件,用于排查问题。“清空显示”只清除窗口中的信息,不影响任务、下载记录或日志文件。
操作流程也从“先检查,再确认下载”,简化成了一个“开始下载”按钮:用户点击后,程序自动先检测,通过就继续下载;检测失败时说明原因,并提供浏览器登录入口。
这比把所有错误都解释成“没有登录”更合理。失效链接、网络故障和格式不匹配,同样可能导致检测失败。
如何做到换电脑也能运行?
便携包不仅包含主程序,还带有 Python 运行环境、yt-dlp、FFmpeg、FFprobe、Deno 和自定义插件。
因此,目标电脑不需要另外安装 Python,也不需要配置工具路径。代价是完整包约为 241 MB,需要复制或解压整个文件夹,不能只拿走一个 exe。
新增视频功能没有明显增加体积,因为最主要的下载和媒体处理组件,原本就已经包含在音频版本中。
程序还经过了清理系统 Python 配置和工具搜索路径后的启动自检,以及旧版覆盖升级测试。不过,这不等于已经在所有全新 Windows 设备上验证,实际运行仍需要继续积累反馈。
开发验证使用了自行生成的短音视频,测试下载、音画合并、编码保留、封面标签、进度、去重和中途停止,没有为了验证程序而擅自下载整张外部歌单。
这个项目最终做的,是把专业工具组织成更容易使用的本地流程:让普通用户通过中文界面完成操作,同时保留原始编码、失败原因、处理记录和可维护性。
它解决的是使用体验问题,不改变内容的版权和访问边界。下载时仍应确认自己有权保存相关内容,并遵守平台条款。
参考项目与文档:




