5

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

  • What do you mean by drop in quality. Is the resolution lower? (if so ensure that the canvas resolution matches the video) Is it dropping frames, showing blank frames, or jittery ? (if so use `requestAnimationFrame` to render the video rather than `setTimeout`). There could be other sources of quality loss but you will have give us more information about what aspect of the video quality is degrading. – Blindman67 Aug 02 '17 at 10:26
  • @Blindman67 I have added the Images of what is expected and what is actual result I am getting. The aspect ration of video is 9:16 which is properly displaying in canvas but not in video tag – Avinash Lakhera Aug 02 '17 at 10:52
  • Upscaling the video to a bad fitting size. Ensure that image smoothing is on `ctx.imageSmoothingEnabled = true` You are scaling up by ~ 1.1875 which is bad, you want a scale like 1.2, 1.25, 1.5, or 2 Smoothing will help but for the best quality you should scale at whole values 2 times 3 times original. 256 -> 384 @ 1.5 scale, or 512 @ 2 will be much better. Also make sure that the canvas pixel size matches the CSS pixel size. Scaling video will reduce quality, you must plan how you scale images (video) to get the best result, (note you can also clip pixels for a better scale) – Blindman67 Aug 02 '17 at 12:26
  • This will explain/solve the issue: https://stackoverflow.com/questions/17861447/html5-canvas-drawimage-how-to-apply-antialiasing/17862644#17862644 There is also a new setting coming to 2d context, currently only supported in chrome, the "`imageSmoothingQuality`" which can be set to high and will improve the scaling issue. –  Aug 02 '17 at 16:51
  • @Blindman67 The quality of video in canvas is working fine but the original video in video tags quality gets dropped – Avinash Lakhera Aug 03 '17 at 02:41

1 Answers1

1

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

linked
  • 1,258
  • 1
  • 14
  • 25