使用Python的yt-dlp下载YouTube视频合并时触发[WinError 2]错误
问题:合并FFmpeg时出现[WinError 2]找不到文件错误?
我开发了一款Python脚本,借助yt-dlp实现手动选择并下载YouTube平台的视频、音频分离流,随后通过FFmpeg将下载的音视频文件合并为完整视频。脚本流程为:从指定YouTube URL获取可用的纯视频、纯音频格式列表,允许用户选择偏好格式,下载对应流后执行合并操作。但运行脚本时,在合并环节出现如下错误:
Merging video and audio... An error occurred: [WinError 2] The system cannot find the file specified
完整代码如下:
import yt_dlp import os import subprocess # Function to list and allow manual selection of video and audio formats def download_and_merge_video_audio_with_selection(url, download_path): try: # Ensure the download path exists if not os.path.exists(download_path): os.makedirs(download_path) # Get available formats from yt-dlp ydl_opts = {'listformats': True} with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(url, download=False) formats = info_dict.get('formats', []) # List available video formats (video only) print("\nAvailable video formats:") video_formats = [f for f in formats if f.get('vcodec') != 'none' and f.get('acodec') == 'none'] for idx, f in enumerate(video_formats): resolution = f.get('height', 'unknown') filesize = f.get('filesize', 'unknown') print(f"{idx}: Format code: {f['format_id']}, Resolution: {resolution}p, Size: {filesize} bytes") # Let user select the desired video format video_idx = int(input("\nEnter the number corresponding to the video format you want to download: ")) video_format_code = video_formats[video_idx]['format_id'] # List available audio formats (audio only) print("\nAvailable audio formats:") audio_formats = [f for f in formats if f.get('acodec') != 'none' and f.get('vcodec') == 'none'] for idx, f in enumerate(audio_formats): abr = f.get('abr', 'unknown') # Audio bitrate filesize = f.get('filesize', 'unknown') print(f"{idx}: Format code: {f['format_id']}, Audio Bitrate: {abr} kbps, Size: {filesize} bytes") # Let user select the desired audio format audio_idx = int(input("\nEnter the number corresponding to the audio format you want to download: ")) audio_format_code = audio_formats[audio_idx]['format_id'] # Video download options (based on user choice) video_opts = { 'format': video_format_code, # Download user-selected video format 'outtmpl': os.path.join(download_path, 'video.%(ext)s'), # Save video as video.mp4 } # Audio download options (based on user choice) audio_opts = { 'format': audio_format_code, # Download user-selected audio format 'outtmpl': os.path.join(download_path, 'audio.%(ext)s'), # Save audio as audio.m4a } # Download the selected video format print("\nDownloading selected video format...") with yt_dlp.YoutubeDL(video_opts) as ydl_video: ydl_video.download([url]) # Download the selected audio format print("\nDownloading selected audio format...") with yt_dlp.YoutubeDL(audio_opts) as ydl_audio: ydl_audio.download([url]) # Paths to the downloaded video and audio files video_file = os.path.join(download_path, 'video.webm') # Assuming best video will be .mp4 audio_file = os.path.join(download_path, 'audio.m4a') # Assuming best audio will be .m4a output_file = os.path.join(download_path, 'final_output.mp4') # Final merged file # FFmpeg command to merge audio and video ffmpeg_cmd = [ 'ffmpeg', '-i', video_file, '-i', audio_file, '-c', 'copy', output_file ] # Run FFmpeg to merge audio and video print("\nMerging video and audio...") subprocess.run(ffmpeg_cmd, check=True) print(f"\nDownload and merging complete! Output file: {output_file}") except Exception as e: print(f"An error occurred: {e}") # Example usage video_url = "https://www.youtube.com/watch?v=SOwk8FhfEZY" # Replace with your desired video URL download_path = 'C:/Users/vinod/Downloads/VideoDownload' # Replace with your desired download path download_and_merge_video_audio_with_selection(video_url, download_path)
环境依赖要求:
- yt-dlp:执行
pip install yt-dlp安装 - FFmpeg:需安装并添加至系统PATH
寻求该错误的解决方法。
解决方法
1. 检查FFmpeg是否正确安装并加入系统PATH
WinError 2最常见的原因是系统找不到FFmpeg可执行文件。
- 打开命令提示符,输入
ffmpeg -version,如果提示找不到命令,说明FFmpeg未安装或未添加到系统PATH。 - 修复步骤:
- 下载对应系统版本的FFmpeg,解压后找到
bin文件夹。 - 将该
bin文件夹路径添加到系统环境变量PATH中。 - 重启命令提示符或Python IDE后再运行脚本。
- 下载对应系统版本的FFmpeg,解压后找到
2. 修正硬编码的音视频文件名
代码中硬编码了video.webm和audio.m4a,但用户选择的格式扩展名可能与假设不符(比如视频可能是mp4,音频可能是webm),导致找不到文件。
- 修复步骤:
- 在选择格式后,获取对应格式的实际扩展名,用动态生成的文件名替代硬编码值。
- 修改后的关键代码片段:
# 获取选中视频的扩展名并设置下载路径 video_ext = video_formats[video_idx]['ext'] video_opts = { 'format': video_format_code, 'outtmpl': os.path.join(download_path, f'video.{video_ext}'), } # 获取选中音频的扩展名并设置下载路径 audio_ext = audio_formats[audio_idx]['ext'] audio_opts = { 'format': audio_format_code, 'outtmpl': os.path.join(download_path, f'audio.{audio_ext}'), } # 直接使用动态生成的文件路径 video_file = os.path.join(download_path, f'video.{video_ext}') audio_file = os.path.join(download_path, f'audio.{audio_ext}')
3. 检查下载路径的权限
如果下载路径位于系统保护目录(如C盘根目录、Program Files等),脚本可能没有读写权限,导致文件未正确下载。
- 修复步骤:
- 更换到有读写权限的路径(比如用户文档目录)。
- 或右键点击Python IDE/脚本,选择“以管理员身份运行”。
修复后的完整代码
import yt_dlp import os import subprocess def download_and_merge_video_audio_with_selection(url, download_path): try: if not os.path.exists(download_path): os.makedirs(download_path) ydl_opts = {'listformats': True} with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(url, download=False) formats = info_dict.get('formats', []) # 列出视频格式 print("\nAvailable video formats:") video_formats = [f for f in formats if f.get('vcodec') != 'none' and f.get('acodec') == 'none'] for idx, f in enumerate(video_formats): resolution = f.get('height', 'unknown') filesize = f.get('filesize', 'unknown') print(f"{idx}: Format code: {f['format_id']}, Resolution: {resolution}p, Size: {filesize} bytes, Ext: {f['ext']}") video_idx = int(input("\nEnter the number corresponding to the video format you want to download: ")) video_format_code = video_formats[video_idx]['format_id'] video_ext = video_formats[video_idx]['ext'] # 列出音频格式 print("\nAvailable audio formats:") audio_formats = [f for f in formats if f.get('acodec') != 'none' and f.get('vcodec') == 'none'] for idx, f in enumerate(audio_formats): abr = f.get('abr', 'unknown') filesize = f.get('filesize', 'unknown') print(f"{idx}: Format code: {f['format_id']}, Audio Bitrate: {abr} kbps, Size: {filesize} bytes, Ext: {f['ext']}") audio_idx = int(input("\nEnter the number corresponding to the audio format you want to download: ")) audio_format_code = audio_formats[audio_idx]['format_id'] audio_ext = audio_formats[audio_idx]['ext'] # 视频下载配置 video_opts = { 'format': video_format_code, 'outtmpl': os.path.join(download_path, f'video.{video_ext}'), } # 音频下载配置 audio_opts = { 'format': audio_format_code, 'outtmpl': os.path.join(download_path, f'audio.{audio_ext}'), } # 下载视频 print("\nDownloading selected video format...") with yt_dlp.YoutubeDL(video_opts) as ydl_video: ydl_video.download([url]) # 下载音频 print("\nDownloading selected audio format...") with yt_dlp.YoutubeDL(audio_opts) as ydl_audio: ydl_audio.download([url]) # 合并文件路径 video_file = os.path.join(download_path, f'video.{video_ext}') audio_file = os.path.join(download_path, f'audio.{audio_ext}') output_file = os.path.join(download_path, 'final_output.mp4') # FFmpeg合并命令 ffmpeg_cmd = [ 'ffmpeg', '-i', video_file, '-i', audio_file, '-c', 'copy', output_file ] print("\nMerging video and audio...") subprocess.run(ffmpeg_cmd, check=True) print(f"\nDownload and merging complete! Output file: {output_file}") except Exception as e: print(f"An error occurred: {e}") # 示例使用 video_url = "https://www.youtube.com/watch?v=SOwk8FhfEZY" download_path = 'C:/Users/vinod/Downloads/VideoDownload' download_and_merge_video_audio_with_selection(video_url, download_path)
内容的提问来源于stack exchange,提问作者Aditya Kumar
相关产品推荐
相关产品推荐

