diff --git a/public/opencv-worker.js b/public/opencv-worker.js index 073223d..a5964d7 100644 --- a/public/opencv-worker.js +++ b/public/opencv-worker.js @@ -83,6 +83,11 @@ function blurGray(src, dst) { } self.onmessage = async (event) => { + // Dedicated worker messages should only come from the creating page. + if (event.origin !== "" && event.origin !== self.location.origin) { + return; + } + const msg = event.data; const { id, type } = msg; diff --git a/src/webcam.ts b/src/webcam.ts index 1fa54c7..917f4ca 100644 --- a/src/webcam.ts +++ b/src/webcam.ts @@ -71,9 +71,8 @@ export function countWebmFrames(blob: Blob): Promise<{ frameCount: number; durat const video = document.createElement("video"); video.preload = "auto"; video.muted = true; - - const blobUrl = URL.createObjectURL(blob); - video.src = blobUrl; + // Prefer srcObject over createObjectURL+.src so the blob is not reinterpreted as an HTML URL. + video.srcObject = blob; let lastPresentedFrames = 0; let settled = false; @@ -81,14 +80,14 @@ export function countWebmFrames(blob: Blob): Promise<{ frameCount: number; durat const timeoutId = setTimeout(() => { if (!settled) { settled = true; - URL.revokeObjectURL(blobUrl); + video.srcObject = null; reject(new Error("Timeout counting WebM frames")); } }, 60000); const cleanup = () => { clearTimeout(timeoutId); - URL.revokeObjectURL(blobUrl); + video.srcObject = null; }; video.addEventListener("ended", () => { @@ -509,7 +508,7 @@ export async function estimateVideoFrameRate( ); const deviation = Math.abs(empiricalFps - closestCommon); - let confidence: "high" | "medium" | "low" = "medium"; + let confidence: "high" | "medium" | "low"; if (deviation < 1) { confidence = "high"; @@ -638,11 +637,12 @@ export async function extractVideoFileMetadata(file: File, defaultFps: number): // Generic video: probe duration via a temporary video element. return new Promise((resolve) => { - const tempUrl = URL.createObjectURL(file); const tempVideo = document.createElement("video"); tempVideo.preload = "metadata"; - tempVideo.src = tempUrl; - const cleanup = () => URL.revokeObjectURL(tempUrl); + tempVideo.srcObject = file; + const cleanup = () => { + tempVideo.srcObject = null; + }; tempVideo.addEventListener( "loadedmetadata", () => {