Start video at vertical scroll point, then play in reverse - javascript

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>

Related

How to stop white "flash" between javascript video re-loads?

I am building a site with a video background. I have some javascript (shown below) which selects the most appropriate video source based on screen size and bandwidth. It starts by showing a default low-res version and then as soon as the bandwidth has been calculated, the highest quality that is appropriate is set as the new element source. However, this means that when the resolution is "upgraded" on the video.load(); command, the background flashes white. Is there a way of getting a less obtrusive transition, something like the video streaming sites changing resolution mid video.
<div class="video-container">
<video autoplay loop mob-hide id="video">
<source src="Images/Medium.mp4" type="video/mp4" />
Your browser does not support the video tag. I suggest you upgrade your browser.</video>
</div>
JS:
var video = document.getElementById('video');
if (screen.width > 992 && screen.width <= 1200) {
console.log(screen.width);
if (speedMbps > 0 && speedMbps <= 5) {
video.setAttribute("src", "Images/Medium.mp4");
}
if (speedMbps > 5 && speedMbps <= 10) {
video.setAttribute("src", "../Images/Large.mp4");
}
//more options etc.
}
video.load();

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>

Html5 video.currentTime freezes player

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.

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.

HTML5 video height and width through javascript

I'm trying to fetch and print out width and height attributes from video with a simple javascript, but for some reason I'm not managing.
This is the javascript
video = document.getElementsByTagName("video")[1];
span1 = document.getElementById("dimensions");
span1.innerHTML = video.videoWidth + " x " + video.videoHeight;
and this is html5 code which it affects (this is the second video tag in html structure)
<figure>
<video controls>
<source src="video.webm" type="video/webm">
</video>
</figure>
<p>
Dimensions: <span id="dimensions"></span>
</p>
Thanks a lot, I'm a beginner so be light on me.
Your index, based on your markup, won't return you the element you want. The index is zero-based as node lists are array-like and start indexing at 0.
var video = document.getElementsByTagName("video")[0];
Edit: sorry, didn't see you said it was the second video tag. In that case, I'm not certain, because it works for me: http://jsfiddle.net/3wCYz/1/
One thing you might want to try is putting the code you use to get the width and height inside a handler on your video tag that listens for the loadedmetadata event:
video.addEventListener("loadedmetadata", dimensionFunction, false);
where dimensionFunction is a function that does what you're already doing to grab the dimensions.
What this does is make sure the metadata for the video has downloaded before you try to grab it.

Categories

Resources