目录
  1. pytube项目
    1. Github地址
    2. 文档地址
    3. 安装方式
  2. 快速上手
  3. 视频筛选
    1. 1、传统混合音频的视频源
    2. 2、DASH流的视频源
    3. 3、其它过滤条件
  4. 通过itag下载视频
  5. 关于网络
  6. 下载视频
  7. 音视频合并
【模块】pytube,下载YouTube视频无压力

pytube项目

最近我家姑娘的幼儿园外教需要一整套YouTube的教学儿歌《Singing Walrus Music》,在家长群里发出求助后,作为程序员的老爸必须把这个事情安排的明明白白的。

Github地址

https://github.com/nficano/pytube

文档地址

https://python-pytube.readthedocs.io

安装方式

1
pip install pytube

快速上手

1
2
from pytube import YouTube
YouTube('http://youtube.com/watch?v=9bZkp7q19f0').streams.first().download()
  • pytube的 first() 方法,按照作者的解释,会选取最高分辨率的视频进行下载,但亲测后发现效果并不理想。
  • YouTube的是采用DASH Streams的技术架构,其中的DASH技术会将视频、音频进行独立拆分,比如视频有480p video,720p video,音频有44100采样 audio,22050采样audio。通过以下代码即可输出DASH的Representation描述信息:
