'Why is ctx.drawImage only drawing part of the video element to canvas?

I am trying to draw a movie frame to the canvas element using ctx.DrawImage and I am getting what I think are very weird scaling / cropping behaviors.

First, here is my code:

HTML

<body>
    <video autoplay width="125" height="125"></video>
    <img src="">
    <canvas></canvas>
</body>

Javascript:

    var video = document.querySelector('video');
    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    var localMediaStream = null;

    function snapshot() {
        if (localMediaStream) {
            ctx.drawImage(video, 0, 0, 125, 125);
            document.querySelector('img').src = canvas.toDataURL('image/webp');
        }
    }   

video.addEventListener('click', snapshot, false);

navigator.getUserMedia(

    {
        video: true

    }, function(stream) {
        video.src = window.URL.createObjectURL(stream);
        localMediaStream = stream;
});

What this does is essentially take the still from the video and squish it so that it is about 1/3 the original width and about 70% of the height. This is frustrating.

Leaving off the 125 and just using ctx.drawImage(video, 0, 0) fills the canvas with the still, however, it is only about the top left corner (25%) of the image. This is also frustrating.

How can I make the canvas draw the exact same sized image as the video element is playing?

This is coupled with the fact the video element itself is indeed 125px x 125px but my because of the aspect ratio, there is letter boxing (white space) around the video element. Is there a way to force the video element to fill itself with the incoming video stream?



Solution 1:[1]

I too was facing the same problem when I tried...

var sw = video.offsetWidth, // source width
    sh = video.offsetHeight, // source height
    dw = canvas.width, // destination width
    dh = canvas.height; // destination height
ctx.drawImage(video, 0, 0, sw, sh, 0, 0, dw, dh);

it got solved when I changed to :

ctx.drawImage(video, 0, 0, dw, dh);

I believe in your case the problem is, 125 is height and width of video element, but what you should be supplying is the canvas height and width, for example, setting the canvas width and height:

canvas.width = 125;
canvas.height = 125;
ctx.drawImage(video, 0, 0, 125, 125);

Solution 2:[2]

This seems to be a very old question, but I was faced with a similar challenge a few days back.

Making use of CSS viewport units to set height & width of the canvas and also adjust size of the tags saved my day.

Viewport units allow you to size elements and font sizes as a percentage of the total width or height of the user’s screen (the viewport).

This is how i implemented in my code

The video tags

<video id="video" style="height: calc(25vh - 15px); width: calc(25vh - 15px); border: 1px solid gray;" autoplay playsinline></video>

You can read more about them here https://alligator.io/css/viewport-units/

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mido
Solution 2 Benson Okello