You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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后再运行脚本。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 02:34:51