YouTube 的高清视频流服务器技术?
最近我一直在研究将 MP4 流式传输到浏览器的不同方法。 Flash Media Server 是一个明显的选择(使用 Cloudfront),而且我见过的大多数解决方案都使用 RTMP 协议。
然而,我花了一些时间在 YouTube 上使用 Firebug 和 Chrome 调试器弄清楚他们的流媒体是如何工作的,并且我发现了他们的一些视频和质量率之间的一些有趣的差异。
我的两个示例视频是 A 和 B。 A 的分辨率最高可达 480p,B 的分辨率最高可达 1080p。对于这两个视频,所有高达 480p 的速率均通过 HTTP 在包含 H.264 视频和 AAC 音频的 FLV 容器中提供。这里有趣的是,如果您尚未下载(缓存)整个视频,并且尝试跳到视频的未缓存部分,则会发出一个新请求,其“begin”参数等于中的目标偏移量毫秒。 480p 视频 A 的示例:
http://v11.lscache8.c.youtube.com/videoplayback?ip=0.0.0.0&sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor%2Coc%3AU0dWTldQVF9FSkNNNl9PSlhJ&fexp=904806%2C902906%2C903711&algorithm=throttle-factor&itag=35&ipbits=0&burst=40&sver=3&expire=1279756800&key=yt1&signature=D2D704D63C242CF187CAA5B5D5BAFB8DFACAC5FF.39180C01559C976717B651A7EB1D0C6249231EB7&factor=1.25&id=8568eb3135971f6f&begin=111863
Response Headers:
Cache-Control:public,max-age=23472
Connection:close
Content-Length:14320637
Content-Type:video/x-flv
Date:Wed, 21 Jul 2010 17:23:48 GMT
Expires:Wed, 21 Jul 2010 23:55:00 GMT
Last-Modified:Wed, 19 May 2010 12:31:41 GMT
Server:gvs 1.0
X-Content-Type-Options:nosniff
此 URL 返回的文件是完全有效的 FLV,仅包含请求的偏移量之后的视频部分。
我对视频 B 的更高分辨率版本进行了同样的测试。在 720p 和 1080p 下,YouTube 将返回 MP4 容器中的视频,还包含 H.264 视频和 AAC 音频。令我印象深刻的是,他们的服务器对 MP4 视频采用相同类型的偏移量(通过“begin”参数)并返回一个有效的、可流式传输的 MP4(具有正确偏移量的文件前面的 moov 原子),该偏移量也只包括视频的请求部分。
那么,YouTube 是如何做到这一点的呢?他们如何即时生成具有正确标头且仅包含所请求视频的所需片段的 FLV 或 MP4 容器?我知道这可以使用 FFMPEG 来寻找所需的起始点并使用 qt-faststart 脚本将 moov 原子重新定位到流的前面来完成,但这似乎太慢了,无法处理数百万个的点播YouTube 观众。
有想法吗?
提前致谢!
脚注:此时我不允许包含超过 1 个链接,因此这里是视频 A 的 URL:http://www.youtube.com/watch?v=hWjrMTWXH28“视频最高可达 480p”
Lately I've been researching different methods for streaming MP4s to the browser. Flash Media Server is an obvious choice here (using Cloudfront), and most solutions I've seen use the RTMP protocol.
However, I spent some time on YouTube with Firebug and Chrome debugger figuring out how their streaming worked and I discovered some interesting differences between some of their videos and quality rates.
My two sample videos are A and B. A is available up to 480p and B is available up to 1080p. For both videos, all rates up to 480p are served in an FLV container with H.264 video and AAC audio, over HTTP. What's interesting here is that if you have not yet downloaded (cached) the entire video, and you try to skip forward to an uncached part of the video, a new request will be made with a 'begin' parameter equal to the target offset in milliseconds. Example from Video A at 480p:
http://v11.lscache8.c.youtube.com/videoplayback?ip=0.0.0.0&sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor%2Coc%3AU0dWTldQVF9FSkNNNl9PSlhJ&fexp=904806%2C902906%2C903711&algorithm=throttle-factor&itag=35&ipbits=0&burst=40&sver=3&expire=1279756800&key=yt1&signature=D2D704D63C242CF187CAA5B5D5BAFB8DFACAC5FF.39180C01559C976717B651A7EB1D0C6249231EB7&factor=1.25&id=8568eb3135971f6f&begin=111863
Response Headers:
Cache-Control:public,max-age=23472
Connection:close
Content-Length:14320637
Content-Type:video/x-flv
Date:Wed, 21 Jul 2010 17:23:48 GMT
Expires:Wed, 21 Jul 2010 23:55:00 GMT
Last-Modified:Wed, 19 May 2010 12:31:41 GMT
Server:gvs 1.0
X-Content-Type-Options:nosniff
The file returned by this URL is a fully valid FLV containing only the portion of the video after the requested offset.
I did the same kind of test on the higher resolution versions of Video B. At 720p and 1080p, YouTube will return a video in an MP4 container, also with H.264 video and AAC audio. What's impressive to me is that their server takes the same type of offset for an MP4 video (via the 'begin' parameter) and returns a valid, streamable MP4 (moov atom at the front of the file with correct offsets) that also only includes the requested portion of the video.
So, how does YouTube do this? How do they generate the FLV or MP4 container on the fly with the correct headers and only the desired segment of the requested video? I know this can be accomplished using FFMPEG to seek to the desired start point and the qt-faststart script to reposition the moov atom to the front of the stream, but it seems like this would be too slow to handle on-demand for millions of YouTube viewers.
Ideas?
Thanks in advance!
Footnote: I am not allowed to include more than 1 link at this point, so here is Video A's URL: http:// www.youtube .com/watch?v=hWjrMTWXH28 "Video available up to 480p"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在这个论坛上也有人提出了类似的问题。
http://www.flashforum.de/forum /video/flv-ab-beliebiger-position-streamen-248483.html
有两种可用的解决方案:
在这两种解决方案中,您都需要使用 flvmid 修改所有视频,以将关键帧信息添加到 flv 视频中。
在第二个解决方案中,您的 php 脚本接收上面发布的请求并解析 flv-video,直到它到达参数 begin 指定的位置。之后,它开始将视频内容推送给页面访问者。
阅读该主题以获取更多信息和 php 代码示例。
原始帖子是用德语编写的,但您可以使用 http://translate.google.com 来获得糟糕的英语:)
您发布的 HTTP 响应包含以下行:
也许gvs 意味着类似“Google 视频服务器”的内容。我搜索了gvs,但找不到任何有价值的东西。
A simular question has been asked at this forum.
http://www.flashforum.de/forum/video/flv-ab-beliebiger-position-streamen-248483.html
There are two solutions avaiable:
In both solutions you need to modify all your videos f.e. using flvmid to add the key-frame-informations to the flv-video.
In the second solution you php-script recives the request you've posted above and parses the flv-video until it reaches the position given by the parameter begin. After that it starts to push the video-content to the page-visitor.
Read the thread to get more informations and a php-code-examples.
The original thread is written in german but you can use http://translate.google.com to get a bad english :)
The HTTP-Response you've posted contains the following line:
Maybe gvs means something like "Google Video Server". I've searched for gvs but I could not find anything of value.
查看 NGINX 服务器,它有专门执行此操作的模块。作者对 FLV 和 MP4 容器进行了所有解析和重写,以按照所需的确切偏移量进行输出。流媒体部分不需要 ffmpeg,因为它太过分了。
Have a look in to the NGINX server, it has modules to do exactly this. The author did all the parsing and rewriting of the FLV and MP4 containers to output on the exact required offset. No need for ffmpeg at the streaming part as it would be overkill.
Youtube 使用lighttpd 服务器进行流媒体播放。它实际上使用伪流而不是流。这种机制允许观看者寻找视频中尚未下载的部分
Youtube uses lighttpd server for streaming. It actually uses pseudo streaming not streaming. This mechanism allows viewers to seek to not-yet downloaded parts of a video
我不认为 YouTube 使用 FFMPEG 进行流媒体播放。容器格式,无论是 flv 还是 mp4,都很简单,并且计算量不大。重要的是找到距指定
begin
时间戳最近的关键帧并从它开始。I don't think YouTube use FFMPEG for its streaming. Container format, either flv or mp4, is simple enough and is not computation intensive. It's important only to find the nearest key-frame to specified
begin
timestamp and to start from it.