Youtube 的 HTML5 视频播放器如何控制缓冲?

Posted

技术标签:

【中文标题】Youtube 的 HTML5 视频播放器如何控制缓冲?【英文标题】:How does Youtube's HTML5 video player control buffering? 【发布时间】: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 写完这篇文章后你发现什么了吗? 【参考方案1】:

当您查看 GoogleChrome 的 AppData 时,在播放 youtube 视频时,您会看到它缓冲在分段文件中。上传到 youtube 的视频是分段的,这就是为什么如果该时间段在当前段之外,您无法在第一次点击栏时完美地确定时间段。

片段的数量取决于视频的长度,以及您开始和停止播放视频的时间。

当您链接到视频的时间范围时,它只会跳过该时间范围之前的片段的缓冲。

很遗憾,我对视频播放的编码知之甚少,但我希望这能为您指明正确的方向。

【讨论】:

有趣的是,我确实看到大量文件被添加到我的 AppData\Local\Google\Chrome\User Data\Default\Cache 目录中,从网络流量来看,1.1MB 的文件是视频块。现在的问题仍然是他们如何将它们缝合在一起。谢谢:)【参考方案2】:

好的,您只需要知道 YouTube 是基于这个伟大的开源 Project。每个浏览器的行为都不同,如果您的浏览器支持更密集的解码(如 WEBM),它将使用它来节省 Google 的带宽。另外,如果您查看此Demo 然后你会发现一个部分将整个视频下载到一个叫做“离线存储”的东西中。我知道 chrome 拥有它,而其他一些浏览器并非在某些情况下都必须使用整个视频源而不是 blob。因此,该 blob 正在流式传输,具体取决于用户与视频的交互。是的,视频只是 1 个文件,他们有该视频的元数据,就像一个小数据库,告诉视频的时间和可以划分块的点。

您可以通过阅读项目的文档了解更多信息。我真的建议你看看演示。

【讨论】:

【参考方案3】:

页面中有一个画布元素,也许这会有所帮助 http://html5doctor.com/video-canvas-magic/

我们知道视频是分段的,问题是如何将它们拼接在一起。我认为真正的视频元素不做播放工作,它支持数据源,并将每一帧的分段绘制到画布元素。

var v = document.getElementById('v'); 
var canvas = document.getElementById('c');
v.addEventListener('play', function() 
   if(v.paused || v.ended) return false; 
   c.drawImage(v,0,0,w,h); 
   setTimeout(draw,20,v,c,w,h); 
,false);

【讨论】:

请进一步解释您的答案(也许通过从您提供的链接中添加一些信息)。不鼓励仅提供链接的答案。 对不起,我的英语很差。我们知道视频是分段的,问题是如何将它们拼接在一起。我认为真正的视频元素不做播放工作,它支持数据源,并将每一帧的分段绘制到画布元素...【参考方案4】:

Youtube 仅在支持媒体源扩展的浏览器中使用此功能,因此由浏览器决定是否使用此功能。

【讨论】:

以上是关于Youtube 的 HTML5 视频播放器如何控制缓冲?的主要内容,如果未能解决你的问题,请参考以下文章

youtube 如何防止从其 HTML5 播放器下载视频?

如何通过 HTML5 视频标签播放 YouTube 视频

如何使用 HTML 5 仅播放 Youtube 视频的音频?

video.js 视频播放器是不是支持 youtube 视频?

html5媒体播放器播放youtube视频

HTML Youtube HTML5视频播放器标记