Smooth transition between different html5 videos - javascript

I have a list of video tags which I need to play one by one with preset currentTime. When I load the page the readyState of videos get stuck at 1 and the video gives a starting glitch. I have used preload attribute still the video takes time to start playing on every switch. Even if some of the videos have currentTime set and readyState = 4 it takes time to play the video. I looked into xhr createObjectURL blob method but that takes too long for all the videos to get downloaded. For the same reason I did not try MediaSource API.

The media source extension (MSE) does not require you to download the whole video before you play it.
It allows you request a video segment by segment and manipulate the segments any way you want before you set them as the source for the video player.
There is a good overview along with some sample javascript which I think helps to understand the approach here: https://www.html5rocks.com/en/tutorials/eme/basics/
and you can see a simple working example here: https://github.com/bitmovin/mse-demo/blob/master/index.html
The general approach is:
create a MediaSource object
Set the source of the video element in your HTML page to the MediaSource object
Add a listener for the MediaSource being opened (when the video is played)
get the first segment and add a listener to request the next segment
as segments are received append them to the MediaSource buffer
when there are no more segments to be requested stop
In your case you can immediately start to request the next video when you get to the end of the first.
One other thing twitch for - mp4 videos often have their metadata at the end which means you need to download the entire video to start. You can move the metadata to the start using special tools or simply make sure you put it there in the first place if you are doing the transcoding yourself. ffmpeg supports moving the data with the command line option '-movflags faststart', for example.

Related

Forcing playback with short HTML5 videos in Safari

I've been running into issues with Safari and the <video> element in combination with shorter high-quality videos. For a showcase website I'm loading 12-15 second .mp4 and .webm files into a <video> container using the <source> element. When trying to play the video in Chrome it works flawlessly and the video start playing almost instantaneously, but Safari appears to want to load the video completely before starting playback.
I have looked into loading the video directly through the src attribute of <video> and have also added the preload="auto" attribute in an attempt to force immediate playback.
I've set up an example using one of the videos we use on the websites, which is around 8 MB and 12 seconds long: https://jsfiddle.net/n1eac46v/
var video = document.getElementById('video');
var source = document.createElement('source');
source.src = "foo.mp4";
source.type = "video/mp4";
video.appendChild(source);
video.on("canplay canplaythrough", video.play);
As you can see I'm also listening for the canplay and the canplaythrough events, but even that doesn't appear to help. I've been looking all over the place for days on end but am running out of options now.
I am not an OS X user so I have no experience with Safari, however I've had the chance to debug mp4 playback in Chrome. Chrome has a buffering window that it tries to fill until it begins actual playback. Safari may have a bigger window. Also since in normal cases all the tables that contain sample positions, durations etc. are at the end of the file browser may want to read them to begin playback. A smart browser can dispatch a read with a byte range header to get only the end of the file and then seek the actual video data, but again I have no idea what safari does.
What you can try is to use MP4Box on your video files to move the meta data and all tables to the beginning, that could help.
As mentioned by OP in the comments using FFmpeg with -movflags faststart (see FFmpeg MP4 options) can also be used to achieve this.

How to increase audio loading speed using JavaScript?

I have created code for playing an .mp3 file using JavaScript. But the file is taking to much time to play on Android. I want to play the sound quickly after click on a text image. How do I increase loading speed on Android?
My JavaScript code:
if(window.audio)
{
audio.pause();
}
window.audio = new Audio (audio_path);
window.audio.play();
Check demo here -
http://97.74.195.122/gizmo-demo/canvasslidertwo.php
In the above link, click on the Japanese word for playing sound.
You are actually facing the bug depicted in this question. Which makes chrome browsers redownload the files from an Audio Element each time you change its src property (no-caching).
One solution would be to use the WebAudioAPIand store your audio files in the buffer. Doing so, you should be able to call them with no latency.
You can check the accepted answer for an example on how to deal with it.
Or you could also try not to call a new Audio() on each click, and rather load every audios from your page and only call their play() method on click.
But I'm not sure it would fix your issue.

Seamlessly play video files in sequence with HTML <video>

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 completely (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 complete 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 compatibility.
Like you, I tried to implement this behaviour without using Media Source Extensions. I tried (and tried combining) 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.

MediaSource API - reloading MP4 video being recorded

I have a MP4/H264 video clip which is being captured so that it grows every 4 seconds and its metadata is dynamically refreshed. Since this is not fragmented MP4 I cannot use MediaSource API to manipulate chunks.
I'm looking for a way to update/refresh the duration of the video during playback without the need to reload the whole clip.
In short words I'm looking for a way to do the following in more user-friendly way.
setInterval(function() {
video.src = video.src;
}, 4000);
I'd like to avoid having 2 video tags and switching from one to another with the method above. I have also tried with popcorn.js without any luck.
Using Chrome, and... only chrome so not worried about other browsers.
Any advice would be greatly appreciated!
I am not sure that is possible. As per specs:
If a src attribute of a media element is set or changed, the user agent must invoke the media element's media element load algorithm. (Removing the src attribute does not do this, even if there are source elements present.)
So if you touch the video.src the browser should invoke implicitly video.load(). In your case (setInterval) Chrome does this.
I guess you already went the route of saving the currentTime of the video before changing the src and applying it after the src change (wait for the canplay event in this case and call video.play() to resume playing)? I guess you would have some stuttering for 4 seconds refresh in your case.
It seems that you are trying to emulate a live stream as an on demand feed and I do not know a way to do this with progressive download of mp4 (read with un-fragmented MP4).
Related article.
Thanks

Reusing an HTML5 Audio object for repeated playing of the same mp3 sound effect

In a simple HTML5/WebGL app, I want to play a sound effect occasionally.
Currently I have in a constructor:
this.audio = new Audio('audio/zeep.mp3');
Then later, I want to play the file:
this.audio.play();
It works the first time, but second plays fail. I've tried resetting the currentTime to zero, and also to 0.1. Neither work:
this.audio.currentTime = 0;
this.audio.play();
If I recreate the Audio object with each time I want to play it, Chrome's network tab shows that it's going across the wire to re-fetch the file, rather than serving it from the cache.
Note that I don't need the same sound effect to play multiple times concurrently. This sound will be infrequent.
Am I missing something here?
audio element Can't play again.
the http header of the audio file need to have Content-Range like:
Content-Range:bytes 0-5151/5152
it's designed for seeking.
and one audio element can NOT be playing concurrently, if need concurrency.use:
var copy = audio.cloneNode();
copy.play();

Categories