Skip to content

把 yt-dlp 做成中文便携下载器:从 YouTube Music 歌单到普通视频播放列表

最初,我只是想把 YouTube Music 歌单里有权保存的歌曲,批量下载到本地,再放进 Navidrome 音乐库。

需求看起来很简单:输入一个链接,选择文件夹,开始下载。但实际使用时,遇到了私人歌单需要登录、Chrome Cookie 无法读取、歌曲名称变成拼音、文件分类不方便等问题。

后来,需求又扩展到了普通 YouTube 视频:不仅要下载单个视频,还要支持整张播放列表,尽量保留平台提供的原始画质。

最终,我们围绕开源项目 yt-dlp,做成了一个中文 Windows 便携下载器。它不需要 Codex 或 ChatGPT 持续参与运行,复制完整文件夹到兼容的 Windows 电脑,便可以独立使用。

2.2 版音频下载主界面

图 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 登录状态读取方式:

  1. 用户在真正的 Firefox 浏览器中登录。
  2. 程序查找本机 Firefox 档案。
  3. 用户选择正确档案,并勾选读取授权。
  4. yt-dlp 在本机读取登录状态,用于访问对应内容。

程序不提供 Google 密码输入框,也不要求用户上传 Cookie 文件。

Firefox 本机登录档案与授权选项

图 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 输出的结构化下载信息,展示下载百分比、速度和预计时间。视频包含多路数据时,分别显示当前是哪一路。

合并、封装和写入标签需要额外时间,不能在数据刚传完时就算作最终成功。程序会显示正在处理的阶段,直到文件检查通过并保存后,才写入完成记录。

为了让总数稳定,程序先读取本次列表,再按这份固定队列执行。平台隐藏、没有返回的内容,无法纳入准确统计,这一点也需要向用户说明。

展开右侧任务详情后的 2.2 版界面

图 5:任务详情展开后的真实界面,包含任务总进度、当前文件进度、主要信息和“清空显示”。本图是空闲状态,用于展示布局,未伪造下载中的进度或日志。

去重、文件命名和重试,需要一起设计 ​

最初的文件名包含视频编号,例如:

txt
李玟 - 刀马旦 [0Jq8-Ti285E].opus

这些字符不是乱码,而是内容编号,有助于区分同名文件。但日常音乐库更适合简洁名称,所以后来改成了可选项,默认使用:

txt
李玟 - 刀马旦.opus

遇到同名的不同内容时,自动追加 (2)、(3),避免覆盖。

音频转换时,临时文件与已经完成的文件也必须隔离。否则,将同一内容转换为另一种格式时,可能误用已经存在的原始音频作为中间文件。

去重记录则保存在输出目录的 .ytmusic 中。只有最终文件检查并保存成功,才记录为完成。

音频与视频使用不同的记录范围,避免“下载过音频,就把视频跳过”。不同画质和格式也需要区分,否则低画质的完成记录可能阻止用户后来下载高画质版本。

停止任务时,未完成项不计入成功。再次执行相同任务,可以利用保留的临时文件继续,并跳过已有的完成记录。

从“设置很多”到“只点一次下载” ​

界面经历了几次实际使用后的调整。

最初所有设置和日志上下排列,后来改为左右分区;再根据使用反馈,让左侧成为主要设置区,右侧进度与日志可以隐藏或展开。

音频和视频切换也移到了左侧。格式、分类、命名等设置同行排列,去掉了左侧整体滚动条。

右侧不再把全部技术信息逐行展示,只保留主要进展,例如:

txt
正在检测连接
已读取列表
正在下载当前文件
正在合并音视频
已保存文件
任务处理完成

完整技术日志仍写入文件,用于排查问题。“清空显示”只清除窗口中的信息,不影响任务、下载记录或日志文件。

操作流程也从“先检查,再确认下载”,简化成了一个“开始下载”按钮:用户点击后,程序自动先检测,通过就继续下载;检测失败时说明原因,并提供浏览器登录入口。

这比把所有错误都解释成“没有登录”更合理。失效链接、网络故障和格式不匹配,同样可能导致检测失败。

如何做到换电脑也能运行? ​

便携包不仅包含主程序,还带有 Python 运行环境、yt-dlp、FFmpeg、FFprobe、Deno 和自定义插件。

因此,目标电脑不需要另外安装 Python,也不需要配置工具路径。代价是完整包约为 241 MB,需要复制或解压整个文件夹,不能只拿走一个 exe。

新增视频功能没有明显增加体积,因为最主要的下载和媒体处理组件,原本就已经包含在音频版本中。

程序还经过了清理系统 Python 配置和工具搜索路径后的启动自检,以及旧版覆盖升级测试。不过,这不等于已经在所有全新 Windows 设备上验证,实际运行仍需要继续积累反馈。

开发验证使用了自行生成的短音视频,测试下载、音画合并、编码保留、封面标签、进度、去重和中途停止,没有为了验证程序而擅自下载整张外部歌单。

这个项目最终做的,是把专业工具组织成更容易使用的本地流程:让普通用户通过中文界面完成操作,同时保留原始编码、失败原因、处理记录和可维护性。

它解决的是使用体验问题,不改变内容的版权和访问边界。下载时仍应确认自己有权保存相关内容,并遵守平台条款。


参考项目与文档:

内容由 WordPress 管理,静态页面由 VitePress 生成