所有这些“从 YouTube 保存视频”服务是如何工作的?

所有这些“从 YouTube 保存视频”服务是如何工作的?

我的意思是,它们一般是如何工作的?它们如何接收视频流本身的链接(而不仅仅是包含 Flash 播放器的页面)?

我在网上搜索过,但没有找到任何有用的信息,所有链接都指向此类服务,但没有一个表明它们实际上是如何实现的。

答案1

有一个非常流行的开源命令行下载器叫做youtube-dl,它就是这样做的。它从给定的 YouTube 链接(或任何其他流行的网络视频网站,如 Vimeo、Yahoo! Video、uStream 等)抓取实际的视频和音频文件链接。

要了解如何做到这一点,请查看YouTube 提取器。这里就不一一介绍了。还有其他提取器对于更简单的网站

为了找到视频流,您必须假装是实际的浏览器客户端,尝试加载视频。这意味着您首先必须解析 HTML 代码,加载相关的 Javascript 代码,并初始化播放器对象,该对象通过 HTML 元素播放视频<video>

这意味着在 Javascript 执行的某个地方,存在播放器的初始化代码,其中包含重要参数,例如实际找到视频的位置。

在最简单的情况下,视频可能作为某个 MP4 文件的 URL 直接存在于某个配置对象中。通过查看元素src的属性,可以很容易地解析<video>它。但它也可以在客户端和某个身份验证服务器之间协商一些特定的下载令牌的情况下动态生成。视频也可能通过 URL 播放blob,因此您无法直接看到它,因为它是通过MediaSource API

通常,Javascript 代码本身会被混淆,以使其更难重新设计,使用类似xyz而不是 的变量player

如今,大多数视频网站都在后台使用 MPEG-DASH 或 Apple 的 HTTP Live Streaming (HLS)。它们不使用视频文件的直接 URL,而是使用所谓的“清单”文件。清单提供元信息以获取实际的视频流。清单文件(.mpd例如在 DASH 和.m3u8HLS 中)将包含视频和音频片段的链接,您稍后必须将它们组合起来才能获得可播放的文件。

许多网站将这些清单从服务器传输到客户端播放器,因此如果您可以检查客户端发出的网络请求,那么可能会找到一个.mpd文件,然后您可以使用该文件从您自己的客户端下载视频片段。

但是,清单也可以通过其他侧信道传输,嵌入到某些 Javascript 代码中,动态生成等等。对于youtube-dl,您可以看到代码如何尝试从传输的配置信息中提取 DASH 清单 URL。

对此没有通用的解决方案。它需要仔细检查和调试目标站点。

答案2

从一个典型的视频开始:

https://www.youtube.com/watch?v=XeojXq6ySs4

使用相同的 ID,构造如下 URL:

https://www.youtube.com/get_video_info?eurl=https://www.youtube.com&video_id=XeojXq6ySs4

响应将是一个查询字符串,如下所示(为便于阅读已编辑):

innertube_api_version=v1&
innertube_context_client_version=2.20210504.09.00&
player_response=%7B%22responseContext%22%3A%7B%22serviceTrackingParams%22%3A...
ps=desktop-polymer&
root_ve_type=27240&

提取player_response值。这将是一个 JSON 对象,如下所示:

{
  "streamingData": {
    "adaptiveFormats": [
      {
        "itag": 137,
        "mimeType": "video/mp4; codecs=\"avc1.640020\"",
        "bitrate": 570464,
        "height": 1080,
        "signatureCipher": "s=VZVZOq0QJ8wRgIhANWm3sPF-2hbzQQGrErjQFMNmxTfALco..."
      }
    ]
  }
}

然后提取signatureCipher值,这是一个查询字符串,如下所示:

sp=sig&
s=VZVZOq0QJ8wRgIhANWm3sPF-2hbzQQGrErjQFMNmxTfALcoZkZ4IVR1djIpAiEA8HFKix6d4B3T...&
url=https://r3---sn-q4flrnek.googlevideo.com/videoplayback%3Fexpire%3D16201927...

url是音频或视频的 URL。但在访问 URL 之前,您必须向查询字符串添加一个条目。新键是上面的值 spsig在本例中)。新值是上面的值sVZVZOq0QJ8wRgIhANWm3sPF-2hbzQQGrErjQFMNmxTfALcoZkZ4IVR1djIpA...在本例中)。但在添加新条目之前,您必须解码该s值。要解码该值,请执行以下步骤。首先,访问原始页面:

https://www.youtube.com/watch?v=XeojXq6ySs4

在源代码中,将会有一些这样的文本:

/s/player/3e7e4b43/player_ias.vflset/en_US/base.js

你可以将其变成:

https://www.youtube.com/s/player/3e7e4b43/player_ias.vflset/en_US/base.js

在这个新页面中,将会有一些如下代码:

var uy={an:function(a){a.reverse()},
gN:function(a,b){a.splice(0,b)},
J4:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b%a.length]=c}};
vy=function(a){a=a.split("");uy.gN(a,2);uy.J4(a,47);uy.gN(a,1);uy.an(a,49);
uy.gN(a,2);uy.J4(a,4);uy.an(a,71);uy.J4(a,15);uy.J4(a,40);return a.join("")};

取原始s值并通过此函数运行它:

vy('_l_lOq0QJ8wRAIgc-yNc9Z4lSO2CozG4B-W9uC5zeuTATDvqHlnQaHGNmkCICsZJGbEjKDmD...')

结果看起来大致相同,但是有些混乱:

AOq0QJ8wRAIgc-ylc9Z4lSO2CozG4B-W9uC5zeuTNTDvqH_nQaHGNmkCICsZJGbEjKDmDSnKg_atTR...

最后你可以构建最终的 URL:

https://r3---sn-q4fl6nz7.googlevideo.com/videoplayback?vprv=1&
id=o-AHThxQXyxJ3jfw5EBUJeT0IJLrdQeYpMdCsCImMfbuac&
sig=AOq0QJ8wRAIgc-ylc9Z4lSO2CozG4B-W9uC5zeuTNTDvqH_nQaHGNmkCICsZJGbEjKDmDSnKg_...

我有一个执行以下步骤的库和程序:

https://pkg.go.dev/github.com/89z/mech/youtube

相关内容