javascriptcanvasvideoperspective

Draw a video frame using perspective on a canvas


I know how to draw a video frame on a canvas with this code I got from Codepen:

let v = document.querySelector("video");
let c = document.querySelector("canvas");
let ctx = c.getContext("2d");
let i;
function draw() {
  let times = v.videoWidth/270;
  let vHeight = v.videoHeight/times;
  c.width = 270;
  c.height = vHeight; 
  i = window.requestAnimationFrame(draw)
  ctx.drawImage(v, 0, 0, 270, vHeight)
}

v.addEventListener("loadeddata", function() {
  draw()
}, false);
v.addEventListener("play", function() {
  draw()
}, false);
v.addEventListener("pause", function() {
  window.cancelAnimationFrame(i);
  i = undefined;
}, false);
v.addEventListener("ended", function() {
  window.cancelAnimationFrame(i);
  i = undefined;
}, false); 

I also know how to draw an image with prespective on a canvas with the perspective.js from wanadev on github. Now my question is how to combine those two to get a drawn video frame with perspective. I tried to combine those two like this:

function zeichne() {
    let times = v.videoWidth/270;
    let vHeight = v.videoHeight/times;
    c.width = 270;
    c.height = vHeight; 
    i = window.requestAnimationFrame(zeichne)
    var p = new Perspective(ctx, v);
    //This is the original perspective draw
    /* p.draw([
            [0, 0],
            [image.width - 50, 50],
            [image.width - 70, image.height - 30],
            [10, image.height]
    ]); */
    //This is mine
    p.draw([
        [0, 0],
        [times - 50, 50],
        [times - 70, vHeight - 30],
        [10, vHeight]
    ]); 
    //ctx.drawImage(v, 40, 0, 270, vHeight)
  }
}

The problem is that I just get an error saying: 'this.p is undefined' in line 84 of perspective.js. But I checked the js and can't see any mistakes in my code or the perspective.js.


Solution

  • I made a working snippet. According to the following Error message it should work with video element as well as others.

    "TypeError: The provided value is not of type '(CSSImageValue or HTMLCanvasElement or HTMLImageElement or HTMLVideoElement or ImageBitmap or OffscreenCanvas or SVGImageElement or VideoFrame)'.
        at new html5jp.perspective (<anonymous>:43:14)
        at processFrame (<anonymous>:39:12)
        at HTMLVideoElement.<anonymous> (<anonymous>:57:3)"
    

    Issue was importing the correct library and calling the correct constructor.

    const video = document.getElementById('videoElement');
    const outputCanvas = document.getElementById('outputCanvas');
    const outputCtx = outputCanvas.getContext('2d');
    const Perspective = html5jp.perspective
    const points = [
      [20, 20],
      [150, 10],
      [160, 100],
      [-20, 90]
    ];
    
    function processFrame() {
      var p = new Perspective(outputCtx, video);
      p.draw(points)
      requestAnimationFrame(processFrame);
    }
    
    // Handle video play/pause events
    video.addEventListener('play', () => {
      console.log('Video started playing');
      processFrame();
    });
    canvas,
    video {
      border: 1px solid gray;
    }
    <script src="https://unpkg.com/perspectivejs@1.0.4/src/perspective.js"></script>
    
    <video id="videoElement" width="160" height="100" autoplay muted loop controls crossorigin="anonymous" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"></video>
    <canvas id="outputCanvas" width="160" height="100"></canvas>