I have a video that's streaming parts of a video into a MediaSource
and playing it. I have a canvas that I want to draw the video on an then overlay some effects. However, in my handler, the call to drawImage
, while it works, it only appears to copy a single pixel. The video itself plays fine.
I have a screenshot from my app, which has the source video next to the destination canvas element:
As you can sorta see, the solid color of the canvas is the color of the very first pixel of the source video.
The actual code in question looks similar to this:
startWatch() {
this.timer = setInterval(this.copyFrame.bind(this), 1000 / this.fps)
}
copyFrame() {
const { width, height } = this.video.getBoundingClientRect()
// I've tried the 3, 5, and 9 argument versions of this function
// width is 300 and height is 168.75.
this.ctx.drawImage(this.video, 0, 0, width, height, 0, 0, width, height)
}
(where this.video
is a video
element)
This code does "work" in that the canvas's color does update over time as the video plays. But it's always just the initial pixel. So the timing loop works, but the drawImage
call isn't doing what I expect.
(1) Using const { width, height }
may not be correct. Check the values you are given.
What happens if you console.log
the width or height values, are they correct/expected numbers?
(2) "...But the drawImage
call isn't doing what I expect."
ctx.drawImage( someElement, 0, 0, A1, A2, 0, 0, B1, B2 );
Consider the above code,
The first width/height (A1/A2) is for how much of the input to draw (it must match size of input's own width/height, otherwise cropping or margins will occur). Eg: A1 == 720
if input video is 720 pixels wide.
The second width/height (B1/B2) is for how much resize of the output to draw. Usually you want to fill entire canvas area so use canvas dimensions (aspect ratio is left to coder to implement as preferred).
In your shown code, your const { width, height }
is either
Possible solutions:
Try (if you must use bounding rectangle):
function copyFrame()
{
//# width is 300 and height is 168.75.
//const { width, height } = this.video.getBoundingClientRect()
let myRect = this.video.getBoundingClientRect();
this.ctx.drawImage( this.video, 0, 0,
this.video.videoWidth, this.video.videoHeight,
0, 0, myRect.width, myRect.height);
}
Alternativey you could just draw the picture into canvas size:
function copyFrame()
{
//# assuming your Canvas is called "this.cnvs"
this.ctx.drawImage( this.video, 0, 0,
this.video.videoWidth, this.video.videoHeight,
0, 0, this.cnvs.width, this.cnvs.height);
}
For aspect ratio you can use the below formula (swap all width & height references for a new drawn_width
)
myRatio = ( vid_height / vid_width );
drawn_height = ( myCanvas_width * myRatio );