I try many articles and methods but still can’t solve it, I hope to get a little hint
Then English is not my native language, sorry
var video = document.getElementById('video'); var canvas = document.createElement('canvas'); var videobg = document.getElementById('bgc'); video.addEventListener('loadeddata', function() { canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d'); var img = new Image; img.onload = function() { ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); } var imgURL = canvas.toDataURL('image/jpeg'); img.setAttribute('src', imgURL); videobg.appendChild(img); }) }
<div class="flexbord"> <div id="bgc" class="bgc"> <video id="video" src="https://kwibao-video.s3.ap-northeast-1.amazonaws.com/h7C886i3HFJs98SVUQG5_video_1626853820000.mp4" type="mp4" autoplay muted loop></video> </div> <div class="qwe"></div> </div>
Advertisement
Answer
You are mixing a few pieces of code here…
The img.onload
part works for when you want to draw that img
on the canvas. Here you are not in this case, you want to draw the video
, and then (probably) populate the img
with an image extracted from the canvas.
So in this case, you don’t need to wait for the image load, you can draw directly the video to the canvas.
However, the loadeddata
doesn’t mean that a frame has been presented to the video element yet, so you may prefer to wait for an other event like playing
instead.
var video = document.getElementById('video'); var canvas = document.createElement('canvas'); var videobg = document.getElementById('bgc'); var ctx = canvas.getContext("2d"); video.addEventListener('playing', function() { canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d'); // draw the video directly ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); var img = new Image; // now this represents the canvas, when the video has been drawn on it var imgURL = canvas.toDataURL('image/jpeg'); img.setAttribute('src', imgURL); videobg.appendChild(img); }, { once: true });
.bgc { display: flex; }
<div class="flexbord"> <div id="bgc" class="bgc"> <!-- don't forget to set the crossorigin attribute --> <video id="video" src="https://kwibao-video.s3.ap-northeast-1.amazonaws.com/h7C886i3HFJs98SVUQG5_video_1626853820000.mp4" crossorigin type="mp4" autoplay muted loop></video> </div> <div class="qwe"></div> </div>
However you’d be better avoiding toDataURL
and prefer toBlob
instead, which uses a lot less memory
var video = document.getElementById('video'); var canvas = document.createElement('canvas'); var videobg = document.getElementById('bgc'); var ctx = canvas.getContext("2d"); video.addEventListener('playing', function() { canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d'); // draw the video directly ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); var img = new Image; canvas.toBlob(async(blob) => { img.src = URL.createObjectURL(blob); await img.decode(); // wait for the image is loaded URL.revokeObjectURL(img.src); videobg.appendChild(img); }, 'image/jpeg'); }, { once: true });
.bgc { display: flex; }
<div class="flexbord"> <div id="bgc" class="bgc"> <!-- don't forget to set the crossorigin attribute --> <video id="video" src="https://kwibao-video.s3.ap-northeast-1.amazonaws.com/h7C886i3HFJs98SVUQG5_video_1626853820000.mp4" crossorigin type="mp4" autoplay muted loop></video> </div> <div class="qwe"></div> </div>
or, since you are apparently only “presenting” this frame, append the <canvas>
directly, which is even better memory wise:
var video = document.getElementById('video'); var canvas = document.createElement('canvas'); var videobg = document.getElementById('bgc'); var ctx = canvas.getContext("2d"); video.addEventListener('playing', function() { canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d'); // draw the video directly ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); // show the canvas videobg.appendChild(canvas); }, { once: true });
.bgc { display: flex; }
<div class="flexbord"> <div id="bgc" class="bgc"> <!-- don't forget to set the crossorigin attribute --> <video id="video" src="https://kwibao-video.s3.ap-northeast-1.amazonaws.com/h7C886i3HFJs98SVUQG5_video_1626853820000.mp4" crossorigin type="mp4" autoplay muted loop></video> </div> <div class="qwe"></div> </div>