snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
132
react/features/screenshot-capture/worker.ts
Normal file
132
react/features/screenshot-capture/worker.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import pixelmatch from 'pixelmatch';
|
||||
|
||||
import {
|
||||
CLEAR_TIMEOUT,
|
||||
MAX_FILE_SIZE,
|
||||
PERCENTAGE_LOWER_BOUND,
|
||||
SET_TIMEOUT,
|
||||
TIMEOUT_TICK
|
||||
} from './constants';
|
||||
|
||||
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
const canvas = new OffscreenCanvas(0, 0);
|
||||
const ctx = canvas.getContext('2d');
|
||||
let storedImageData: ImageData | undefined;
|
||||
|
||||
/**
|
||||
* Sends Blob with the screenshot to main thread.
|
||||
*
|
||||
* @param {ImageData} imageData - The image of the screenshot.
|
||||
* @returns {void}
|
||||
*/
|
||||
async function sendBlob(imageData: ImageData) {
|
||||
let imageBlob = await canvas.convertToBlob({ type: 'image/jpeg' });
|
||||
|
||||
if (imageBlob.size > MAX_FILE_SIZE) {
|
||||
const quality = Number((MAX_FILE_SIZE / imageBlob.size).toFixed(2)) * 0.92;
|
||||
|
||||
imageBlob = await canvas.convertToBlob({ type: 'image/jpeg',
|
||||
quality });
|
||||
}
|
||||
|
||||
storedImageData = imageData;
|
||||
|
||||
postMessage({
|
||||
id: TIMEOUT_TICK,
|
||||
imageBlob
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends empty message to main thread.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function sendEmpty() {
|
||||
postMessage({
|
||||
id: TIMEOUT_TICK
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the image bitmap on the canvas and checks the difference percent with the previous image
|
||||
* if there is no previous image the percentage is not calculated.
|
||||
*
|
||||
* @param {ImageBitmap} imageBitmap - The image bitmap that is drawn on canvas.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkScreenshot(imageBitmap: ImageBitmap) {
|
||||
const { height, width } = imageBitmap;
|
||||
|
||||
if (canvas.width !== width) {
|
||||
canvas.width = width;
|
||||
}
|
||||
|
||||
if (canvas.height !== height) {
|
||||
canvas.height = height;
|
||||
}
|
||||
|
||||
ctx?.drawImage(imageBitmap, 0, 0, width, height);
|
||||
const imageData = ctx?.getImageData(0, 0, width, height);
|
||||
|
||||
imageBitmap.close();
|
||||
|
||||
if (!imageData) {
|
||||
sendEmpty();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!storedImageData || imageData.data.length !== storedImageData.data.length) {
|
||||
sendBlob(imageData);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let numOfPixels = 0;
|
||||
|
||||
try {
|
||||
numOfPixels = pixelmatch(
|
||||
imageData.data,
|
||||
storedImageData.data,
|
||||
null,
|
||||
width,
|
||||
height);
|
||||
} catch {
|
||||
sendEmpty();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const percent = numOfPixels / imageData.data.length * 100;
|
||||
|
||||
if (percent >= PERCENTAGE_LOWER_BOUND) {
|
||||
sendBlob(imageData);
|
||||
} else {
|
||||
sendEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
onmessage = function(request) {
|
||||
switch (request.data.id) {
|
||||
case SET_TIMEOUT: {
|
||||
timer = setTimeout(async () => {
|
||||
const imageBitmap = request.data.imageBitmap;
|
||||
|
||||
if (imageBitmap) {
|
||||
checkScreenshot(imageBitmap);
|
||||
} else {
|
||||
sendEmpty();
|
||||
}
|
||||
}, request.data.timeMs);
|
||||
break;
|
||||
}
|
||||
case CLEAR_TIMEOUT: {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user