使用yt_dlp下载字幕时触发FileNotFoundError(重命名失败)
解决yt_dlp字幕下载时的FileNotFoundError问题
问题背景
使用yt_dlp Python API下载YouTube字幕时,触发FileNotFoundError,报错显示尝试将.part临时文件重命名为最终字幕文件失败。尽管命令行版本可正常运行,但API调用始终报错。
代码片段
import yt_dlp import os def download_video(self, url): ydl_opts = { 'outtmpl': self.download_dir + '/%(id)s.%(ext)s', 'writesubtitles': True, 'subtitleslangs': ['en'], 'writeautomaticsub': True, 'skip_download': True, # 仅下载字幕,跳过视频 'quiet': True, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(url) try: vtt_fp = info_dict['requested_subtitles']['en']['filepath'] if os.path.exists(vtt_fp): print(f"字幕文件已找到: {vtt_fp}") else: print(f"未找到字幕文件: {vtt_fp}") except KeyError as e: print(f"键错误: {e}") except Exception as e: print(f"发生错误: {e}")
报错信息
File "backend/venv/lib/python3.10/site-packages/yt_dlp/downloader/common.py", line 245, in wrapper return func(self, *args, **kwargs) File "backend/venv/lib/python3.10/site-packages/yt_dlp/downloader/common.py", line 270, in try_rename os.replace(old_filename, new_filename) FileNotFoundError: [Errno 2] No such file or directory: './download/Auuk1y4DRgk.en.vtt.part' -> './download/Auuk1y4DRgk.en.vtt'
已确认事项:
- 下载目录中存在对应
.part文件 - 路径权限正常,使用最新版yt_dlp(2024.8.6)
- 命令行工具可正常完成字幕下载
问题解答
1. 为何会出现重命名不存在文件的错误?
核心原因是Python API与命令行的执行流程差异:
- 命令行模式下,yt_dlp会自动完成下载后的收尾工作,包括将
.part临时文件重命名为最终文件名。 - 但在API调用中,仅调用
extract_info()不会触发文件收尾逻辑——即使skip_download=True,字幕的.part文件已下载,但yt_dlp并未执行重命名步骤。此外,如果目标视频没有手动英文字幕,requested_subtitles['en']可能指向未生成的文件,导致后续重命名逻辑出错。
2. 需检查的额外配置与步骤
- 调用
download()方法触发收尾:即使设置skip_download=True,调用ydl.download([url])会触发字幕文件的收尾处理(重命名.part),仅用extract_info()不会执行这一步。修改后的代码片段:with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(url, download=False) ydl.download([url]) # 触发字幕收尾逻辑 # 后续处理... - 区分视频与字幕的命名模板:当前
outtmpl未区分视频和字幕,建议单独配置字幕路径,避免冲突:'outtmpl': { 'default': f"{self.download_dir}/%(id)s.%(ext)s", 'subtitle': f"{self.download_dir}/%(id)s.%(ext)s", } - 检查字幕类型:优先确认手动字幕是否存在,不存在则 fallback 到自动字幕:
# 获取正确的字幕文件路径 subtitle_path = None if 'en' in info_dict.get('requested_subtitles', {}): subtitle_path = info_dict['requested_subtitles']['en']['filepath'] elif 'en' in info_dict.get('automatic_captions', {}): # 取第一个自动字幕源 subtitle_path = info_dict['automatic_captions']['en'][0]['filepath']
3. 调试与错误处理优化
- 开启详细日志:关闭
quiet: True,启用verbose: True,查看完整的字幕下载流程,定位.part文件的处理细节:ydl_opts = { # ... 其他配置 'quiet': False, 'verbose': True, } - 手动处理重命名:如果自动重命名失败,手动检查并重命名
.part文件:if subtitle_path: part_file = subtitle_path + '.part' if os.path.exists(part_file) and not os.path.exists(subtitle_path): os.replace(part_file, subtitle_path) - 使用字幕后处理器:添加后处理器确保字幕文件正确生成:
ydl_opts = { # ... 其他配置 'postprocessors': [ {'key': 'FFmpegSubtitlesConvertor', 'format': 'vtt'} ], }
内容的提问来源于stack exchange,提问作者Zachzhao
相关产品推荐
相关产品推荐

