fix(youtube): 修复 YouTube 笔记生成失败 "Requested format is not available"#427
Open
pumpkinperson996 wants to merge 1 commit into
Open
fix(youtube): 修复 YouTube 笔记生成失败 "Requested format is not available"#427pumpkinperson996 wants to merge 1 commit into
pumpkinperson996 wants to merge 1 commit into
Conversation
## 问题
输入 YouTube 链接生成笔记时任务必定失败:
ERROR: [youtube] <id>: Requested format is not available
即使字幕已经抓取成功(日志里能看到"成功获取 YouTube 字幕,共 N 段"),
任务仍然在下载阶段崩掉。
## 原因
两个独立的问题叠加:
1. `requirements.txt` 把 yt-dlp 钉在 `2025.3.31`。YouTube 之后轮换过
player,旧版 yt-dlp 解不出 nsig 签名,所有音视频格式都被丢弃,只剩下
storyboard 图片(日志:`Only images are available for download`),
格式选择随即抛错。
2. 有字幕时 `NoteGenerator` 走的是"只取元信息"的路径
(`download(skip_download=True)`,只要 title/duration/cover),但
`YoutubeDownloader.download` 无条件设置了
`format='bestaudio[ext=m4a]/bestaudio/best'`。于是一个根本不需要媒体流的
调用,也会因为选不出格式而失败——把一个字幕已经到手的任务整个带崩。
## 改动
- `youtube_downloader.py`:`skip_download` 时设置
`ignore_no_formats_error=True`。yt-dlp 落后于 YouTube 时,只取元信息的路径
降级为"没有音频",而不是让整个笔记失败。
- `youtube_downloader.py`:`ext = info.get("ext") or "m4a"`。跳过下载时
yt-dlp 返回 `ext=None`,`dict.get` 的默认值对显式 None 不生效,
会拼出 `xxx.None` 这样的路径。
- `requirements.txt`:`yt-dlp==2025.3.31` → `>=2026.7.4`。yt-dlp 是对抗
YouTube 变化的滚动依赖,精确钉版本本身就是这个 bug 的成因;用 `>=` 与同文件
的 `youtube-transcript-api>=1.0.0` 保持一致。
- `bilibili_dm_patch.py`:wrapper 改为透传 `**kwargs`。升级 yt-dlp 后
`_real_extract` 会以 `fatal=False` 调用 `_download_playinfo`,而 wrapper
钉死了签名,导致 **所有 B 站下载** 抛
`TypeError: ... got an unexpected keyword argument 'fatal'`。
- 测试:新增 `test_youtube_metadata_only.py` 覆盖上面两条 YouTube 保证;
`test_bilibili_dm_patch.py` 新增未知 kwargs 透传用例,并让 fake 响应带上
`code` 字段(yt-dlp 2026.x 会先校验信封再返回 data)。
## 验证
- 真实跑通:YouTube(有字幕,走元信息路径)与 B 站(无字幕,走完整下载 +
转写)均能生成笔记。
- `pytest tests/` → 46 passed。唯一失败的
`test_task_serial_executor` 在升级前后表现一致,与本次改动无关,未作改动。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
输入 YouTube 链接生成笔记时任务必定失败:
即使字幕已经抓取成功(日志里能看到
成功获取 YouTube 字幕,共 1021 段),任务仍然在下载阶段崩掉,最终TaskStatus.FAILED。原因
两个独立的问题叠在一起:
1.
yt-dlp被钉在2025.3.31(backend/requirements.txt)YouTube 之后轮换过 player,该版本解不出 nsig 签名,所有音视频格式被丢弃,只剩 storyboard 图片:
2. "只取元信息"的路径却要求选出音频格式
有字幕时
NoteGenerator不下载音视频,只调download(skip_download=True)拿 title/duration/cover。但YoutubeDownloader.download无条件设置了format='bestaudio[ext=m4a]/bestaudio/best',导致一个根本不需要媒体流的调用也会因选不出格式而抛错——把一个字幕已经到手的任务整个带崩,随后回退到"完整下载"再挂一次。第 2 点是放大器:只修 yt-dlp 版本的话,下次 YouTube 再变、yt-dlp 再落后时,同样的全量失败会重演;修掉之后,有字幕的视频会降级为"没有音频"而不是任务失败。
改动
youtube_downloader.pyskip_download时设ignore_no_formats_error=Trueyoutube_downloader.pyext = info.get("ext") or "m4a":跳过下载时 yt-dlp 返回ext=None,dict.get的默认值对显式None不生效,会拼出xxx.Nonerequirements.txtyt-dlp==2025.3.31→>=2026.7.4bilibili_dm_patch.py**kwargs(见下)tests/关于
yt-dlp用>=而不是==yt-dlp 是对抗 YouTube 持续变化的滚动依赖,精确钉版本本身就是这个 bug 的成因——钉到
==2026.7.4只是把同一个定时器重置一遍。同文件的youtube-transcript-api>=1.0.0已有先例。如果维护者倾向保持==,我可以改。这点值得单独说明。升级后 yt-dlp 的
_real_extract会以fatal=False调用_download_playinfo,而bilibili_dm_patch.py的 wrapper 钉死了签名,于是所有 B 站下载都会抛:wrapper 已改为透传
**kwargs,对新旧 yt-dlp 都成立。顺带一提:yt-dlp 2026.x 已经在_download_playinfo里原生注入self._dm_params,这个 monkey-patch 现在是冗余的——但本 PR 不动它,那是另一件事,需要单独验证。验证
真实环境跑通(Docker,
fast-whisper+ DeepSeek):唯一失败的
test_task_serial_executor::test_executor_runs_tasks_one_by_one在升级前后表现完全一致(我在yt-dlp==2025.3.31的干净容器里复现过),与本次改动无关,因此未作改动。新增测试均确认过 red-green:在未修复的代码上会失败,且 B 站那条复现的正是上面production 里的
TypeError。