Hi everyone, the video I am intending to capture frames from is coming from a different URL, and hence while painting to the canvas it is throwing me a security error
ERROR Error: Uncaught (in promise): SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
Error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
Here is the code I have:
export async function extractFramesFromVideoCV2(cv, media?: DATA_DRIVE,
metaData?: VIDEO_METADATA,
service?: VideoOperatorService,
frameSize: FRAME_SIZE = { w: 50, h: 50 },) {
const start = new Date().getTime();
const video:HTMLVideoElement=createVideo()
video.src=metaData.url
let seekComplete;
video.onseeked = async (event) => {
if (seekComplete) seekComplete();
/**
* The seeked event is fired when a seek operation completed,
* the current playback position has changed,
* and the Boolean seeking attribute is changed to false.
*/
};
// workaround chromium metadata bug (https://stackoverflow.com/q/38062864/993683)
while (
(video.duration === Infinity || isNaN(video.duration)) &&
video.readyState < 2
) {
await new Promise((r) => setTimeout(r, 1000));
}
video.crossOrigin = "Anonymous"; // here I set the cross origin as anonymous but //still getting the same error
video.height = metaData.height;
video.width = metaData.width;
const sourceMatrix = new cv.Mat(
video.height,
video.width,
cv.CV_8UC4
);
const destinationMatrix = new cv.Mat(
video.height,
video.width,
cv.CV_8UC4
);
const openCVCaptureInstance = new cv.VideoCapture(video);
const canvas = createCanvas();
canvas.width = video.width;
canvas.height = video.height;
const FPS= metaData.fps
const intervalPerFrame = 1 / FPS; // 0.1 sec
const processingDelayPerFrame = 1000 / FPS;
let currentTime = intervalPerFrame;
let streaming=true;
let i=0
async function processVideo() {
let begin = Date.now();
if (!streaming) {
// shut down the process if streaming is complete.
return;
}
// start processing.
video.currentTime = currentTime; // seek video to next frame and wait until seeked to current time.
await once(video, "seeked");
openCVCaptureInstance.read(sourceMatrix);
sourceMatrix.copyTo(destinationMatrix);
cv.imshow(canvas, destinationMatrix);
i++;
canvas.toBlob((blob) => {
const rawUrl = URL.createObjectURL(blob);
currentTime += intervalPerFrame;
console.log(rawUrl, i);
if (i == metaData.numberOfFrames) {
// streaming of video completes
console.log("stream done");
streaming = false;
// clear the material from memory on stream complete
console.log("Clear memory");
sourceMatrix.delete();
destinationMatrix.delete();
video.remove();
} else {
if (streaming) {
let delay = processingDelayPerFrame - (Date.now() - begin);
// schedule next one.
setTimeout(processVideo, delay);
}
}
});
}
// schedule first one.
setTimeout(processVideo, 0);
}
However, for videos on the same domain, the code works perfect. Pls help
@matti.vuori @berak