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
Related
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.
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.
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.
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.
I'm working on a site for a client and they're insistent on using HTML5's video tag as the delivery method for some of their video content. I currently have it up and running with a little help from http://videojs.com/ to handle the Internet Explorer Flash fallback.
One thing they've asked me to do is, after the videos finish playing (they're all a different length), fade them out and then fade a picture in place of the video --- think of it like a poster frame after the video.
Is this even possible? Can you get the timecode of a currently playing movie via Javascript or some other method? I know Flowplayer (http://flowplayer.org/demos/scripting/grow.html) has an onFinish function, is that the route I should take in lieu of the HTML5 video method? Does the fact that IE users will be getting a Flash player require two separate solutions?
Any input would be greatly appreciated. I'm currently using jQuery on the site, so I'd like to keep the solution in that realm if at all possible. Thanks!
You can view a complete list of events in the spec here.
For example:
$("video").bind("ended", function() {
alert("I'm done!");
});
You can bind to the event on the element like anything else in jQuery...as for your comment question, whatever element you're delivering for IE, yes, it would need a separate handler rigged up to whatever event it provides.
For the other question about timecode, the timeupdate event occurs when it's playing, and the durationchange event occurs when the overall duration changes. You can bind to and use them just like I showed with the ended event above. With timeupdate you'll probably want the currentTime property, with durationchange you'll want the duration property, each of which you get directly off the DOM object, like this:
$("video").bind("durationchange", function() {
alert("Current duration is: " + this.duration);
});
There is an OnEnded event associated with the video tag. However, it does not work for me in the current version of Google Chrome.
HTML 5 Video OnEnded Event not Firing
and see also
Detect when an HTML5 video finishes
For a general-purpose solution (supports video tag with fallback see)
http://camendesign.com/code/video_for_everybody
or
http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library or http://www.mediafront.org/
I used this code. It basically reloads the video which will get the poster to show again. Assuming you want the image at the end to be the same as the poster. I only have one video on the page so using the video tag works. I have my video set to autoplay on page load so I added the pause after the reload.
<script type="text/javascript">
var video= $('video')[0];
var videoJ= $('video');
videoJ.on('ended',function(){
video.load();
video.pause();
});
</script>