1303c8e26f
- backup/restore dialog + user profile popover components - image compression, video blur, wake lock utilities - message cache + conversation messages hook refinements - call context, active speakers, screen share dialog tweaks - audio + screen share settings persistence - refreshed app icons (smaller sizes) across all platforms
68 lines
2.3 KiB
TypeScript
68 lines
2.3 KiB
TypeScript
// Background-blur processor wrapper. LiveKit's `@livekit/track-processors`
|
|
// ships a MediaPipe-based selfie-segmentation pipeline that keeps the
|
|
// foreground sharp and blurs the background. The model (~1.5MB) downloads
|
|
// lazily on first activation, so users who never enable blur don't pay
|
|
// for it.
|
|
//
|
|
// attach/detach hide behind a guard so repeated toggles don't create a
|
|
// stack of processors — `setProcessor(null)` tears down the WebGL context
|
|
// and frees the GPU surface.
|
|
|
|
import type { LocalParticipant, LocalVideoTrack } from 'livekit-client';
|
|
import { Track } from 'livekit-client';
|
|
|
|
let cachedProcessor: unknown = null;
|
|
|
|
async function getProcessor(): Promise<unknown> {
|
|
if (cachedProcessor) return cachedProcessor;
|
|
const mod = (await import('@livekit/track-processors')) as {
|
|
BackgroundBlur?: (radius?: number) => unknown;
|
|
};
|
|
if (!mod.BackgroundBlur) {
|
|
throw new Error('BackgroundBlur not exported by @livekit/track-processors');
|
|
}
|
|
cachedProcessor = mod.BackgroundBlur(12);
|
|
return cachedProcessor;
|
|
}
|
|
|
|
function getCameraTrack(lp: LocalParticipant): LocalVideoTrack | null {
|
|
const pub = lp.getTrackPublication(Track.Source.Camera);
|
|
const track = pub?.track;
|
|
if (!track) return null;
|
|
return track as LocalVideoTrack;
|
|
}
|
|
|
|
export async function applyBackgroundBlurToLocal(lp: LocalParticipant): Promise<void> {
|
|
try {
|
|
const track = getCameraTrack(lp);
|
|
if (!track) return;
|
|
const processor = await getProcessor();
|
|
// `setProcessor` is declared on LocalVideoTrack; cast because the
|
|
// processor type lives in a separate module we don't want to strongly
|
|
// couple to here.
|
|
await (track as unknown as {
|
|
setProcessor: (p: unknown) => Promise<void>;
|
|
}).setProcessor(processor);
|
|
} catch (err: unknown) {
|
|
console.warn('applyBackgroundBlur failed', err);
|
|
}
|
|
}
|
|
|
|
export async function removeBackgroundBlurFromLocal(lp: LocalParticipant): Promise<void> {
|
|
try {
|
|
const track = getCameraTrack(lp);
|
|
if (!track) return;
|
|
const setter = (track as unknown as {
|
|
setProcessor?: (p: unknown) => Promise<void>;
|
|
stopProcessor?: () => Promise<void>;
|
|
});
|
|
if (setter.stopProcessor) {
|
|
await setter.stopProcessor();
|
|
} else if (setter.setProcessor) {
|
|
await setter.setProcessor(null);
|
|
}
|
|
} catch (err: unknown) {
|
|
console.warn('removeBackgroundBlur failed', err);
|
|
}
|
|
}
|