How does Youtube's HTML5 video player control buffering?

HtmlVideoYoutube

Html Problem Overview


I was watching a youtube video and I decided to investigate some parts of its video player. I noticed that unlike most HTML5 video I have seen, Youtube's video player does not do a normal video source and instead utilizes a blob url as the source.

Previously I have tested HTML5 videos and I found that the server starts streaming the whole video from the start and buffers in the background the complete rest of the video. This means that if your video is 300 megs, all 300 megs will be downloaded. If you seek to the middle, it will start downloading from the seek position all the way to the end.

Youtube does not work this way (at least in chrome). Instead it manages to control buffering so it only buffers a certain amount while paused. It also seems to only buffer the relevant pieces, so if you skip around it will make sure not to buffer pieces that are unlikely to be watched.

In my attempts to investigate how this worked, I noticed the video src tag has a value of blob:http%3A//www.youtube.com/ee625eee-2802-49b2-a13f-eb374d551d54, which pointed me to https://developer.mozilla.org/en-US/docs/Web/API/Blob">blobs</a>;, which then led me to https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data">typed arrays. Using those two resources I am able to load a mp4 video into a blob and display it in a HTML5 video tag.

However, what I am now stuck on is how Youtube deals with the pieces. Looking at the network traffic it appears to sends requests to http://r6---sn-p5q7ynee.c.youtube.com/videoplayback which returns binary video data back in chunks of 1.1mb. It also seems worth noting that most normal requests due to HTML5 video requests seem to receive a 206 response code back while it streams, yet youtube's playvideo calls get a 200 back.

I tried to attempt to only load a range of bytes (via setting the Range http header) which unfortunately failed (I'm assuming because there was no meta-data for the video coming with the video).

At this point I'm stuck on figuring out how Youtube accomplishes this. I came up with several ideas though none of which I am completely sold on:

  1. Youtube is sending down self contained video and audio chunks with each /videoplayback call. This seems like a pretty heavy burden on the upload side and it seems like it would be difficult to stitch these together to make it appear like it's one seemless video. Also, the video tag seems to think it's one full video, judging from calling $('video').duration and $('video').currentTime, which leads me to believe that the video tag thinks it's a single video file. Finally, the vidoe src tag never changes which makes me believe it is working with a singular blob and not switching out blobs.

  2. Youtube constructs an empty blob pre-sized to the full video array and updates the blob with pieces as it downloads it. It would then make sure the user has not gotten too close to the last downloaded piece (to prevent the user from entering an undownloaded section of the blob). The problem that I see with this that I don't see any way to dynamically update a blob through javascript (although maybe I'm just having trouble googling for it)

  3. Youtube downloads the meta data and then starts constructing the blob in order by appending the video pieces as it downloads them. The problem I see with this method is I don't understand how it would handle seeks in post-buffered territory.

Maybe I"m just missing an obvious answer that's right in front of me. Anyone have any ideas?


edit: I just thought of a fourth option. Another idea is they might use the file API to write the binary chunks to a file and use that file to stream off of. The file API seems to have the ability to seek to specific positions, therefore allowing you to fill a video with empty bytes and fill them in as they are received. This would definitely accommodate video seeking as well.

Html Solutions


Solution 1 - Html

When you look at the AppData of GoogleChrome, while playing a youtube video, you will see that it buffers in segmented files. The videos uploaded to youtube are segmented, which is why you can't perfectly pinpoint a timeframe in the first click on the bar if that timeframe is outside of the current segment.

The amount of segments depends on the length of the video, and the time from which you start and stop playing back the video.

When you are linked to a timeframe of a video, it will simply skip the buffering of the segments that come before that timeframe.

Unfortunately I don't know much about the coding for video playback, but I hope this points you in the right direction.

Solution 2 - Html

there is a canvas element in the page ,Maybe This Will Help http://html5doctor.com/video-canvas-magic/

we knew the video is been segmented,the question is how to stitch them together.i think the real video element doesn't do the play work,it support the datasource,and draw the seagments each frame to the canvas element。

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);

Solution 3 - Html

Okay, so few things you need to know is that YouTube is based on this great open source [Project][1]. It behaves different for every browser and if your browser supports more intensive decoding like WEBM it will use that to save Google's bandwidth. Also if you look at this [Demo][2] Then you will find a section which downloads the entire video into a thing called "offline storage". I know chrome has it and some other browsers not every in some cases they do have to use the entire video source instead of a blob. So that blob is streaming depending on the user interaction with the video. Yes the video is just 1 file and they have metadata for that video like a little database that tells the time of the video and the points at which chunks can be divided in.

You can find out more by reading the Project's documentation. I really recommend you have a look at the demo.

[1]: https://github.com/google/shaka-player "Project" [2]: http://shaka-player-demo.appspot.com/demo/ "Demo"

Solution 4 - Html

Youtube is using this feature only in browsers that support Media Source Extensions so it is up to the browser decide about all the rest because of this feature.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKallDrexxView Question on Stackoverflow
Solution 1 - HtmlMilanSxDView Answer on Stackoverflow
Solution 2 - HtmlvetchView Answer on Stackoverflow
Solution 3 - HtmlGot To FigureView Answer on Stackoverflow
Solution 4 - HtmlAlbi PatoziView Answer on Stackoverflow