我正在观看一个 youtube 视频,我决定研究其视频播放器的某些部分。我注意到,与我见过的大多数 HTML5 视频不同,Youtube 的视频播放器不做普通的视频源,而是使用 blob url 作为源。
以前我测试过 HTML5 视频,我发现服务器从一开始就开始流式传输整个视频,并在后台缓冲完整的其余视频。这意味着如果您的视频为 300 兆,则将下载所有 300 兆。如果你搜索到中间,它将从搜索位置开始下载,一直到最后。
Youtube 不能以这种方式工作(至少在 chrome 中)。相反,它设法控制缓冲,因此它仅在暂停时缓冲一定量。它似乎也只缓冲相关的片段,所以如果你跳过它会确保不会缓冲不太可能被观看的片段。
在我尝试调查它是如何工作的过程中,我注意到 video src 标记的值为blob:http%3A//www.youtube.com/ee625eee-2802-49b2-a13f-eb374d551d54
,这将我指向blobs,然后将我引导到typed arrays。使用这两个资源,我可以将 mp4 视频加载到 blob 中,并将其显示在 HTML5 视频标签中。
然而,我现在坚持的是 Youtube 是如何处理这些片段的。查看网络流量,它似乎发送请求,以http://r6---sn-p5q7ynee.c.youtube.com/videoplayback
1.1mb 的块返回二进制视频数据。似乎还值得注意的是,由于 HTML5 视频请求导致的大多数正常请求似乎在流式传输时收到了 206 响应代码,但 youtube 的 playvideo 调用得到了 200 响应。
我试图尝试仅加载一系列字节(通过设置Range
http 标头),但不幸的是失败了(我假设是因为视频附带的视频没有元数据)。
在这一点上,我一直在弄清楚 Youtube 是如何做到这一点的。我提出了几个想法,但没有一个完全被我所接受:
/videoplayback
1) Youtube 每次通话都会发送自包含的视频和音频块。这在上传方面似乎是一个相当沉重的负担,而且似乎很难将它们拼接在一起以使其看起来像是一个无缝的视频。$('video').duration
此外,从调用and判断,视频标签似乎认为它是一个完整的视频,$('video').currentTime
这让我相信视频标签认为它是一个单独的视频文件。最后,vidoe src 标签永远不会改变,这让我相信它正在处理单个 blob 而不是切换 blob。
2) Youtube 构造一个空的 blob,其大小预先设置为完整的视频数组,并在下载 blob 时用片段更新 blob。然后它会确保用户没有离最后下载的片段太近(以防止用户进入 blob 的未下载部分)。我看到的问题是我看不到任何通过javascript动态更新blob的方法(尽管我可能只是在谷歌搜索时遇到了麻烦)
3) Youtube 下载元数据,然后在下载视频片段时按顺序开始构建 blob。我用这种方法看到的问题是我不明白它如何处理后缓冲区域中的搜索。
也许我只是错过了一个明显的答案,就在我面前。有人有什么想法吗?
编辑:我只是想到了第四个选项。另一个想法是他们可能使用文件 API 将二进制块写入文件并使用该文件流出。文件 API 似乎具有寻找特定位置的能力,因此允许您用空字节填充视频并在收到它们时填充它们。这肯定也会适应视频搜索。