canvas捕获的第一帧输出到img后全黑
The first frame captured by the canvas becomes completely black after outputting to the img
试了很多文章和方法还是无法解决,希望得到一点提示
那英语不是我的母语,抱歉
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>
您在这里混合了几段代码...
当您想在 canvas 上绘制 img
时,img.onload
部分适用。在这种情况下你不是,你想绘制 video
,然后(可能)用从 canvas.
中提取的图像填充 img
所以在这种情况下,你不需要等待图像加载,你可以直接将视频绘制到canvas。
但是,loadeddata
并不意味着帧已呈现给视频元素,因此您可能更愿意等待 playing
等其他事件。
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>
不过,您最好避免使用 toDataURL
,而更喜欢使用 toBlob
,这样会占用更少的内存
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>
或者,因为你显然只是在“展示”这个框架,所以直接附加 <canvas>
,这在记忆方面更好:
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>
试了很多文章和方法还是无法解决,希望得到一点提示
那英语不是我的母语,抱歉
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>
您在这里混合了几段代码...
当您想在 canvas 上绘制 img
时,img.onload
部分适用。在这种情况下你不是,你想绘制 video
,然后(可能)用从 canvas.
img
所以在这种情况下,你不需要等待图像加载,你可以直接将视频绘制到canvas。
但是,loadeddata
并不意味着帧已呈现给视频元素,因此您可能更愿意等待 playing
等其他事件。
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>
不过,您最好避免使用 toDataURL
,而更喜欢使用 toBlob
,这样会占用更少的内存
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>
或者,因为你显然只是在“展示”这个框架,所以直接附加 <canvas>
,这在记忆方面更好:
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>