Get dimensions of HTML5 video (playing region - not division) during playback - javascript

I have a HTML video in a division. When the user changes the size of the HTML window the playing area of the video changes to maintain its aspect ratio leaving boarders around the video (depending on how the window is resized).
Is there a way of obtaining the dimensions of the actual playback region of the video within a division (not the division itself).
I've tried:
console.log($("#video").css("height"));
Where #video is the id of the video itself, but it seems to return the division height, not the video playback area.
This needs to happen within a window resize event handler:
$( window ).resize(function() {
//Detect playback window size
}

My solution was to get the original video size (see HTML5 Video Dimensions) and then compute the height and width based on the original aspect ratio.
The problem, as explained in that page, is that those dimensions are only retrieved after loading the metadata (which in my test page happened only after playing the video). The way to make the video load the metadata is to use the preload="metadata" attribute on the video tag.
The rest is just combining these:
var aspectratio=1;
resizeHandler();
$("video").on('loadedmetadata',function() {
var width = this.videoWidth;
var height = this.videoHeight;
aspectratio=width/height;
resizeHandler();
});
function dis(v) { return Math.round(v*100)/100; }
function resizeHandler() {
var height=$('video').height();
var width=$('video').width();
var actualHeight=Math.min(height,width/aspectratio);
var actualWidth=Math.min(width,height*aspectratio);
$('#spnInfo').text('ratio: '+dis(aspectratio)+' width: '+dis(width)+', height:'+dis(height)+' ,actual width: '+dis(actualWidth)+', actual height:'+dis(actualHeight));
}
$(window).resize(resizeHandler);
$('#btnResize').click(function() {
$('video').css({height:Math.random()*600+50,width:Math.random()*600+50});
$(window).trigger('resize');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="button" id="btnResize" value="Resize" /><span id="spnInfo"></span><br/>
<video poster="http://corrupt-system.de/assets/media/sintel/sintel-trailer.jpg" controls=""
preload="metadata" style="width:200px; height:500px">
<source src="http://corrupt-system.de/assets/media/sintel/sintel-trailer.m4v" type="video/mp4">
<source src="http://corrupt-system.de/assets/media/sintel/sintel-trailer.webm" type="video/webm">
</video>

Related

jQuery - Get height of video before it finishes loading

I have an 8MB video set to "object-fit:contain" and need to retrieve its height before it finishes loading on mobile devices. Reason I need the height earlier is to position content overlaying the video by matching the video height on this content container.
I am not looking for the actual height of the video, but the height as rendered in the user's browser / viewport.
If I try to get the height while it's loading, I get a much smaller value (200 some pixels) than what it ends up being (usually 600 some pixels). I've been able to get the height AFTER it loads using the load() function, but this method is very slow because my video is 8MB in size.
Is there any workaround?
jQuery(document).ready(function($){
function vidHeight() {
var newHeight = jQuery('#section-feature-device video').height();
jQuery(".elementor-element-0113321").css("height", newHeight+"px");
}
jQuery(window).load(function () {
var win = jQuery(this);
if (win.width() <= 767) {
vidHeight();
}
});
});
If you are planing to get the intrinsic height of the video, you may use the event listener loadedmetadata.
document.getElementById('video').addEventListener('loadedmetadata', (e) => console.info(e.target.videoHeight));
<video controls="true" poster="" id="video">
<source type="video/mp4" src="http://www.w3schools.com/html/mov_bbb.mp4">
</video>
I found how to find the video height by knowing the video width was 100%, therefore I just multiply the viewport width by the aspect ratio of the video.
jQuery(document).ready(function($){
function vidHeight() {
var viewportWidth = jQuery(window).width();
var videoHeight = viewportWidth * 0.5625;
jQuery("#section-feature").css("height", videoHeight+"px");
//console.log("Video height is "+videoHeight)
}
vidHeight();
jQuery(window).on('resize', vidHeight);
});

seamlessly change video resolution while video is playing

I am writing code that changes video resolution depending on the current screen size. On fullscreen button clicked I check screen size and if it is bigger than 1280px, a 1080p video is used instead of 720p.
I do that by changing src of the video element. Unfortunately, this causes a delay of a second or more, because the video with higher resolution needs to load first.
How can I create a seamless transition between the 2 resolutions? Sometimes youtube or facebook videos change resolution depending on your network conditions, and it is seamless in terms of delay.
This is my basic code. I use plyr library:
html
<video id="main-video" playsinline poster="/assets/img/video.png" class="element-video">
<source id="main-video-source" src="/assets/img/video.mp4" type="video/mp4" size="1080">
</video>
js
var player = new Plyr('#main-video',{controls:['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'settings', 'fullscreen']});
player.on('enterfullscreen', event => {
var videoPlayer = document.getElementById("main-video");
if(window.devicePixelRatio * window.innerWidth > 1280){
var currentTime = videoPlayer.currentTime;
videoPlayer.src = "video.mp4";
videoPlayer.currentTime = currentTime;
videoPlayer.play();
}else{
var currentTime = videoPlayer.currentTime;
videoPlayer.src = "video-720.mp4";
videoPlayer.currentTime = currentTime;
videoPlayer.play();
}
});
As Joel says, using Adaptive Bit Rate Streaming is the easiest approach here currently to get the affect you are looking for. See here for more info on ABR and an example of how to view it in action: https://stackoverflow.com/a/42365034/334402
Most video player clients will support ABR, and will give the type of smooth(ish...) transition you see on services like YouTube or Netflix when it steps through different resolutions. Having more different resolutions or 'steps' may make it smoother so it may be worth experimenting to find what is acceptable for your use case.
Also, as you already have at least two resolution versions of the video any extra server side overhead is not too great for your case.

Html5 video Scroll video

I've a problem with the scroll control of video. I took this code : http://codepen.io/ollieRogers/pen/lfeLc/.
var frameNumber = 0, // start video at frame 0
// lower numbers = faster playback
playbackConst = 500,
// get page height from video duration
setHeight = document.getElementById("set-height"),
// select video element
vid = document.getElementById('v0');
// var vid = $('#v0')[0]; // jquery option
// dynamically set the page height according to video length
vid.addEventListener('loadedmetadata', function() {
setHeight.style.height = Math.floor(vid.duration) * playbackConst + "px";
});
// Use requestAnimationFrame for smooth playback
function scrollPlay(){
var frameNumber = window.pageYOffset/playbackConst;
vid.currentTime = frameNumber;
window.requestAnimationFrame(scrollPlay);
}
window.requestAnimationFrame(scrollPlay);
And it work in all browsers with the video of codepen but when I put my test video, it's not smooth, I try a lot of differents codecs or formats (example with my test video : http://www.dugautiertheo.fr/videoscroll/).
I don't know why but it work fine and very smooth on Safari only.
Can you help me ?
Thank you
Per the first comment listed, it does appear to be something with the video. However, one additional thing to try would be to supply multiple video source files per the code provided in codepen.io this way you let the browser decide what is the best video type/codec to use. As shown below:
<video id="v0" tabindex="0" autobuffer="autobuffer" preload="preload">
<source type="video/webm; codecs="vp8, vorbis"" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"></source>
<source type="video/ogg; codecs="theora, vorbis"" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.ogv"></source>
<source type="video/mp4; codecs="avc1.42E01E, mp4a.40.2"" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.mp4"></source>
<p>Sorry, your browser does not support the <video> element.</p>
</video>
Problems arise, when grabing single frames in an highly compressed video container format like .mp4 etc with js. Our solution was to provide the video as a .json in a lottie animation:
scroll video example
You can check the source code.

Controls not showing on HTML5 Video when using javascript

I have a video that I wish to display on my webpage, everything is working except the controls are not showing up. I had an issue with displaying the video in my desired width and height so I used a little javascript hack to make it so. The autoplay attribute works but when applying the controls attribute it does not seem to work. Any ideas?
Here is my HTML
<canvas id="canvas" height="500" width="1300">
<video id="video" controls>
<source src="videos/Trailer.mp4" type="video/mp4">
</video>
</canvas>
and the Javascript
function updateVideo( ) {
var canvas = document.getElementById( 'canvas' );
var ctx = canvas.getContext( '2d' );
var myVideo = document.getElementById( 'video' );
ctx.drawImage( myVideo, 0, 0, 1300, 500 );
}
setInterval ( updateVideo, 24 );
The problem you're having by placing a canvas over the video is blocking the built in html video controls. My suggestion is to implement your own video controls (play, pause, volume, seeker, etc.) using html and javascript calling the video API. You can probably even make it prettier then the ugly built in controls. Your controls can be contained in a layer above the overlaid canvas, and thus the video will be shown, above it the overlay and above it your control set.
You can read a little about implementing your own controls here or here
Hope this helps :)

Displaying a <video> in a <canvas> in another window - how do I achieve the full frame rate?

I have a video playing in a video element in my main window. I would like to display the video in a cavas in a window I open() with JavaScript. (The original video element will be hidden, but it will still be responsble for playing the sound.)
I'm doing it like this.
<video id='video' style='display: none;' autoplay>
<source src="http://media.w3.org/2010/05/sintel/trailer.mp4" type='video/mp4' />
<source src="http://media.w3.org/2010/05/sintel/trailer.webm" type='video/webm' />
<source src="http://media.w3.org/2010/05/sintel/trailer.ogv" type='video/ogg' />
</video>
I open a new window and create a canvas element. Then I add a callback for each timeupdate event of the video in the main window. When this runs I copy the current frame of video to the canvas.
video.addEventListener("play", function() {
var child = open("/echo/html/", "width=" + video.videoWidth + ",height=" + video.videoHeight);
child.addEventListener("load", function() {
var canvas = child.document.createElement("canvas"),
g2d = canvas.getContext("2d");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
child.document.body.appendChild(canvas);
video.addEventListener("timeupdate", function() {
g2d.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
});
});
});
You can see this working here on jsfiddle but it doesn't run smoothly. It seems like the function for timeupdate will not be called every time the frame changes. It is called less often.
How can I display the video in the external window at its full quality?
timeupdate() is designed for displaying video run-time and indeed may not run for every frame.
To have smooth animation loop, animate it using requestAnimationFrame() loop on the consumer side
https://developer.mozilla.org/en-US/docs/DOM/window.requestAnimationFrame
For each requestAnimationFrame call pull over the new video frame.

Categories