I have an undetermined amount of very short videos that I would like to loop through.
I have the following HTML:
<video class="bgvid bgvid--0 bgvid--visible" poster="<?= URL ;?>img/vidframe.jpg" src="1920x800.webm" playsinline muted></video>
<video class="bgvid bgvid--1 bgvid--hidden" poster="<?= URL ;?>img/vidframe.jpg" src="1920x800.2.webm" playsinline muted></video>
<video class="bgvid bgvid--2 bgvid--hidden" poster="<?= URL ;?>img/vidframe.jpg" src="1920x800.2.webm" playsinline muted></video>
In my CSS I show the one video with class bgvid--visible, and hide all others with class bgvid--hidden as follows:
.bgvid--hidden { opacity: 0; }
.bgvid--visible { opacity: 1; }
In my JS I start playback of my initial video by doing the following:
$('.bgvid--0').get(0).play();
Then after 5 seconds using CSS transitions and by switching the bgvid--visible and bgvid--hidden classes I "fade out" the current "active" video, and start playback and "fade in" the following video as follows:
setTimeout(function(){
$('.bgvid--0').removeClass('bgvid--visible').addClass('bgvid--hidden');
}, 5000);
setTimeout(function(){
$('.bgvid--1').get(0).play();
$('.bgvid--1').removeClass('bgvid--hidden').addClass('bgvid--visible');
}, 4500);
Notice the second timeout being slightly shorter than the first in order to create the impression of a seamless transition by fading in the next video prior to fading out the active one.
I have read about "ended" events, but the transition has to start before the video has ended. How can I turn this into a loop of some kind that loops this way through an undetermined amount of videos?
You can get the length of your video using videoElement.duration, and the current time with videoElement.currentTime.
You can use the HTML Audio/Video timeupdate event to monitor if the current time reached the last 5 seconds, and then start the transition to the next video.
videoElement.ontimeupdate = function() {
if (videoElement.currentTime >= videoElement.duration - 5) {
startTransition();
}
};
You could use only the duration, and simply set your timeout accordingly, but nothing guarantees that a 30 seconds video will really end 30 seconds later. It can be paused, or it can buffer for some time. But this method will tell you when the video is really 5 seconds from the end.
Related
I am trying to make a playlist using the HTML5 <video> tag and the onended trigger.
The playlist works, videos get played one after another, but the problem is that there is a minor gap between 2 videos played.
Its not a seamless continuous play. What can I do to fix this problem?
Here is my code:
<video id="vd" style=" width: 480px; height: 360px; " autoplay controls
src="vid/0006v.mp4" />
<script type="text/javascript">
var vf=[ "0006v", "0007v", "0008v", "0009v", "0010v" ];
var c=0;
v=document.getElementById("vd");
v.onended=function()
{
++c;
if( c >= vf.length ){ c=0; }
v.src= "vid/"+ vf[c]+ ".mp4";
};
</script>
Below is the player demo.
Each video is of 1 minute duration, about 5 loaded in the playlist.
The gap appears when video number one ends after 1 minute and second video starts, and so on...
http://13pp.co.uk/play.php
This happens because the next video only starts downloading when the previous video ends. Here's my solution:
Have two <video> elements, one visible and one hidden. Set the src attribute of the first to the first video URL. When the first <video> element is almost done playing, set the src attribute of the second to the second video and call video2.load(), but don't start playing right away. When the first <video> element is done playing, make the first invisible, make the second visible and start playing the second. Then use the first to play the third video, the second to play the fourth, etc...
So the HTML5 video has no controls. Basically I want to show a loading gif that shows over the video only when the video is loading (buffering and paused)
<video id="myvideo" width="100%"><source src="video/Good.mp4" type="video/mp4"><source src="movie.html" type="video/ogg"></video>
How about using the built-in browser animation instead of a gif.
All you have to do is set the controls to TRUE and then back to FALSE depending on the buffering state.
The best practice for me looks like this,
<video src="myVideo.fileExtension" onplaying="hideControls(this)" onwaiting="showControls(this)" preload="auto" poster="myAnimatedWebpOrGifThatSaysVideoIsNotYetReady.fileExtension">No video support?</video>
<script type="text/javascript">
//We hide the video control buttons and the playhead when the video is playing and enjoyed by the viewer
function hideControls(event){ event.controls=false; }
//If the video has to pause and wait for data from the server we let controls be seen if the user hovers or taps on the video. As a bonus this also makes the built-in loading animation of the browser appear e.g. the rotating circular shape and we give it a little delay (like 1 sec) because I would say it looks and feels better.
function showControls(event){ setTimeout(function(){ event.controls=true; },1000); }
</script>
Maybe you could use ontimeupdate instead of onplaying which would fire continuously.
As for the delay time actually not 1 but 4 seconds -to me- is the best.
I need some code or login using which I can solve my issue.
I can design HTML5 video player but issue is plying second Ad video. What I need is:
User will click on any video from listing. HTML5 video player will start playing it. When user will reach at middle of the video, That first video will be pause and Second Ad video will start playing. And once ad video will be completed, Player will keep continue with first video.
It must work with safari.
You can catch the middle of the video by currentTime and duration of HTML property.
And you can pause video by pause function and play ad video by using another video DOM.
var delta = 0.05;
setInterval(function(){
if(video.currentTime >= video.duration*(0.5-delta)
&& video.currentTime <= video.duration*(0.5+delta)) {
video.pause(); //pause current video
//play ad and resume video when ad end
}
}, 1000);
I'm trying to achieve something with html5 video and haven't been able to find an answer elsewhere. Is it possible? Any help is much appreciated.
Here's the html:
<video autoplay="autoplay" poster="http://dummyimage.com/320x240/ffffff/fff">
<source src="videos/ship.mp4" type="video/mp4" />
</video>
I want to:
- on page load, display the video paused on the first frame (use poster?)
- at vertical scroll of X pixels, play the video once through (alternatively, inject it onto the page at X scroll?)
- then, when I scroll back beyond the X pixels value play the video again in reverse once through (does this work aMediaElement.playbackRate = -1; ?)
sadly the simplest solution playbackRate = -1 doesn't seem to be implemented anywhere yet.
you could fake it with some code like below to jump the currentTime back at whatever rate you need but from playing around it doesn't look very smooth.
my suggestion would be - if practical - to actually encode a a reversed version of the video if being able to play it backwards is the goal and then swap the source or toggle the visible <video> tag
Oh, and as usual... any video you're planning to stream on the web make sure you optimize and get the moov atom in the right place (see sample ffmpeg)
<script>
var intervalRewind = 0;
var v = document.getElementById("v")
function rewind() {
intervalRewind = setInterval(
function(){
v.playbackRate = 1.0;
if(v.currentTime == 0){
clearInterval(intervalRewind);
v.pause();
} else {
v.currentTime += -.1;
}
},30);
}
</script>
...
<video id="v" onclick="clearInterval(intervalRewind)" width="320" height="240" controls="controls">
<source type="video/mp4" src="video-fs.mp4" />
</video>
<button onclick="rewind()">Rewind</button>
This question already has an answer here:
Event for every frame of HTML Video?
(1 answer)
Closed 24 days ago.
I need detect all frames changes of a video in HTML 5, i tried the follow code, but i can't get all changes, only i can get eight or nine updates per second..
<body>
<canvas id="Canvas" width="800" height="450" style="position:absolute; left:5; top:5">Can't Load Canvas</canvas>
<video id="videoPlay" muted controls>
<source src="assets/soccer.webm" type="video/webm">
<source src="assets/soccer.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
<script type="text/javascript">
videoPlay.addEventListener('timeupdate', function (){
putOverlay();
});
function putOverlay(){
console.log(videoPlay.currentTime);
console.log("another frame");
}
</script>
</html>
I tried the following code too, but with a timer there is a loss of synchronization between the frame and the value given by the timer, over time..
<body>
<canvas id="LeCanvas" width="800" height="450" style="position:absolute; left:5; top:5">Can't Load Canvas</canvas>
<!-- Video -->
<video id="videoPlay" controls>
<source src="assets/soccer.webm" type="video/webm">
<source src="assets/soccer.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
<!-- Play Video-->
<script>
//Play Damn Video
var videoPlay = $('#videoPlay')[0];
videoPlay.play(1);
</script>
<!-- Canvas Animation -->
<script>
//Animation
function animate() {
console.log("frame change");
}
setInterval(animate, 1000/29.97);
</script>
Any suggestions for my problem?
Sorry my english
regards
Alex
As noted in the comments above, timeupdate only fires every 15-250ms, and in practice it appears to be closer to 250ms. It seems as though timeupdate was designed to provide enough accuracy to display the currentTime every second. So your best option is to run a timer that runs at the rate you want and query currentTime on every iteration.
But rather than use setInterval or even setTimeout, you should be using requestAnimationFrame. This will run approximately every 16ms (60fps), but it will be synchronized with the video card refresh rate. If you use setTimeout, you may see flicker or screen tearing on certain devices, especially mobile ones. It also allows the browser to throttle your frame rate when the tab is not visible to save on CPU cycles (and therefore battery usage).
It's also better than setInterval because, if for some reason your render code takes longer than the 30 or 16ms you've allotted, setInterval may pile up calls and cause timing problems, but requestAnimationFrame will skip frames to get you back on track.
Assuming you've used the polyfill as above, the code would look something like this:
var video = document.getElementById('videoPlay'),
lastTime = -1;
function draw() {
var time = video.currentTime;
if (time !== lastTime) {
console.log('time: ' + time);
//todo: do your rendering here
lastTime = time;
}
//wait approximately 16ms and run again
requestAnimationFrame(draw);
}
draw();
The above code has a check on time to make sure you don't draw the same frame twice in a row. You don't really need that, but it will save you a few CPU cycles. But when drawing a video to canvas, the frame is a couple of milliseconds behind what's reported by currentTime. So if you pause the video and then skip around, you will almost definitely be one frame behind. Usually, if the currentTime hasn't changed since my last draw but the video is paused, I'll keep drawing every cycle for another half second or so. Or you could just take the time check out.