I want to use the first frame of a video as the background for a canvas, but I've been struggling with it. I can set a background and extract a frame from a video, but I can't seem to make that frame the background. It seems like I need a URL for the frame in order to set it as the background using CSS. For that, I believe I need a blob on which I can call createObjectURL() (although I am aware that this method may be deprecated).
Here is some code:
<!DOCTYPE html>
<html lang="en">
<canvas id="back" style="background-image: url('path/to/.png')";></canvas>
<input type="file" accept="video/*" />
<script>
document.querySelector('input').addEventListener('change', extractFrame, false);
var canvas = document.getElementById('back');
var context = canvas.getContext('2d');
var imageObj = new Image();
var image;
imageObj.onload = function() {
var height = imageObj.height;
var width = imageObj.width;
canvas.height = height;
canvas.width = width;
context.drawImage(imageObj, 0, 0, back.width, back.height);
};
imageObj.src = "path/to/.png";
var draw_canvas = document.getElementById('back');
var draw_context = draw_canvas.getContext('2d');
var corners = [];
draw_canvas.addEventListener('mousedown',startDrawing,false);
function startDrawing(e){
corners.length=0;
corners.push([e.layerX, e.layerY]);
corners.push([e.layerX+1, e.layerY+1]);
draw_canvas.addEventListener('mousemove', updateCorners,false);
draw_canvas.addEventListener('mouseup',function(){
draw_canvas.removeEventListener('mousemove', updateCorners,false);
},false);
}
function updateCorners(e){
corners[1] = [e.layerX, e.layerY]
redraw();
}
function redraw(){
draw_context.clearRect(0, 0, canvas.width, canvas.height);
draw_context.beginPath()
draw_context.lineWidth = "2";
draw_context.strokeStyle = "red";
draw_context.rect(corners[0][0], corners[0][1], corners[1][0] - corners[0][0], corners[1][1] - corners[0][1]);
draw_context.stroke();
}
function extractFrame(){
var video = document.createElement('video');
var array = [];
function initCanvas(){
canvas.width = this.videoWidth;
canvas.height = this.videoHeight;
}
function drawFrame(e) {
this.pause();
context.drawImage(this, 0, 0);
var blob = canvas.toBlob(saveFrame, 'image/png');
var dataUrl = URL.createObjectURL(array[0]);
document.getElementById('back').style.background = "url('${dataUrl}')";
URL.revokeObjectURL(dataUrl);
}
function saveFrame(blob) {
console.log(array);
array.push(blob);
console.log(array);
}
video.muted = true;
video.addEventListener('loadedmetadata', initCanvas, false);
video.addEventListener('timeupdate', drawFrame, false);
video.src = URL.createObjectURL(this.files[0]);
video.play();
}
</script>
I've tried reordering the code, adjusting objects passed around, and more, but nothing seems to work. One common error I encounter is:
Failed to execute 'createObjectURL' on 'URL': Overload resolution failed.
According to another source, this could be due to the object in the array being undefined or None, but the logged array shows that it contains blobs.
Any advice would be greatly appreciated. Let me know if you need more code or specifications. Thank you!
EDIT: I have added additional code for clarity. I am testing this locally, so hopefully it will suffice for now.