1
2
yt = YouTube('http://youtube.com/watch?v=9bZkp7q19f0')
yt.streams.all()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[<Stream: itag="22" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2">,
<Stream: itag="43" mime_type="video/webm" res="360p" fps="30fps" vcodec="vp8.0" acodec="vorbis">,
<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2">,
<Stream: itag="36" mime_type="video/3gpp" res="240p" fps="30fps" vcodec="mp4v.20.3" acodec="mp4a.40.2">,
<Stream: itag="17" mime_type="video/3gpp" res="144p" fps="30fps" vcodec="mp4v.20.3" acodec="mp4a.40.2">,
<Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028">,
<Stream: itag="248" mime_type="video/webm" res="1080p" fps="30fps" vcodec="vp9">,
<Stream: itag="136" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.4d401f">,
<Stream: itag="247" mime_type="video/webm" res="720p" fps="30fps" vcodec="vp9">,
<Stream: itag="135" mime_type="video/mp4" res="480p" fps="30fps" vcodec="avc1.4d401e">,
<Stream: itag="244" mime_type="video/webm" res="480p" fps="30fps" vcodec="vp9">,
<Stream: itag="134" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.4d401e">,
<Stream: itag="243" mime_type="video/webm" res="360p" fps="30fps" vcodec="vp9">,
<Stream: itag="133" mime_type="video/mp4" res="240p" fps="30fps" vcodec="avc1.4d4015">,
<Stream: itag="242" mime_type="video/webm" res="240p" fps="30fps" vcodec="vp9">,
<Stream: itag="160" mime_type="video/mp4" res="144p" fps="30fps" vcodec="avc1.4d400c">,
<Stream: itag="278" mime_type="video/webm" res="144p" fps="30fps" vcodec="vp9">,
<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2">,
<Stream: itag="171" mime_type="audio/webm" abr="128kbps" acodec="vorbis">,
<Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus">,
<Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus">,
<Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus">]
  • 其中 itag="22" 的视频为720p并带有音频( acodec="mp4a.40.2" )的视频文件;而 itag="136" 同样的720p的,却是无声版视频文件。
  • 回到之前的pytube的 first() 方法,该方法会优先混合音频的视频源,再选择无声版视频源。这就导致一种极端情况发生, first() 会简单粗暴的选择了低分辨率的混合版视频源,忽略了高清版视频源。
  • 我自己对视频筛选逻辑进行重新改写,后面会说明。

视频筛选

  • pytube提供了多种视频筛选策略

1、传统混合音频的视频源

  • 设置参数为 progressive=True
1
yt.streams.filter(progressive=True).all()
1
2
3
4
5
[<Stream: itag="22" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2">,
<Stream: itag="43" mime_type="video/webm" res="360p" fps="30fps" vcodec="vp8.0" acodec="vorbis">,
<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2">,
<Stream: itag="36" mime_type="video/3gpp" res="240p" fps="30fps" vcodec="mp4v.20.3" acodec="mp4a.40.2">,
<Stream: itag="17" mime_type="video/3gpp" res="144p" fps="30fps" vcodec="mp4v.20.3" acodec="mp4a.40.2">]

2、DASH流的视频源

  • 设置参数为 adaptive=True
1
yt.streams.filter(adaptive=True).all()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[<Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028">,
<Stream: itag="248" mime_type="video/webm" res="1080p" fps="30fps" vcodec="vp9">,
<Stream: itag="136" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.4d401f">,
<Stream: itag="247" mime_type="video/webm" res="720p" fps="30fps" vcodec="vp9">,
<Stream: itag="135" mime_type="video/mp4" res="480p" fps="30fps" vcodec="avc1.4d401e">,
<Stream: itag="244" mime_type="video/webm" res="480p" fps="30fps" vcodec="vp9">,
<Stream: itag="134" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.4d401e">,
<Stream: itag="243" mime_type="video/webm" res="360p" fps="30fps" vcodec="vp9">,
<Stream: itag="133" mime_type="video/mp4" res="240p" fps="30fps" vcodec="avc1.4d4015">,
<Stream: itag="242" mime_type="video/webm" res="240p" fps="30fps" vcodec="vp9">,
<Stream: itag="160" mime_type="video/mp4" res="144p" fps="30fps" vcodec="avc1.4d400c">,
<Stream: itag="278" mime_type="video/webm" res="144p" fps="30fps" vcodec="vp9">,
<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2">,
<Stream: itag="171" mime_type="audio/webm" abr="128kbps" acodec="vorbis">,
<Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus">,
<Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus">,
<Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus">]

3、其它过滤条件

  • only_audio=True :只下载音频
  • only_video :只下载视频
  • subtype='mp4' :下载扩展名为“mp4”的文件,包括音频和视频
  • res="720p" :下载清晰度为720p的视频
  • abr="64kbps" :下载码率为64kbps的视频
  • video_codec="vp9" :下载压缩格式为vp9的视频
  • audio_codec="vorbis" :下载压缩格式为vorbis的音频

通过itag下载视频

  • YouTube对每个DASH流的视频源的类型给了一个独立的id,称为itag
  • 可通过 get_by_itag 方法下载对应视频
1
yt.streams.get_by_itag(22)
  • itag对应的类型如下
itag CodeContainerContentResolutionBitrateRangeVR / 3D
5flvaudio/video240p---
6flvaudio/video270p---
173gpaudio/video144p---
18mp4audio/video360p---
22mp4audio/video720p---
34flvaudio/video360p---
35flvaudio/video480p---
363gpaudio/video180p---
37mp4audio/video1080p---
38mp4audio/video3072p---
43webmaudio/video360p---
44webmaudio/video480p---
45webmaudio/video720p---
46webmaudio/video1080p---
82mp4audio/video360p--3D
83mp4audio/video480p--3D
84mp4audio/video720p--3D
85mp4audio/video1080p--3D
92hlsaudio/video240p--3D
93hlsaudio/video360p--3D
94hlsaudio/video480p--3D
95hlsaudio/video720p--3D
96hlsaudio/video1080p---
100webmaudio/video360p--3D
101webmaudio/video480p--3D
102webmaudio/video720p--3D
132hlsaudio/video240p--
133mp4video240p--
134mp4video360p--
135mp4video480p--
136mp4video720p--
137mp4video1080p--
138mp4video2160p60--
139m4aaudio-48k-
140m4aaudio-128k-
141m4aaudio-256k-
151hlsaudio/video72p--
160mp4video144p--
167webmvideo360p--
168webmvideo480p--
169webmvideo1080p--
171webmaudio-128k-
218webmvideo480p--
219webmvideo144p--
242webmvideo240p--
243webmvideo360p--
244webmvideo480p--
245webmvideo480p--
246webmvideo480p--
247webmvideo720p--
248webmvideo1080p--
249webmaudio-50k-
250webmaudio-70k-
251webmaudio-160k-
264mp4video1440p--
266mp4video2160p60--
271webmvideo1440p--
272webmvideo4320p--
278webmvideo144p--
298mp4video720p60--
299mp4video1080p60--
302webmvideo720p60--
303webmvideo1080p60--
308webmvideo1440p60--
313webmvideo2160p--
315webmvideo2160p60--
330webmvideo144p60-hdr
331webmvideo240p60-hdr
332webmvideo360p60-hdr
333webmvideo480p60-hdr
334webmvideo720p60-hdr
335webmvideo1080p60-hdr
336webmvideo1440p60-hdr
337webmvideo2160p60-hdr
394mp4video144p--
395mp4video240p--
396mp4video360p--
397mp4video480p--
398mp4video720p--
399mp4video1080p--
400mp4video1440p--
401mp4video2160p--
402mp4video2880p--

关于网络

  • 因为需要避免西方资本主义思想毒害,网络经常请求不稳定
  • 常见的错误会有以下两种:
    • HTTPError
    • URLError
    • 使用Pycharm的同学还会遇到 ConnectionResetError
  • 前两种错误需要引入 from urllib.error import HTTPError, URLError
  • 然后通过where循环,try…except… 来重复请求
1
2
3
4
5
6
7
8
9
10
11
12
yt = None
while True:
try:
yt = YouTube(url)
break
except HTTPError:
self.logger.error("请求出错一次:HTTPError")
continue
except URLError:
self.logger.error("请求出错一次:URLError")
continue
streams = yt.streams.filter(subtype='mp4').all()

下载视频

  • 当确认了符合条件的视频后,可通过 download 的方式直接下载
1
2
3
4
from pytube import YouTube
yt=YouTube('http://youtube.com/watch?v=9bZkp7q19f0')
mp4=yt.streams.first()
mp4.download(output_path, filename, filename_prefix)
  • 其中 download 会接受3个参数:
    • output_path :视频输出路径;
    • filename :视频输出名称,默认为视频的标题,该名称不需要扩展名;
    • filename_prefix :视频名称前缀,这里主要是区分音频和视频,因为音频和视频下载后名称相同,格式相同,前者会被后者覆盖掉。可以增加前缀来进行区分,比如音频为“audio_FilmTitle.mp4”、视频为“video_FilmTitle.mp4”

音视频合并

文章作者: Haibei
文章链接: http://www.haibei.online/posts/3728898916.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Haibei的博客
打赏
  • 微信
  • 支付宝

评论