I have tried several methods:
I tried to create hidden video tags and show/hide them, but this will cause flickering.
I tried to change the src attribute of the video, but I have to call load() method before play(), and the load() will load the new video.
This is not what I want either, because this causes the new video to stop for a while (because need time to load).
I tried to cache the new video by using ajax to load the new video in background before the previous video is finished. The new video can be downloaded pletely (300Kbytes) before the old video is finished.
But when I call .load() function on the new video, it will be downloaded again.
My question is: for my third method, is there a way for the video object to make use of the downloaded file in cache?
After reading around, I think the above three are probably the only ways to realize my objective. The third one is really what I want but the video file just got downloaded twice (once is Ajax download, and another is calling load()). Note that, without calling load(), just simply changing the src attribute and calling play() will not work.
I have tried several methods:
I tried to create hidden video tags and show/hide them, but this will cause flickering.
I tried to change the src attribute of the video, but I have to call load() method before play(), and the load() will load the new video.
This is not what I want either, because this causes the new video to stop for a while (because need time to load).
I tried to cache the new video by using ajax to load the new video in background before the previous video is finished. The new video can be downloaded pletely (300Kbytes) before the old video is finished.
But when I call .load() function on the new video, it will be downloaded again.
My question is: for my third method, is there a way for the video object to make use of the downloaded file in cache?
After reading around, I think the above three are probably the only ways to realize my objective. The third one is really what I want but the video file just got downloaded twice (once is Ajax download, and another is calling load()). Note that, without calling load(), just simply changing the src attribute and calling play() will not work.
Media Source Extensions are what you need. It's hard to find good documentation on them yet (at the time of writing, MDN's documentation is mostly stubs), but you can delve into the spec if you dare.
The two-sentence summary is that with Media Source Extensions you can create a MediaSource
object and set it as the source of a <video>
element, instead of pointing the <video>
at the URL of a plete video. Then you can use JavaScript to explicitly download videos representing further segments of your live stream and append them to your MediaSource
object, and the segments will play seamlessly.
Also, while it's slightly beyond the scope of what you've asked here, MPEG-DASH is a technique for doing exactly what you're interested in (i.e. streaming live video by encoding short segments as individual files, such as short standalone mp4s, and serving these segments individually to the browser). There's no way to implement MPEG-DASH in a browser without Media Source Extensions, so they are often discussed together. There are some good writeups (at different levels of detail) on building a DASH player with HTML and JavaScript using Media Source Extensions on the BBC's tech blog and MSDN.
Unfortunately, Media Source Extensions are not yet available in all major browsers. For instance, the latest version of Firefox on my Mac doesn't have window.MediaSource
. This means you can't do segmented live streaming in a way that will work on all major browsers using only a HTML 5 <video>
element yet. Unfortunately, it's still necessary to fall back to Flash if you need cross-browser patibility.
Like you, I tried to implement this behaviour without using Media Source Extensions. I tried (and tried bining) a whole bunch of techniques, including swapping out URLs on <video>
elements, unhiding and playing <video>
elements, downloading segments fully in advance and storing them in Blobs that I'd use as the src
for my <video>
elements, and setting the preload
attribute to auto
to load the segments into memory in advance... but nothing worked. In Google Chrome, using any of these techniques results in a visible stutter when you play()
the second video from the first video's ended
event, even if you've loaded the second video fully in advance. There just isn't a way to get seamless consecutive video playback using <video>
elements without some kind of stutter in browsers that don't support Media Source Extensions.