Html5 video.currentTime freezes player - javascript

I am trying to skip a video ahead, using currentTime.
I set my video up like this:
<style>
#video-player {
display:inline-block;
width:500px;
height:358px;
margin-left:20px;
}
</style>
<video id="video-player" controls autoplay>
<source src="messi.mp4" type="video/mp4">
</video>
Later on, I have a click event set up on a button.
var video = document.getElementById('video-player');
video.currentTime = parseInt(video.currentTime) - 2;
All I want that button to do is to move the video back 2 seconds in time.
But when I click, it either moves the video to the beginning to freezes it up.

So this is very strange, but the issue went away when I tested my code on a live url.
I was testing using a local Python web server where I encountered the problem. Hope this helps someone.

Related

Showing HTML5 Video with a loading GIF image if the video is loading (buffering)

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.

which is more performant, <video> or <canvas> with video embed?

I am developing a page with a full width / full height intro video (100vw / 100vh), looks "full screen" until you scroll down.
Currently I am using HTML5 <video> to accomplish this, but I've noticed the page can get a little choppy, particularly while scrolling. The video is about 4mb.
Would I see an increase in performance if I were to replace the <video> with a <canvas>, and load the video frames directly through the canvas object instead? both elements are GPU accelerated so I'd figure it shouldn't make a difference, but I'm not sure.
No, all the cost of decoding a video frame is still there. Using a canvas would in addition to that add more cost, not less.
If the video is without sound you could temporary pause the video while scrolling, as well as pause it permanently when out of view:
var vt;
window.onscroll = function() {
video.pause(); // pause video
clearTimeout(vt); // clear timer
vt = setTimeout(function() { // create a new timer
var r = video.getBoudingClientRect(); // abs. bound
if (window.scrollY < r.height) video.play(); // assumes video is in top
}, 70); // 70ms
...
};
Another key, although not of very much difference, is to make sure the video code is easy to decode. You can achieve this by removing noise, use flat colors and large surfaces, good lighting conditions, low depth-of-field to blur background as well as lower contrast and avoid too many details in the main subject(s) (this will also produce smaller files).
var video = document.querySelector("video"),
vt;
window.onscroll = function() {
video.pause();
clearTimeout(vt);
vt = setTimeout(function() {
var r = video.getBoundingClientRect();
if (window.scrollY < r.height) video.play();
}, 70);
};
html, body {width:100%; height: 2000px}
video {
width:100%;
height:auto;
}
<video muted width="500" height="280" autoplay="true">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm" type="video/webm">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv" type="video/ogg">
</video>

Start video at vertical scroll point, then play in reverse

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>

Touch Events stop working on iPad after the Video tag

I have an application that lets you swipe left and right to view different screens, or alternatively click on the Next and Previous buttons to navigate.
if(isMobile){
detectSwipe = true;
document.addEventListener('touchstart',TouchStart,false);
document.addEventListener('touchmove',TouchMove,false);
document.addEventListener('touchend',TouchEnd,false);
document.addEventListener('touchend',TouchCancel,false);
}
$("#prevBtn").on('touchstart click', function () {
...
}
The problem is for some unknown reason when it reaches a screen with a video tag all buttons become unclickable and only the swipe events are still active. This only happens on the iPad however, on the desktop it works fine.
<video width="960" height="560">
<source src="video.mp4" type="video/mp4"/>
<source src="video.ogg" type="video/ogg"/>
<source src="video.webm" type="video/webm"/>
Your browser does not support the video tag.
</video>
I've also tried to use a embed youtube video instead of the video tag, but the problem persists.
You have to set the video element's controls to false and set your own controls, for it to work.

Get frame change in video HTML5 [duplicate]

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.

Categories

Resources