HTML 5 Canvas drawImage is droping the quality of orginal video

Viewed 2087

I wanted to display same video in two area of the application. So using canvas its working fine but the quality of original video is getting dropped but canvas video quality is fine.

var canvas = document.getElementById('shrinkVideo');
var context = canvas.getContext('2d');
var video = document.getElementById('mainVideo');

video.addEventListener('play', () => {
            // canvas.width = 270;
            // canvas.height = 480;
           this.draw(video, context, canvas.width,canvas.height);
        }, false);

   draw(v, c, w, h) {
        if (v.paused || v.ended) return false;
        c.drawImage(v, 0, 0, w, h);
        setTimeout(this.draw, 20, v, c, w, h);
    }

This is my code to sync two video's and it is working fine but 'mainVideo' quality gets dropped.

But if I remove all the canvas code and just play 'mainVideo' the quality is maintained but using canvas its quality get dropped.

Expected Result This is output of the video when canvas code is not added

Actual Result This is output I am getting after adding the canvas code

Thanks In Advance

1 Answers

I came to this answer because I thought I was experiencing the same issue.

  • I have 1080p source on a element (HD content from a HDMI capture device, which registers as a webcam in the browser)
  • I had a 1920x1080 canvas and I was using ctx.drawImage(video, 0, 0, 1920, 1080) - as mentioned by a commenter above, I think I've found it crucial that you draw only in good multiples of the original height/width values.
  • I tried with-and-without imageSmoothingEnabled and various imageSmoothingQuality settings in Chrome/Brave; ultimately, I saw no vast difference with these settings.
  • My canvas on my webapp was still coming out extremely blurry -- unable to read even ~24pt font on the screen, basically couldn't use the video at all

I was frustrated by my blurry video so I recreated a full test in a "clean suite" here and now I experience no scaling issues anymore -- I don't know what my main application is doing differently yet, but in this example, you can attach any 1080p/720p device and see it scaled quite nicely to 1080p (change the resolution in the JS file if you want to scale to 720p)

https://playcode.io/543520

  const WIDTH = 1920;
  const HEIGHT = 1080;
  const video = document.getElementById('video1'); // Video element
  const broadcast = document.getElementById('broadcast'); // Canvas element
  broadcast.width = video.width = WIDTH;
  broadcast.height = video.height = HEIGHT;

  let ctx = broadcast.getContext('2d')

  onFrame = function() {
    ctx.drawImage(video, 0, 0, broadcast.width, broadcast.height)
    window.requestAnimationFrame(onFrame);
  }

  navigator.mediaDevices
    .getUserMedia({ video: true })
    .then(stream => {
      window.stream = stream
      console.log('got UM')
      video.srcObject = stream;
      window.onFrame();
    })

Below you can see my viewport, with a Video and Canvas element (both 1080p, scaled to ~45% so they fit), using requestAnimationFrame to draw my content. The content is zoomed out, so you can see anti-aliasing, but if you load the example and click on the Canvas, it goes to Fullscreen, and the quality is pretty good - I played a 1080p Youtube video on my source machine, and couldn't see any difference on my full screen 1080p canvas element. enter image description here

Related