我在观看YouTube视频时,决定调查其视频播放器的某些部分。我注意到与我见过的大多数HTML5视频不同,Youtube的视频播放器没有使用普通的视频源,而是将blob url作为源。
以前,我测试过HTML5视频,并发现服务器从开始就开始流式传输整个视频,并在后台缓冲完整的视频。这意味着如果您的视频大小为300兆字节,那么就会下载全部300兆字节。如果您跳转到中间,它将从跳转位置开始下载直到末尾。
Youtube不以这种方式工作(至少在Chrome浏览器中)。相反,它设法控制缓冲,因此仅在暂停时缓存一定数量。它还似乎只缓存相关片段,因此如果您跳来跳去,它会确保不缓存不太可能被观看的片段。
在我试图调查它是如何工作的时候,我注意到视频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头信息,仅加载字节范围,但遗憾的是失败了(我猜测是因为视频没有附带元数据)。
目前我卡在如何解决这个问题上。我想到了几个方法,但都存在一些问题并无法完全解决:
1)Youtube会在每个/videoplayback
请求中发送自包含的音频和视频块。这看起来对上传端的负担很重,并且似乎很难将它们拼接在一起使其看起来像一个无缝的视频。此外,从调用$('video').duration
和$('video').currentTime
来看,视频标签也认为它是一个完整的视频。最后,视频src标签从未更改,这使我相信它正在使用单个blob而不是切换blob。
2)Youtube构建一个预先设置为完整视频数组大小的空blob,并在下载过程中更新blob的片段。然后,它会确保用户没有接近最后一个下载的部分(以防止用户进入未下载的blob部分)。我认为这个方法的问题在于我没有看到任何通过javascript动态更新blob的方法(也许我只是在搜索时有些困难)
3)Youtube下载元数据,然后按顺序构建blob,随着下载它们将视频块附加到blob上。我认为这种方法的问题在于我不理解它如何处理已缓冲区域内的寻址。
也许我只是忽略了一个显而易见的答案。有没有人有任何想法?
编辑:我刚想到第四个选择。另一个想法是他们可能使用文件API将二进制块写入文件,并使用该文件进行流式传输。文件API似乎具有定位到特定位置的能力,因此允许您填充视频为空字节,并在接收到空字节时进行填充。这肯定也适合视频寻找。