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

Pau*_*ulD 61 youtube

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

我在网上搜索但找不到任何有用的东西,所有链接都指向此类服务,但没有说明它们是如何实际实现的。

slh*_*hck 53

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

要了解这是如何完成的,请查看YouTube 提取器。这太多了,无法在这里展示。其他提取器存在用于更简单的站点

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

这意味着在 Javascript 执行的某个地方,有播放器的初始化代码,包含重要的参数,比如在哪里实际找到视频。

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

通常,Javascript 代码本身被混淆以使其更难重新设计,使用诸如xyz而不是player.

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

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

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

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

  • §5.1.L 中的 YouTube [服务条款](https://www.youtube.com/static?gl=GB&amp;template=terms) 禁止通过流媒体以外的任何其他方式消费其内容,因此理论上是不允许的。在实践中,他们将无法强制执行。任何下载器都可以或多或少地模拟它只是流式传输。 (33认同)
  • @slhck Flash 也可以自己发出 HTTP 请求。相反,它使用浏览器的 HTTP 引擎。如果 Flash 本身发出请求,它们将不会对浏览器“可见”。当然对广告商来说会很棒。;) (5认同)
  • 一个问题,Youtube/Google 对此有何政策?他们对这个没意见,还是没那么多? (3认同)
  • @slhck 他们不能*以编程方式*执行它,但是如果他们让他们的律师团队退出,他们可以*合法地*执行它吗? (3认同)
  • @StevenPenny 你有任何非缩小版的吗? (2认同)

Ste*_*nny 38

从一个典型的视频开始:

https://www.youtube.com/watch?v=XeojXq6ySs4
Run Code Online (Sandbox Code Playgroud)

使用相同的 ID,构造一个像这样的 URL:

https://www.youtube.com/get_video_info?eurl=https://www.youtube.com&video_id=XeojXq6ySs4
Run Code Online (Sandbox Code Playgroud)

响应将是一个查询字符串,如下所示(为了可读性进行了编辑):

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&
Run Code Online (Sandbox Code Playgroud)

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

https://www.youtube.com/watch?v=XeojXq6ySs4
Run Code Online (Sandbox Code Playgroud)

然后提取signatureCipher值,这是一个查询字符串,像这样:

sp=sig&
s=VZVZOq0QJ8wRgIhANWm3sPF-2hbzQQGrErjQFMNmxTfALcoZkZ4IVR1djIpAiEA8HFKix6d4B3T...&
url=https://r3---sn-q4flrnek.googlevideo.com/videoplayback%3Fexpire%3D16201927...
Run Code Online (Sandbox Code Playgroud)

url是URL的音频或视频。但是,在访问 URL 之前,您必须向查询字符串添加一个条目。新键是sp上面的值 (sig在这种情况下)。新值是s上面的值(VZVZOq0QJ8wRgIhANWm3sPF-2hbzQQGrErjQFMNmxTfALcoZkZ4IVR1djIpA...在这种情况下)。但是,在添加新条目之前,您必须对s值进行解码。要解码该值,请执行以下步骤。首先,访问原始页面:

https://www.youtube.com/watch?v=XeojXq6ySs4
Run Code Online (Sandbox Code Playgroud)

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

/s/player/3e7e4b43/player_ias.vflset/en_US/base.js
Run Code Online (Sandbox Code Playgroud)

你可以变成:

https://www.youtube.com/s/player/3e7e4b43/player_ias.vflset/en_US/base.js
Run Code Online (Sandbox Code Playgroud)

在这个新页面中,会有一些像这样的代码:

https://www.youtube.com/get_video_info?eurl=https://www.youtube.com&video_id=XeojXq6ySs4
Run Code Online (Sandbox Code Playgroud)

取原始s值,并通过这个函数运行它:

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&
Run Code Online (Sandbox Code Playgroud)

结果看起来差不多,但是乱七八糟:

AOq0QJ8wRAIgc-ylc9Z4lSO2CozG4B-W9uC5zeuTNTDvqH_nQaHGNmkCICsZJGbEjKDmDSnKg_atTR...
Run Code Online (Sandbox Code Playgroud)

最后,您可以构建生成的 URL:

https://r3---sn-q4fl6nz7.googlevideo.com/videoplayback?vprv=1&
id=o-AHThxQXyxJ3jfw5EBUJeT0IJLrdQeYpMdCsCImMfbuac&
sig=AOq0QJ8wRAIgc-ylc9Z4lSO2CozG4B-W9uC5zeuTNTDvqH_nQaHGNmkCICsZJGbEjKDmDSnKg_...
Run Code Online (Sandbox Code Playgroud)

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

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