2021-11-24 11:05:27 +00:00
|
|
|
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications';
|
2021-06-17 14:03:39 +00:00
|
|
|
import { showWarningNotification } from '../../notifications/actions';
|
2021-08-26 13:33:43 +00:00
|
|
|
import { timeout } from '../../virtual-background/functions';
|
2021-06-17 14:03:39 +00:00
|
|
|
import logger from '../../virtual-background/logger';
|
2021-02-18 15:52:47 +00:00
|
|
|
|
|
|
|
import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
|
|
|
|
import createTFLiteModule from './vendor/tflite/tflite';
|
|
|
|
import createTFLiteSIMDModule from './vendor/tflite/tflite-simd';
|
|
|
|
const models = {
|
2022-01-06 09:16:55 +00:00
|
|
|
modelLandscape: 'libs/selfie_segmentation_landscape.tflite'
|
2021-02-18 15:52:47 +00:00
|
|
|
};
|
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
let modelBuffer;
|
2021-10-18 12:19:21 +00:00
|
|
|
let tflite;
|
|
|
|
let wasmCheck;
|
|
|
|
let isWasmDisabled = false;
|
|
|
|
|
2021-02-18 15:52:47 +00:00
|
|
|
const segmentationDimensions = {
|
2022-01-06 09:16:55 +00:00
|
|
|
modelLandscape: {
|
2021-02-18 15:52:47 +00:00
|
|
|
height: 144,
|
|
|
|
width: 256
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new instance of JitsiStreamBackgroundEffect. This loads the Meet background model that is used to
|
|
|
|
* extract person segmentation.
|
|
|
|
*
|
|
|
|
* @param {Object} virtualBackground - The virtual object that contains the background image source and
|
|
|
|
* the isVirtualBackground flag that indicates if virtual image is activated.
|
2021-06-17 14:03:39 +00:00
|
|
|
* @param {Function} dispatch - The Redux dispatch function.
|
2021-02-18 15:52:47 +00:00
|
|
|
* @returns {Promise<JitsiStreamBackgroundEffect>}
|
|
|
|
*/
|
2021-06-17 14:03:39 +00:00
|
|
|
export async function createVirtualBackgroundEffect(virtualBackground: Object, dispatch: Function) {
|
2021-02-18 15:52:47 +00:00
|
|
|
if (!MediaStreamTrack.prototype.getSettings && !MediaStreamTrack.prototype.getConstraints) {
|
|
|
|
throw new Error('JitsiStreamBackgroundEffect not supported!');
|
|
|
|
}
|
2021-06-17 14:03:39 +00:00
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
if (isWasmDisabled) {
|
|
|
|
dispatch(showWarningNotification({
|
|
|
|
titleKey: 'virtualBackground.backgroundEffectError'
|
|
|
|
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-06-17 14:03:39 +00:00
|
|
|
// Checks if WebAssembly feature is supported or enabled by/in the browser.
|
|
|
|
// Conditional import of wasm-check package is done to prevent
|
|
|
|
// the browser from crashing when the user opens the app.
|
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
if (!tflite) {
|
2021-10-18 12:19:21 +00:00
|
|
|
try {
|
|
|
|
wasmCheck = require('wasm-check');
|
|
|
|
const tfliteTimeout = 10000;
|
|
|
|
|
|
|
|
if (wasmCheck?.feature?.simd) {
|
|
|
|
tflite = await timeout(tfliteTimeout, createTFLiteSIMDModule());
|
|
|
|
} else {
|
|
|
|
tflite = await timeout(tfliteTimeout, createTFLiteModule());
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
if (err?.message === '408') {
|
|
|
|
logger.error('Failed to download tflite model!');
|
|
|
|
dispatch(showWarningNotification({
|
|
|
|
titleKey: 'virtualBackground.backgroundEffectError'
|
2021-11-24 11:05:27 +00:00
|
|
|
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
2021-10-18 12:19:21 +00:00
|
|
|
} else {
|
2022-04-25 09:14:45 +00:00
|
|
|
isWasmDisabled = true;
|
2021-12-08 10:27:06 +00:00
|
|
|
logger.error('Looks like WebAssembly is disabled or not supported on this browser', err);
|
2021-10-18 12:19:21 +00:00
|
|
|
dispatch(showWarningNotification({
|
|
|
|
titleKey: 'virtualBackground.webAssemblyWarning',
|
2021-12-08 10:27:06 +00:00
|
|
|
descriptionKey: 'virtualBackground.webAssemblyWarningDescription'
|
2021-11-24 11:05:27 +00:00
|
|
|
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
2021-10-18 12:19:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2021-08-26 13:33:43 +00:00
|
|
|
}
|
2021-02-18 15:52:47 +00:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
if (!modelBuffer) {
|
|
|
|
const modelResponse = await fetch(models.modelLandscape);
|
2021-02-18 15:52:47 +00:00
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
if (!modelResponse.ok) {
|
|
|
|
throw new Error('Failed to download tflite model!');
|
|
|
|
}
|
2021-02-18 15:52:47 +00:00
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
modelBuffer = await modelResponse.arrayBuffer();
|
2021-02-18 15:52:47 +00:00
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
tflite.HEAPU8.set(new Uint8Array(modelBuffer), tflite._getModelBufferMemoryOffset());
|
2021-02-18 15:52:47 +00:00
|
|
|
|
2022-08-15 11:02:47 +00:00
|
|
|
tflite._loadModel(modelBuffer.byteLength);
|
|
|
|
}
|
2021-02-18 15:52:47 +00:00
|
|
|
|
|
|
|
const options = {
|
2022-01-06 09:16:55 +00:00
|
|
|
...segmentationDimensions.modelLandscape,
|
2021-02-18 15:52:47 +00:00
|
|
|
virtualBackground
|
2021-10-25 11:48:18 +00:00
|
|
|
};
|
2021-02-18 15:52:47 +00:00
|
|
|
|
2021-05-14 14:53:11 +00:00
|
|
|
return new JitsiStreamBackgroundEffect(tflite, options);
|
2021-02-18 15:52:47 +00:00
|
|
|
}
|