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

使用Pytube下载YouTube视频时部分分辨率无法下载的问题

问题描述

我在用Python编写YouTube音视频下载脚本,视频下载功能存在异常:部分分辨率(如1080p)可正常下载,但选择480p这类分辨率时会报错:'NoneType' object has no attribute 'download'。我希望能下载视频支持的任意分辨率,请问下载脚本哪里有遗漏?

相关代码

下载函数:

def VideoDownload_mp4(url, res):
    try:
        yt = pytube.YouTube(url)
        folder = "YouTube Videos"
        video = yt.streams.get_by_resolution(resolution=res)
        video.download(folder)
        print("downloaded.")
    except Exception as e:
        print(f"Error: {e}")

获取可用分辨率的函数:

def GetVideoQuality(url):
    yt = pytube.YouTube(url)
    base_list = []
    for stream in yt.streams:
        resolution = stream.resolution
        bitrate = stream.bitrate
        base_list.append({'resolution':resolution, 'bitrate':bitrate})
    
    new_dict = {}
    fixed_list = []

    for diccionario in base_list:
        resolution = diccionario['resolution']
        bitrate = diccionario['bitrate']
        if resolution is not None:
            if resolution not in new_dict:
                new_dict[resolution] = bitrate
                fixed_list.append(diccionario.copy())
            else:
                if bitrate > new_dict[resolution]:
                    new_dict[resolution] = bitrate
                    fixed_list.remove([d for d in fixed_list if d['resolution'] == resolution][0])
                    fixed_list.append(diccionario.copy())

    return fixed_list

示例参数:

  • url = "https://youtu.be/YEqWLCBrgic?si=Z245EINTenbGqasr"
  • res = "720p"

问题原因

get_by_resolution()方法仅能匹配视频+音频合并的流,但YouTube的中低分辨率(如480p)往往没有合并流,而是拆分为纯视频流和纯音频流两个独立文件。此时get_by_resolution()找不到对应合并流,会返回None,调用download()自然触发报错。

另外你的分辨率获取脚本会列出所有带分辨率的流(包括纯视频流),但这些流无法通过get_by_resolution()获取,导致你选中的部分分辨率实际无对应合并流可下载。


解决方案

修改下载逻辑,优先匹配合并流;若不存在,则下载对应分辨率的纯视频流+最高质量音频流,再通过ffmpeg合并两者。

方案1:兼容合并流与分离流的下载函数

from pytube import YouTube
import os
import subprocess

def VideoDownload_mp4(url, res):
    try:
        yt = YouTube(url)
        folder = "YouTube Videos"
        os.makedirs(folder, exist_ok=True)
        
        # 优先尝试下载对应分辨率的合并流
        video_stream = yt.streams.filter(progressive=True, resolution=res).first()
        
        if video_stream:
            video_stream.download(folder)
            print(f"{res} 合并流下载完成")
            return
        
        # 无合并流时,下载纯视频流+音频流
        # 获取对应分辨率的最高码率纯视频流
        video_stream = yt.streams.filter(adaptive=True, resolution=res, only_video=True).order_by('bitrate').desc().first()
        # 获取最高质量音频流
        audio_stream = yt.streams.filter(only_audio=True).order_by('bitrate').desc().first()
        
        if not video_stream:
            print(f"找不到 {res} 分辨率的视频流")
            return
        if not audio_stream:
            print("找不到音频流")
            return
        
        # 下载临时文件
        video_path = video_stream.download(folder, filename_prefix="temp_video_")
        audio_path = audio_stream.download(folder, filename_prefix="temp_audio_")
        
        # 用ffmpeg合并视频与音频(需提前安装ffmpeg并加入系统PATH)
        output_filename = f"{yt.title}_{res}.mp4"
        output_path = os.path.join(folder, output_filename)
        
        subprocess.run([
            "ffmpeg", "-i", video_path, "-i", audio_path,
            "-c:v", "copy", "-c:a", "aac", "-y", output_path
        ], check=True)
        
        # 删除临时文件
        os.remove(video_path)
        os.remove(audio_path)
        
        print(f"{res} 视频+音频合并完成,保存至 {output_path}")
        
    except Exception as e:
        print(f"错误: {e}")

方案2:优化分辨率获取脚本(仅显示可直接下载的合并流)

如果你希望用户只选择存在合并流的分辨率,可以修改获取函数:

def GetVideoQuality(url):
    yt = YouTube(url)
    # 仅获取合并流的分辨率,去重后按清晰度从高到低排序
    resolutions = sorted(
        list({stream.resolution for stream in yt.streams.filter(progressive=True) if stream.resolution}),
        key=lambda x: int(x[:-1]), reverse=True
    )
    # 转换为原字典格式返回
    fixed_list = []
    for res in resolutions:
        stream = yt.streams.filter(progressive=True, resolution=res).order_by('bitrate').desc().first()
        fixed_list.append({'resolution': res, 'bitrate': stream.bitrate})
    return fixed_list

注意事项
  • 使用方案1的合并逻辑时,需提前安装ffmpeg,并确保其在系统环境变量PATH中。
  • pytube可能因YouTube接口更新出现兼容性问题,建议定期更新:pip install --upgrade pytube

内容的提问来源于stack exchange,提问作者ZeloZalis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:46:16