feat: backup/restore, user profile popover, image compress, video blur, wake lock
- 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
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user