【发布时间】:2013-10-14 19:56:50
【问题描述】:
我正在观看一个 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 标头),但不幸失败了(我假设是因为视频附带的视频没有元数据)。
在这一点上,我一直在弄清楚 Youtube 是如何做到这一点的。我提出了几个想法,但没有一个完全被我所接受:
1) Youtube 通过每个/videoplayback 呼叫发送自包含的视频和音频块。这在上传方面似乎是一个相当沉重的负担,而且似乎很难将它们拼接在一起以使其看起来像是一个无缝的视频。此外,从调用$('video').duration 和$('video').currentTime 来看,视频标签似乎认为它是一个完整的视频,这让我相信视频标签认为它是一个视频文件。最后,vidoe src 标签永远不会改变,这让我相信它正在处理单个 blob 而不是切换 blob。
2) Youtube 构造一个空的 blob,其大小已预先设置为完整的视频数组,并在下载 blob 时使用片段更新 blob。然后它会确保用户没有离最后下载的片段太近(以防止用户进入 blob 的未下载部分)。我看到的问题是我看不到任何通过 javascript 动态更新 blob 的方法(尽管我可能只是在谷歌搜索时遇到了麻烦)
3) Youtube 下载元数据,然后在下载视频片段时按顺序开始构建 blob。我用这种方法看到的问题是我不明白它如何处理后缓冲区域中的搜索。
也许我只是错过了一个明显的答案,就在我面前。有人有什么想法吗?
编辑:我只是想到了第四个选项。另一个想法是他们可能使用文件 API 将二进制块写入文件并使用该文件流出。文件 API 似乎具有寻找特定位置的能力,因此允许您用空字节填充视频并在收到它们时填充它们。这肯定也会适应视频搜索。
【问题讨论】:
-
我以为他们使用了MediaStream API,但到目前为止我一直懒得去全面调查。请告诉我! =)
-
不同于MediaSource API....
-
有趣的 API,虽然它缺少很多需要的东西(比如开始的方式),除非我读错了。无论哪种方式,我都不在我进行这项研究的公司工作,也不知道我什么时候会回到这种类型的东西:)
-
是的,也许你是对的,但它不兼容。我没有彻底调查。如果你也不愿意,我会把它放在 TODO 上。
-
@KallDrexx 写完这篇文章后你发现什么了吗?