@livekit/track-processors 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -248,7 +248,7 @@ var _tasksvision = require('@mediapipe/tasks-vision'); var vision = _interopRequ
248
248
 
249
249
  // package.json
250
250
  var dependencies = {
251
- "@mediapipe/tasks-vision": "^0.10.22-rc.20250304"
251
+ "@mediapipe/tasks-vision": "0.10.14"
252
252
  };
253
253
 
254
254
  // src/webgl/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/ProcessorWrapper.ts","../src/transformers/BackgroundTransformer.ts","../package.json","../src/webgl/index.ts","../src/transformers/VideoTransformer.ts","../src/index.ts"],"names":["_a","BackgroundProcessor"],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention */\nexport const supportsProcessor = typeof MediaStreamTrackGenerator !== 'undefined';\nexport const supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined';\n\nasync function sleep(time: number) {\n return new Promise((resolve) => setTimeout(resolve, time));\n}\n\nexport async function waitForTrackResolution(track: MediaStreamTrack) {\n const timeout = 500;\n\n // browsers report wrong initial resolution on iOS.\n // when slightly delaying the call to .getSettings(), the correct resolution is being reported\n await sleep(10);\n\n const started = Date.now();\n while (Date.now() - started < timeout) {\n const { width, height } = track.getSettings();\n if (width && height) {\n return { width, height };\n }\n await sleep(50);\n }\n return { width: undefined, height: undefined };\n}\n","import type { ProcessorOptions, Track, TrackProcessor } from 'livekit-client';\nimport { TrackTransformer } from './transformers';\nimport { waitForTrackResolution } from './utils';\n\nexport interface ProcessorWrapperOptions {\n /**\n * Maximum frame rate for fallback canvas.captureStream implementation\n * Default: 30\n */\n maxFps?: number;\n}\n\nexport default class ProcessorWrapper<TransformerOptions extends Record<string, unknown>>\n implements TrackProcessor<Track.Kind>\n{\n /**\n * Determines if the Processor is supported on the current browser\n */\n static get isSupported() {\n // Check for primary implementation support\n const hasStreamProcessor =\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined';\n\n // Check for fallback implementation support\n const hasFallbackSupport =\n typeof HTMLCanvasElement !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n 'captureStream' in HTMLCanvasElement.prototype;\n\n // We can work if either implementation is available\n return hasStreamProcessor || hasFallbackSupport;\n }\n\n /**\n * Determines if modern browser APIs are supported, which yield better performance\n */\n static get hasModernApiSupport() {\n return (\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined'\n );\n }\n\n name: string;\n\n source?: MediaStreamVideoTrack;\n\n processor?: MediaStreamTrackProcessor<VideoFrame>;\n\n trackGenerator?: MediaStreamTrackGenerator<VideoFrame>;\n\n canvas?: OffscreenCanvas;\n\n displayCanvas?: HTMLCanvasElement;\n\n sourceDummy?: HTMLMediaElement;\n\n processedTrack?: MediaStreamTrack;\n\n transformer: TrackTransformer<TransformerOptions>;\n\n // For tracking whether we're using the stream API fallback\n private useStreamFallback = false;\n\n // For fallback rendering with canvas.captureStream()\n private capturedStream?: MediaStream;\n\n private animationFrameId?: number;\n\n private renderContext?: CanvasRenderingContext2D;\n\n private frameCallback?: (frame: VideoFrame) => void;\n\n private processingEnabled = false;\n\n // FPS control for fallback implementation\n private maxFps: number;\n\n constructor(\n transformer: TrackTransformer<TransformerOptions>,\n name: string,\n options: ProcessorWrapperOptions = {},\n ) {\n this.name = name;\n this.transformer = transformer;\n this.maxFps = options.maxFps ?? 30;\n }\n\n private async setup(opts: ProcessorOptions<Track.Kind>) {\n this.source = opts.track as MediaStreamVideoTrack;\n\n const { width, height } = await waitForTrackResolution(this.source);\n this.sourceDummy = opts.element;\n\n if (!(this.sourceDummy instanceof HTMLVideoElement)) {\n throw TypeError('Currently only video transformers are supported');\n }\n\n if (this.sourceDummy instanceof HTMLVideoElement) {\n this.sourceDummy.height = height ?? 300;\n this.sourceDummy.width = width ?? 300;\n }\n\n this.useStreamFallback = !ProcessorWrapper.hasModernApiSupport;\n\n if (this.useStreamFallback) {\n // Create a visible canvas for the fallback implementation or use an existing one if provided\n const existingCanvas = document.querySelector(\n 'canvas[data-livekit-processor=\"' + this.name + '\"]',\n ) as HTMLCanvasElement;\n\n if (existingCanvas) {\n this.displayCanvas = existingCanvas;\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n } else {\n this.displayCanvas = document.createElement('canvas');\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n this.displayCanvas.style.display = 'none';\n this.displayCanvas.dataset.livekitProcessor = this.name;\n document.body.appendChild(this.displayCanvas);\n }\n\n this.renderContext = this.displayCanvas.getContext('2d')!;\n this.capturedStream = this.displayCanvas.captureStream();\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n } else {\n // Use MediaStreamTrackProcessor API\n this.processor = new MediaStreamTrackProcessor({ track: this.source });\n this.trackGenerator = new MediaStreamTrackGenerator({\n kind: 'video',\n signalTarget: this.source,\n });\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n }\n }\n\n async init(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.setup(opts);\n\n if (!this.canvas) {\n throw new TypeError('Expected canvas to be defined after setup');\n }\n\n await this.transformer.init({\n outputCanvas: this.canvas,\n inputElement: this.sourceDummy as HTMLVideoElement,\n });\n\n if (this.useStreamFallback) {\n this.initFallbackPath();\n } else {\n this.initStreamProcessorPath();\n }\n }\n\n private initStreamProcessorPath() {\n if (!this.processor || !this.trackGenerator) {\n throw new TypeError(\n 'Expected processor and trackGenerator to be defined for stream processor path',\n );\n }\n\n const readableStream = this.processor.readable;\n const pipedStream = readableStream.pipeThrough(this.transformer!.transformer!);\n\n pipedStream\n .pipeTo(this.trackGenerator.writable)\n .catch((e) => console.error('error when trying to pipe', e))\n .finally(() => this.destroy());\n\n this.processedTrack = this.trackGenerator as MediaStreamVideoTrack;\n }\n\n private initFallbackPath() {\n if (!this.capturedStream || !this.source || !this.canvas || !this.renderContext) {\n throw new TypeError('Missing required components for fallback implementation');\n }\n\n this.processedTrack = this.capturedStream.getVideoTracks()[0];\n this.processingEnabled = true;\n\n // Set up the frame callback for the transformer\n this.frameCallback = (frame: VideoFrame) => {\n if (!this.processingEnabled || !frame) {\n frame.close();\n return;\n }\n\n const controller = {\n enqueue: (processedFrame: VideoFrame) => {\n if (this.renderContext && this.displayCanvas) {\n // Draw the processed frame to the visible canvas\n this.renderContext.drawImage(\n processedFrame,\n 0,\n 0,\n this.displayCanvas.width,\n this.displayCanvas.height,\n );\n processedFrame.close();\n }\n },\n } as TransformStreamDefaultController<VideoFrame>;\n\n try {\n // Pass the frame through our transformer\n // @ts-ignore - The controller expects both VideoFrame & AudioData but we're only using VideoFrame\n this.transformer.transform(frame, controller);\n } catch (e) {\n console.error('Error in transform:', e);\n frame.close();\n }\n };\n\n // Start the rendering loop\n this.startRenderLoop();\n }\n\n private startRenderLoop() {\n if (!this.sourceDummy || !(this.sourceDummy instanceof HTMLVideoElement)) {\n return;\n }\n\n // Store the last processed timestamp to avoid duplicate processing\n let lastVideoTimestamp = -1;\n let lastFrameTime = 0;\n const videoElement = this.sourceDummy as HTMLVideoElement;\n const minFrameInterval = 1000 / this.maxFps; // Minimum time between frames\n\n // Estimate the video's native frame rate\n let estimatedVideoFps = this.maxFps;\n let frameTimeHistory: number[] = [];\n let lastVideoTimeChange = 0;\n let frameCount = 0;\n let lastFpsLog = 0;\n\n const renderLoop = () => {\n if (\n !this.processingEnabled ||\n !this.sourceDummy ||\n !(this.sourceDummy instanceof HTMLVideoElement)\n ) {\n return;\n }\n\n if (this.sourceDummy.paused) {\n console.warn('Video is paused, trying to play');\n this.sourceDummy.play();\n return;\n }\n\n // Only process a new frame if the video has actually updated\n const videoTime = videoElement.currentTime;\n const now = performance.now();\n const timeSinceLastFrame = now - lastFrameTime;\n\n // Detect if video has a new frame\n const hasNewFrame = videoTime !== lastVideoTimestamp;\n\n // Update frame rate estimation if we have a new frame\n if (hasNewFrame) {\n if (lastVideoTimeChange > 0) {\n const timeBetweenFrames = now - lastVideoTimeChange;\n frameTimeHistory.push(timeBetweenFrames);\n\n // Keep a rolling window of the last 10 frame times\n if (frameTimeHistory.length > 10) {\n frameTimeHistory.shift();\n }\n\n // Calculate average frame interval\n if (frameTimeHistory.length > 2) {\n const avgFrameTime =\n frameTimeHistory.reduce((sum, time) => sum + time, 0) / frameTimeHistory.length;\n estimatedVideoFps = 1000 / avgFrameTime;\n\n // Log estimated FPS every 5 seconds in development environments\n // Use a simpler check that works in browsers without process.env\n const isDevelopment =\n (typeof window !== 'undefined' && window.location.hostname === 'localhost') ||\n window.location.hostname === '127.0.0.1';\n\n if (isDevelopment && now - lastFpsLog > 5000) {\n console.debug(\n `[${this.name}] Estimated video FPS: ${estimatedVideoFps.toFixed(\n 1,\n )}, Processing at: ${(frameCount / 5).toFixed(1)} FPS`,\n );\n frameCount = 0;\n lastFpsLog = now;\n }\n }\n }\n lastVideoTimeChange = now;\n }\n\n // Determine if we should process this frame\n // We'll process if:\n // 1. The video has a new frame\n // 2. Enough time has passed since last frame (respecting maxFps)\n const timeThresholdMet = timeSinceLastFrame >= minFrameInterval;\n\n if (hasNewFrame && timeThresholdMet) {\n lastVideoTimestamp = videoTime;\n lastFrameTime = now;\n frameCount++;\n\n try {\n // Create a VideoFrame from the video element\n if (videoElement.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {\n const frame = new VideoFrame(videoElement);\n if (this.frameCallback) {\n this.frameCallback(frame);\n } else {\n frame.close();\n }\n }\n } catch (e) {\n console.error('Error in render loop:', e);\n }\n }\n this.animationFrameId = requestAnimationFrame(renderLoop);\n };\n\n this.animationFrameId = requestAnimationFrame(renderLoop);\n }\n\n async restart(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.destroy();\n await this.init(opts);\n }\n\n async restartTransformer(...options: Parameters<(typeof this.transformer)['restart']>) {\n // @ts-ignore unclear why the restart method only accepts VideoTransformerInitOptions instead of either those or AudioTransformerInitOptions\n await this.transformer.restart(options[0]);\n }\n\n async updateTransformerOptions(...options: Parameters<(typeof this.transformer)['update']>) {\n await this.transformer.update(options[0]);\n }\n\n async destroy() {\n if (this.useStreamFallback) {\n this.processingEnabled = false;\n if (this.animationFrameId) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = undefined;\n }\n if (this.displayCanvas && this.displayCanvas.parentNode) {\n this.displayCanvas.parentNode.removeChild(this.displayCanvas);\n }\n this.capturedStream?.getTracks().forEach((track) => track.stop());\n } else {\n await this.processor?.writableControl?.close();\n this.trackGenerator?.stop();\n }\n await this.transformer.destroy();\n }\n}\n","import * as vision from '@mediapipe/tasks-vision';\nimport { dependencies } from '../../package.json';\nimport VideoTransformer from './VideoTransformer';\nimport { VideoTransformerInitOptions } from './types';\n\nexport type SegmenterOptions = Partial<vision.ImageSegmenterOptions['baseOptions']>;\n\nexport interface FrameProcessingStats {\n processingTimeMs: number;\n segmentationTimeMs: number;\n filterTimeMs: number;\n}\n\nexport type BackgroundOptions = {\n blurRadius?: number;\n imagePath?: string;\n /** cannot be updated through the `update` method, needs a restart */\n segmenterOptions?: SegmenterOptions;\n /** cannot be updated through the `update` method, needs a restart */\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n /** called when a new frame is processed */\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n};\n\nexport default class BackgroundProcessor extends VideoTransformer<BackgroundOptions> {\n static get isSupported() {\n return (\n typeof OffscreenCanvas !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n typeof createImageBitmap !== 'undefined' &&\n !!document.createElement('canvas').getContext('webgl2')\n );\n }\n\n imageSegmenter?: vision.ImageSegmenter;\n\n segmentationResults: vision.ImageSegmenterResult | undefined;\n\n backgroundImage: ImageBitmap | null = null;\n\n options: BackgroundOptions;\n\n constructor(opts: BackgroundOptions) {\n super();\n this.options = opts;\n this.update(opts);\n }\n\n async init({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n // Initialize WebGL with appropriate options based on our current state\n\n await super.init({ outputCanvas, inputElement: inputVideo });\n\n const fileSet = await vision.FilesetResolver.forVisionTasks(\n this.options.assetPaths?.tasksVisionFileSet ??\n `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${dependencies['@mediapipe/tasks-vision']}/wasm`,\n );\n\n this.imageSegmenter = await vision.ImageSegmenter.createFromOptions(fileSet, {\n baseOptions: {\n modelAssetPath:\n this.options.assetPaths?.modelAssetPath ??\n 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/latest/selfie_segmenter.tflite',\n delegate: 'GPU',\n ...this.options.segmenterOptions,\n },\n canvas: this.canvas,\n runningMode: 'VIDEO',\n outputCategoryMask: true,\n outputConfidenceMasks: false,\n });\n\n // Skip loading the image here if update already loaded the image below\n if (this.options?.imagePath && !this.backgroundImage) {\n await this.loadBackground(this.options.imagePath).catch((err) =>\n console.error('Error while loading processor background image: ', err),\n );\n }\n if (this.options.blurRadius) {\n this.gl?.setBlurRadius(this.options.blurRadius);\n }\n }\n\n async destroy() {\n await super.destroy();\n await this.imageSegmenter?.close();\n this.backgroundImage = null;\n }\n\n async loadBackground(path: string) {\n const img = new Image();\n\n await new Promise((resolve, reject) => {\n img.crossOrigin = 'Anonymous';\n img.onload = () => resolve(img);\n img.onerror = (err) => reject(err);\n img.src = path;\n });\n const imageData = await createImageBitmap(img);\n this.gl?.setBackgroundImage(imageData);\n }\n\n async transform(frame: VideoFrame, controller: TransformStreamDefaultController<VideoFrame>) {\n try {\n if (!(frame instanceof VideoFrame) || frame.codedWidth === 0 || frame.codedHeight === 0) {\n console.debug('empty frame detected, ignoring');\n return;\n }\n\n if (this.isDisabled) {\n controller.enqueue(frame);\n return;\n }\n if (!this.canvas) {\n throw TypeError('Canvas needs to be initialized first');\n }\n this.canvas.width = frame.displayWidth;\n this.canvas.height = frame.displayHeight;\n let startTimeMs = performance.now();\n\n this.imageSegmenter?.segmentForVideo(frame, startTimeMs, (result) => {\n const segmentationTimeMs = performance.now() - startTimeMs;\n this.segmentationResults = result;\n this.drawFrame(frame);\n if (this.canvas && this.canvas.width > 0 && this.canvas.height > 0) {\n const newFrame = new VideoFrame(this.canvas, {\n timestamp: frame.timestamp || Date.now(),\n });\n const filterTimeMs = performance.now() - startTimeMs - segmentationTimeMs;\n const stats: FrameProcessingStats = {\n processingTimeMs: performance.now() - startTimeMs,\n segmentationTimeMs,\n filterTimeMs,\n };\n this.options.onFrameProcessed?.(stats);\n\n controller.enqueue(newFrame);\n } else {\n controller.enqueue(frame);\n }\n frame.close();\n });\n } catch (e) {\n console.error('Error while processing frame: ', e);\n frame?.close();\n }\n }\n\n async update(opts: BackgroundOptions) {\n this.options = { ...this.options, ...opts };\n if (opts.blurRadius) {\n this.gl?.setBlurRadius(opts.blurRadius);\n } else if (opts.imagePath) {\n await this.loadBackground(opts.imagePath);\n }\n }\n\n async drawFrame(frame: VideoFrame) {\n if (!this.canvas || !this.gl || !this.segmentationResults || !this.inputVideo) return;\n\n const mask = this.segmentationResults.categoryMask;\n if (mask) {\n this.gl.render(frame, mask);\n }\n }\n}\n","{\n \"name\": \"@livekit/track-processors\",\n \"version\": \"0.5.2\",\n \"description\": \"LiveKit track processors\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"source\": \"src/index.ts\",\n \"types\": \"dist/src/index.d.ts\",\n \"repository\": \"git@github.com:livekit/livekit-track-processors.git\",\n \"author\": \"Lukas Seiler\",\n \"license\": \"Apache-2.0\",\n \"scripts\": {\n \"build\": \"tsup --onSuccess \\\"tsc --declaration --emitDeclarationOnly\\\"\",\n \"build-sample\": \"cd example && vite build\",\n \"lint\": \"eslint src\",\n \"release\": \"pnpm build && changeset publish\",\n \"test\": \"jest\",\n \"sample\": \"vite serve example --port 8080 --open\"\n },\n \"files\": [\n \"dist\",\n \"src\"\n ],\n \"dependencies\": {\n \"@mediapipe/tasks-vision\": \"^0.10.22-rc.20250304\"\n },\n \"peerDependencies\": {\n \"livekit-client\": \"^1.12.0 || ^2.1.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.26.2\",\n \"@livekit/changesets-changelog-github\": \"^0.0.4\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.2.1\",\n \"@types/dom-mediacapture-transform\": \"^0.1.9\",\n \"@types/offscreencanvas\": \"^2019.7.3\",\n \"@typescript-eslint/eslint-plugin\": \"^5.62.0\",\n \"eslint\": \"8.39.0\",\n \"eslint-config-airbnb-typescript\": \"17.0.0\",\n \"eslint-config-prettier\": \"8.8.0\",\n \"eslint-plugin-ecmascript-compat\": \"^3.1.0\",\n \"eslint-plugin-import\": \"2.27.5\",\n \"prettier\": \"^2.8.8\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^4.5.0\"\n },\n \"packageManager\": \"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531\"\n}\n","import { MPMask } from '@mediapipe/tasks-vision';\n\n// Define the blur fragment shader\nconst blurFragmentShader = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D u_texture;\n uniform vec2 u_texelSize;\n uniform vec2 u_direction;\n uniform float u_radius;\n\n void main() {\n float sigma = u_radius;\n float twoSigmaSq = 2.0 * sigma * sigma;\n float totalWeight = 0.0;\n vec3 result = vec3(0.0);\n const int MAX_SAMPLES = 16;\n int radius = int(min(float(MAX_SAMPLES), ceil(u_radius)));\n\n for (int i = -MAX_SAMPLES; i <= MAX_SAMPLES; ++i) {\n float offset = float(i);\n if (abs(offset) > float(radius)) continue;\n float weight = exp(-(offset * offset) / twoSigmaSq);\n vec2 sampleCoord = texCoords + u_direction * u_texelSize * offset;\n result += texture2D(u_texture, sampleCoord).rgb * weight;\n totalWeight += weight;\n }\n\n gl_FragColor = vec4(result / totalWeight, 1.0);\n }\n`;\n\nconst createShaderProgram = (gl: WebGL2RenderingContext) => {\n const vs = `\n attribute vec2 position;\n varying vec2 texCoords;\n \n void main() {\n texCoords = (position + 1.0) / 2.0;\n texCoords.y = 1.0 - texCoords.y;\n gl_Position = vec4(position, 0, 1.0);\n }\n `;\n\n const cS = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D background;\n uniform sampler2D frame;\n uniform sampler2D mask;\n void main() {\n vec4 maskTex = texture2D(mask, texCoords); \n vec4 frameTex = texture2D(frame, texCoords);\n vec4 bgTex = texture2D(background, texCoords);\n \n \n float a = maskTex.r;\n \n gl_FragColor = mix(bgTex, vec4(frameTex.rgb, 1.0), 1.0 - a);\n \n }\n `;\n\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!vertexShader) {\n throw Error('can not create vertex shader');\n }\n gl.shaderSource(vertexShader, vs);\n gl.compileShader(vertexShader);\n\n // Create our fragment shader\n const compositeShader = gl.createShader(gl.FRAGMENT_SHADER);\n if (!compositeShader) {\n throw Error('can not create fragment shader');\n }\n gl.shaderSource(compositeShader, cS);\n gl.compileShader(compositeShader);\n\n // Create the composite program\n const compositeProgram = gl.createProgram();\n if (!compositeProgram) {\n throw Error('can not create composite program');\n }\n gl.attachShader(compositeProgram, vertexShader);\n gl.attachShader(compositeProgram, compositeShader);\n gl.linkProgram(compositeProgram);\n\n let blurProgram = null;\n let blurVertexShader = null;\n let blurFrag = null;\n let blurUniforms = null;\n\n // Create blur shader if enabled\n blurFrag = gl.createShader(gl.FRAGMENT_SHADER);\n if (!blurFrag) {\n throw Error('can not create blur shader');\n }\n gl.shaderSource(blurFrag, blurFragmentShader);\n gl.compileShader(blurFrag);\n\n // Get compile status and log errors if any\n if (!gl.getShaderParameter(blurFrag, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(blurFrag);\n throw Error(`Failed to compile blur shader: ${info}`);\n }\n\n // Create blur program\n blurVertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!blurVertexShader) {\n throw Error('can not create blur vertex shader');\n }\n gl.shaderSource(blurVertexShader, vs);\n gl.compileShader(blurVertexShader);\n\n blurProgram = gl.createProgram();\n if (!blurProgram) {\n throw Error('can not create blur program');\n }\n gl.attachShader(blurProgram, blurVertexShader);\n gl.attachShader(blurProgram, blurFrag);\n gl.linkProgram(blurProgram);\n\n // Check blur program link status\n if (!gl.getProgramParameter(blurProgram, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(blurProgram);\n throw Error(`Failed to link blur program: ${info}`);\n }\n\n blurUniforms = {\n position: gl.getAttribLocation(blurProgram, 'position'),\n texture: gl.getUniformLocation(blurProgram, 'u_texture'),\n texelSize: gl.getUniformLocation(blurProgram, 'u_texelSize'),\n direction: gl.getUniformLocation(blurProgram, 'u_direction'),\n radius: gl.getUniformLocation(blurProgram, 'u_radius'),\n };\n\n return {\n vertexShader,\n compositeShader,\n blurShader: blurFrag,\n compositeProgram,\n blurProgram,\n attribLocations: {\n position: gl.getAttribLocation(compositeProgram, 'position'),\n },\n uniformLocations: {\n mask: gl.getUniformLocation(compositeProgram, 'mask')!,\n frame: gl.getUniformLocation(compositeProgram, 'frame')!,\n background: gl.getUniformLocation(compositeProgram, 'background')!,\n },\n blurUniforms,\n };\n};\n\nexport function initTexture(gl: WebGL2RenderingContext, texIndex: number) {\n const texRef = gl.TEXTURE0 + texIndex;\n gl.activeTexture(texRef);\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n return texture;\n}\n\nexport function createFramebuffer(\n gl: WebGL2RenderingContext,\n texture: WebGLTexture,\n width: number,\n height: number,\n) {\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n\n // Set the texture as the color attachment\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n // Ensure texture dimensions match the provided width and height\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n // Check if framebuffer is complete\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer not complete');\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return framebuffer;\n}\n\nconst createVertexBuffer = (gl: WebGL2RenderingContext) => {\n if (!gl) {\n return null;\n }\n const vertexBuffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]),\n gl.STATIC_DRAW,\n );\n return vertexBuffer;\n};\n\nexport const setupWebGL = (canvas: OffscreenCanvas) => {\n const gl = canvas.getContext('webgl2', { premultipliedAlpha: false }) as WebGL2RenderingContext;\n\n let blurRadius: number | null = null;\n\n if (!gl) {\n return undefined;\n }\n\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n const {\n compositeProgram,\n blurProgram,\n attribLocations: { position: positionLocation },\n uniformLocations: {\n mask: maskTextureLocation,\n frame: frameTextureLocation,\n background: bgTextureLocation,\n },\n blurUniforms,\n } = createShaderProgram(gl);\n\n const bgTexture = initTexture(gl, 0);\n const frameTexture = initTexture(gl, 1);\n const vertexBuffer = createVertexBuffer(gl);\n\n // Create additional textures and framebuffers for processing\n let processTextures: WebGLTexture[] = [];\n let processFramebuffers: WebGLFramebuffer[] = [];\n\n // Create textures for processing (blur)\n processTextures.push(initTexture(gl, 3));\n processTextures.push(initTexture(gl, 4));\n\n // Create framebuffers for processing\n processFramebuffers.push(createFramebuffer(gl, processTextures[0], canvas.width, canvas.height));\n processFramebuffers.push(createFramebuffer(gl, processTextures[1], canvas.width, canvas.height));\n\n // Set up uniforms for the composite shader\n gl.useProgram(compositeProgram);\n gl.uniform1i(bgTextureLocation, 0);\n gl.uniform1i(frameTextureLocation, 1);\n gl.uniform1i(maskTextureLocation, 2);\n\n // Store custom background image\n let customBackgroundImage: ImageBitmap | null = null;\n\n function applyBlur(sourceTexture: WebGLTexture, width: number, height: number) {\n if (!blurRadius || !blurProgram || !blurUniforms) return bgTexture;\n\n gl.useProgram(blurProgram);\n\n // Set common attributes\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(blurUniforms.position, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(blurUniforms.position);\n\n const texelWidth = 1.0 / width;\n const texelHeight = 1.0 / height;\n\n // First pass - horizontal blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[0]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, sourceTexture);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.texelSize, texelWidth, texelHeight);\n gl.uniform2f(blurUniforms.direction, 1.0, 0.0); // Horizontal\n gl.uniform1f(blurUniforms.radius, blurRadius);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Second pass - vertical blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[1]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, processTextures[0]);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.direction, 0.0, 1.0); // Vertical\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Reset framebuffer\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n return processTextures[1];\n }\n\n function render(frame: VideoFrame, mask: MPMask) {\n if (frame.codedWidth === 0 || mask.width === 0) {\n return;\n }\n\n const width = frame.displayWidth;\n const height = frame.displayHeight;\n\n // Prepare frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);\n\n // Apply blur if enabled (and no custom background is set)\n let backgroundTexture = bgTexture;\n\n // If we have a custom background image, use that\n if (customBackgroundImage) {\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, customBackgroundImage);\n backgroundTexture = bgTexture;\n } else if (blurRadius) {\n // Otherwise, if blur is enabled, apply blur effect to the frame\n backgroundTexture = applyBlur(frameTexture, width, height);\n }\n\n // Get the mask texture\n const maskTexture = mask.getAsWebGLTexture();\n\n // Render the final composite\n gl.viewport(0, 0, width, height);\n gl.clearColor(1.0, 1.0, 1.0, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(compositeProgram);\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(positionLocation);\n\n // Set background texture (either original, blurred or custom)\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, backgroundTexture);\n gl.uniform1i(bgTextureLocation, 0);\n\n // Set frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.uniform1i(frameTextureLocation, 1);\n\n // Set mask texture\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, maskTexture);\n gl.uniform1i(maskTextureLocation, 2);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n mask.close();\n }\n\n /**\n * Set or update the background image\n * @param image The background image to use, or null to clear\n */\n async function setBackgroundImage(image: ImageBitmap | null) {\n // Clear existing background\n customBackgroundImage = null;\n\n if (image) {\n try {\n // Get current canvas dimensions\n const canvasWidth = canvas.width;\n const canvasHeight = canvas.height;\n\n // Calculate dimensions and crop for \"cover\" mode\n const imgAspect = image.width / image.height;\n const canvasAspect = canvasWidth / canvasHeight;\n\n let sx = 0;\n let sy = 0;\n let sWidth = image.width;\n let sHeight = image.height;\n\n // For cover mode, we need to crop some parts of the image\n // to ensure it covers the canvas while maintaining aspect ratio\n if (imgAspect > canvasAspect) {\n // Image is wider than canvas - crop the sides\n sWidth = Math.round(image.height * canvasAspect);\n sx = Math.round((image.width - sWidth) / 2); // Center the crop horizontally\n } else if (imgAspect < canvasAspect) {\n // Image is taller than canvas - crop the top/bottom\n sHeight = Math.round(image.width / canvasAspect);\n sy = Math.round((image.height - sHeight) / 2); // Center the crop vertically\n }\n\n // Create a new ImageBitmap with the cropped portion\n const croppedImage = await createImageBitmap(image, sx, sy, sWidth, sHeight, {\n resizeWidth: canvasWidth,\n resizeHeight: canvasHeight,\n resizeQuality: 'medium',\n });\n\n // Store the cropped and resized image\n customBackgroundImage = croppedImage;\n\n // Load the image into the texture\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, croppedImage);\n } catch (error) {\n console.error('Error processing background image:', error);\n // Fallback to original image on error\n customBackgroundImage = image;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n }\n } else {\n // set the background texture to an empty 2x2 image\n const emptyImage = new ImageData(2, 2);\n emptyImage.data[0] = 0;\n emptyImage.data[1] = 0;\n emptyImage.data[2] = 0;\n emptyImage.data[3] = 0;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, emptyImage);\n }\n }\n\n function setBlurRadius(radius: number | null) {\n blurRadius = radius;\n setBackgroundImage(null);\n }\n\n function cleanup() {\n gl.deleteProgram(compositeProgram);\n gl.deleteProgram(blurProgram);\n gl.deleteTexture(bgTexture);\n gl.deleteTexture(frameTexture);\n for (const texture of processTextures) {\n gl.deleteTexture(texture);\n }\n for (const framebuffer of processFramebuffers) {\n gl.deleteFramebuffer(framebuffer);\n }\n gl.deleteBuffer(vertexBuffer);\n\n // Release any ImageBitmap resources\n if (customBackgroundImage) {\n customBackgroundImage.close();\n customBackgroundImage = null;\n }\n processTextures = [];\n processFramebuffers = [];\n }\n\n return { render, setBackgroundImage, setBlurRadius, cleanup };\n};\n","import { setupWebGL } from '../webgl/index';\nimport { VideoTrackTransformer, VideoTransformerInitOptions } from './types';\n\nexport default abstract class VideoTransformer<Options extends Record<string, unknown>>\n implements VideoTrackTransformer<Options>\n{\n transformer?: TransformStream;\n\n canvas?: OffscreenCanvas;\n\n // ctx?: OffscreenCanvasRenderingContext2D;\n\n inputVideo?: HTMLVideoElement;\n\n gl?: ReturnType<typeof setupWebGL>;\n\n protected isDisabled?: Boolean = false;\n\n async init({\n outputCanvas,\n inputElement: inputVideo,\n }: VideoTransformerInitOptions): Promise<void> {\n if (!(inputVideo instanceof HTMLVideoElement)) {\n throw TypeError('Video transformer needs a HTMLVideoElement as input');\n }\n\n this.transformer = new TransformStream({\n transform: (frame, controller) => this.transform(frame, controller),\n });\n this.canvas = outputCanvas || null;\n if (outputCanvas) {\n // this.ctx = this.canvas?.getContext('2d') || undefined;\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n }\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async restart({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n this.canvas = outputCanvas || null;\n this.gl?.cleanup();\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async destroy() {\n this.isDisabled = true;\n this.canvas = undefined;\n this.gl?.cleanup();\n this.gl = undefined;\n }\n\n abstract transform(\n frame: VideoFrame,\n controller: TransformStreamDefaultController<VideoFrame>,\n ): void;\n\n abstract update(options: Options): void;\n}\n","import ProcessorWrapper, { ProcessorWrapperOptions } from './ProcessorWrapper';\nimport BackgroundTransformer, {\n BackgroundOptions,\n FrameProcessingStats,\n SegmenterOptions,\n} from './transformers/BackgroundTransformer';\n\nexport * from './transformers/types';\nexport { default as VideoTransformer } from './transformers/VideoTransformer';\nexport {\n ProcessorWrapper,\n type BackgroundOptions,\n type SegmenterOptions,\n BackgroundTransformer,\n type ProcessorWrapperOptions,\n};\n\n/**\n * Determines if the current browser supports background processors\n */\nexport const supportsBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.isSupported;\n\n/**\n * Determines if the current browser supports modern background processors, which yield better performance\n */\nexport const supportsModernBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.hasModernApiSupport;\n\nexport interface BackgroundProcessorOptions extends ProcessorWrapperOptions {\n blurRadius?: number;\n imagePath?: string;\n segmenterOptions?: SegmenterOptions;\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n}\n\nexport const BackgroundBlur = (\n blurRadius: number = 10,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n blurRadius,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'background-blur',\n );\n};\n\nexport const VirtualBackground = (\n imagePath: string,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n imagePath,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'virtual-background',\n );\n};\n\nexport const BackgroundProcessor = (\n options: BackgroundProcessorOptions,\n name = 'background-processor',\n) => {\n const isTransformerSupported = BackgroundTransformer.isSupported;\n const isProcessorSupported = ProcessorWrapper.isSupported;\n\n if (!isTransformerSupported) {\n throw new Error('Background transformer is not supported in this browser');\n }\n\n if (!isProcessorSupported) {\n throw new Error(\n 'Neither MediaStreamTrackProcessor nor canvas.captureStream() fallback is supported in this browser',\n );\n }\n\n // Extract transformer-specific options and processor options\n const {\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n ...processorOpts\n } = options;\n\n const processor = new ProcessorWrapper(\n new BackgroundTransformer({\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n }),\n name,\n processorOpts,\n );\n\n return processor;\n};\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/ProcessorWrapper.ts","../src/transformers/BackgroundTransformer.ts","../package.json","../src/webgl/index.ts","../src/transformers/VideoTransformer.ts","../src/index.ts"],"names":["_a","BackgroundProcessor"],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention */\nexport const supportsProcessor = typeof MediaStreamTrackGenerator !== 'undefined';\nexport const supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined';\n\nasync function sleep(time: number) {\n return new Promise((resolve) => setTimeout(resolve, time));\n}\n\nexport async function waitForTrackResolution(track: MediaStreamTrack) {\n const timeout = 500;\n\n // browsers report wrong initial resolution on iOS.\n // when slightly delaying the call to .getSettings(), the correct resolution is being reported\n await sleep(10);\n\n const started = Date.now();\n while (Date.now() - started < timeout) {\n const { width, height } = track.getSettings();\n if (width && height) {\n return { width, height };\n }\n await sleep(50);\n }\n return { width: undefined, height: undefined };\n}\n","import type { ProcessorOptions, Track, TrackProcessor } from 'livekit-client';\nimport { TrackTransformer } from './transformers';\nimport { waitForTrackResolution } from './utils';\n\nexport interface ProcessorWrapperOptions {\n /**\n * Maximum frame rate for fallback canvas.captureStream implementation\n * Default: 30\n */\n maxFps?: number;\n}\n\nexport default class ProcessorWrapper<TransformerOptions extends Record<string, unknown>>\n implements TrackProcessor<Track.Kind>\n{\n /**\n * Determines if the Processor is supported on the current browser\n */\n static get isSupported() {\n // Check for primary implementation support\n const hasStreamProcessor =\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined';\n\n // Check for fallback implementation support\n const hasFallbackSupport =\n typeof HTMLCanvasElement !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n 'captureStream' in HTMLCanvasElement.prototype;\n\n // We can work if either implementation is available\n return hasStreamProcessor || hasFallbackSupport;\n }\n\n /**\n * Determines if modern browser APIs are supported, which yield better performance\n */\n static get hasModernApiSupport() {\n return (\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined'\n );\n }\n\n name: string;\n\n source?: MediaStreamVideoTrack;\n\n processor?: MediaStreamTrackProcessor<VideoFrame>;\n\n trackGenerator?: MediaStreamTrackGenerator<VideoFrame>;\n\n canvas?: OffscreenCanvas;\n\n displayCanvas?: HTMLCanvasElement;\n\n sourceDummy?: HTMLMediaElement;\n\n processedTrack?: MediaStreamTrack;\n\n transformer: TrackTransformer<TransformerOptions>;\n\n // For tracking whether we're using the stream API fallback\n private useStreamFallback = false;\n\n // For fallback rendering with canvas.captureStream()\n private capturedStream?: MediaStream;\n\n private animationFrameId?: number;\n\n private renderContext?: CanvasRenderingContext2D;\n\n private frameCallback?: (frame: VideoFrame) => void;\n\n private processingEnabled = false;\n\n // FPS control for fallback implementation\n private maxFps: number;\n\n constructor(\n transformer: TrackTransformer<TransformerOptions>,\n name: string,\n options: ProcessorWrapperOptions = {},\n ) {\n this.name = name;\n this.transformer = transformer;\n this.maxFps = options.maxFps ?? 30;\n }\n\n private async setup(opts: ProcessorOptions<Track.Kind>) {\n this.source = opts.track as MediaStreamVideoTrack;\n\n const { width, height } = await waitForTrackResolution(this.source);\n this.sourceDummy = opts.element;\n\n if (!(this.sourceDummy instanceof HTMLVideoElement)) {\n throw TypeError('Currently only video transformers are supported');\n }\n\n if (this.sourceDummy instanceof HTMLVideoElement) {\n this.sourceDummy.height = height ?? 300;\n this.sourceDummy.width = width ?? 300;\n }\n\n this.useStreamFallback = !ProcessorWrapper.hasModernApiSupport;\n\n if (this.useStreamFallback) {\n // Create a visible canvas for the fallback implementation or use an existing one if provided\n const existingCanvas = document.querySelector(\n 'canvas[data-livekit-processor=\"' + this.name + '\"]',\n ) as HTMLCanvasElement;\n\n if (existingCanvas) {\n this.displayCanvas = existingCanvas;\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n } else {\n this.displayCanvas = document.createElement('canvas');\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n this.displayCanvas.style.display = 'none';\n this.displayCanvas.dataset.livekitProcessor = this.name;\n document.body.appendChild(this.displayCanvas);\n }\n\n this.renderContext = this.displayCanvas.getContext('2d')!;\n this.capturedStream = this.displayCanvas.captureStream();\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n } else {\n // Use MediaStreamTrackProcessor API\n this.processor = new MediaStreamTrackProcessor({ track: this.source });\n this.trackGenerator = new MediaStreamTrackGenerator({\n kind: 'video',\n signalTarget: this.source,\n });\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n }\n }\n\n async init(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.setup(opts);\n\n if (!this.canvas) {\n throw new TypeError('Expected canvas to be defined after setup');\n }\n\n await this.transformer.init({\n outputCanvas: this.canvas,\n inputElement: this.sourceDummy as HTMLVideoElement,\n });\n\n if (this.useStreamFallback) {\n this.initFallbackPath();\n } else {\n this.initStreamProcessorPath();\n }\n }\n\n private initStreamProcessorPath() {\n if (!this.processor || !this.trackGenerator) {\n throw new TypeError(\n 'Expected processor and trackGenerator to be defined for stream processor path',\n );\n }\n\n const readableStream = this.processor.readable;\n const pipedStream = readableStream.pipeThrough(this.transformer!.transformer!);\n\n pipedStream\n .pipeTo(this.trackGenerator.writable)\n .catch((e) => console.error('error when trying to pipe', e))\n .finally(() => this.destroy());\n\n this.processedTrack = this.trackGenerator as MediaStreamVideoTrack;\n }\n\n private initFallbackPath() {\n if (!this.capturedStream || !this.source || !this.canvas || !this.renderContext) {\n throw new TypeError('Missing required components for fallback implementation');\n }\n\n this.processedTrack = this.capturedStream.getVideoTracks()[0];\n this.processingEnabled = true;\n\n // Set up the frame callback for the transformer\n this.frameCallback = (frame: VideoFrame) => {\n if (!this.processingEnabled || !frame) {\n frame.close();\n return;\n }\n\n const controller = {\n enqueue: (processedFrame: VideoFrame) => {\n if (this.renderContext && this.displayCanvas) {\n // Draw the processed frame to the visible canvas\n this.renderContext.drawImage(\n processedFrame,\n 0,\n 0,\n this.displayCanvas.width,\n this.displayCanvas.height,\n );\n processedFrame.close();\n }\n },\n } as TransformStreamDefaultController<VideoFrame>;\n\n try {\n // Pass the frame through our transformer\n // @ts-ignore - The controller expects both VideoFrame & AudioData but we're only using VideoFrame\n this.transformer.transform(frame, controller);\n } catch (e) {\n console.error('Error in transform:', e);\n frame.close();\n }\n };\n\n // Start the rendering loop\n this.startRenderLoop();\n }\n\n private startRenderLoop() {\n if (!this.sourceDummy || !(this.sourceDummy instanceof HTMLVideoElement)) {\n return;\n }\n\n // Store the last processed timestamp to avoid duplicate processing\n let lastVideoTimestamp = -1;\n let lastFrameTime = 0;\n const videoElement = this.sourceDummy as HTMLVideoElement;\n const minFrameInterval = 1000 / this.maxFps; // Minimum time between frames\n\n // Estimate the video's native frame rate\n let estimatedVideoFps = this.maxFps;\n let frameTimeHistory: number[] = [];\n let lastVideoTimeChange = 0;\n let frameCount = 0;\n let lastFpsLog = 0;\n\n const renderLoop = () => {\n if (\n !this.processingEnabled ||\n !this.sourceDummy ||\n !(this.sourceDummy instanceof HTMLVideoElement)\n ) {\n return;\n }\n\n if (this.sourceDummy.paused) {\n console.warn('Video is paused, trying to play');\n this.sourceDummy.play();\n return;\n }\n\n // Only process a new frame if the video has actually updated\n const videoTime = videoElement.currentTime;\n const now = performance.now();\n const timeSinceLastFrame = now - lastFrameTime;\n\n // Detect if video has a new frame\n const hasNewFrame = videoTime !== lastVideoTimestamp;\n\n // Update frame rate estimation if we have a new frame\n if (hasNewFrame) {\n if (lastVideoTimeChange > 0) {\n const timeBetweenFrames = now - lastVideoTimeChange;\n frameTimeHistory.push(timeBetweenFrames);\n\n // Keep a rolling window of the last 10 frame times\n if (frameTimeHistory.length > 10) {\n frameTimeHistory.shift();\n }\n\n // Calculate average frame interval\n if (frameTimeHistory.length > 2) {\n const avgFrameTime =\n frameTimeHistory.reduce((sum, time) => sum + time, 0) / frameTimeHistory.length;\n estimatedVideoFps = 1000 / avgFrameTime;\n\n // Log estimated FPS every 5 seconds in development environments\n // Use a simpler check that works in browsers without process.env\n const isDevelopment =\n (typeof window !== 'undefined' && window.location.hostname === 'localhost') ||\n window.location.hostname === '127.0.0.1';\n\n if (isDevelopment && now - lastFpsLog > 5000) {\n console.debug(\n `[${this.name}] Estimated video FPS: ${estimatedVideoFps.toFixed(\n 1,\n )}, Processing at: ${(frameCount / 5).toFixed(1)} FPS`,\n );\n frameCount = 0;\n lastFpsLog = now;\n }\n }\n }\n lastVideoTimeChange = now;\n }\n\n // Determine if we should process this frame\n // We'll process if:\n // 1. The video has a new frame\n // 2. Enough time has passed since last frame (respecting maxFps)\n const timeThresholdMet = timeSinceLastFrame >= minFrameInterval;\n\n if (hasNewFrame && timeThresholdMet) {\n lastVideoTimestamp = videoTime;\n lastFrameTime = now;\n frameCount++;\n\n try {\n // Create a VideoFrame from the video element\n if (videoElement.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {\n const frame = new VideoFrame(videoElement);\n if (this.frameCallback) {\n this.frameCallback(frame);\n } else {\n frame.close();\n }\n }\n } catch (e) {\n console.error('Error in render loop:', e);\n }\n }\n this.animationFrameId = requestAnimationFrame(renderLoop);\n };\n\n this.animationFrameId = requestAnimationFrame(renderLoop);\n }\n\n async restart(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.destroy();\n await this.init(opts);\n }\n\n async restartTransformer(...options: Parameters<(typeof this.transformer)['restart']>) {\n // @ts-ignore unclear why the restart method only accepts VideoTransformerInitOptions instead of either those or AudioTransformerInitOptions\n await this.transformer.restart(options[0]);\n }\n\n async updateTransformerOptions(...options: Parameters<(typeof this.transformer)['update']>) {\n await this.transformer.update(options[0]);\n }\n\n async destroy() {\n if (this.useStreamFallback) {\n this.processingEnabled = false;\n if (this.animationFrameId) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = undefined;\n }\n if (this.displayCanvas && this.displayCanvas.parentNode) {\n this.displayCanvas.parentNode.removeChild(this.displayCanvas);\n }\n this.capturedStream?.getTracks().forEach((track) => track.stop());\n } else {\n await this.processor?.writableControl?.close();\n this.trackGenerator?.stop();\n }\n await this.transformer.destroy();\n }\n}\n","import * as vision from '@mediapipe/tasks-vision';\nimport { dependencies } from '../../package.json';\nimport VideoTransformer from './VideoTransformer';\nimport { VideoTransformerInitOptions } from './types';\n\nexport type SegmenterOptions = Partial<vision.ImageSegmenterOptions['baseOptions']>;\n\nexport interface FrameProcessingStats {\n processingTimeMs: number;\n segmentationTimeMs: number;\n filterTimeMs: number;\n}\n\nexport type BackgroundOptions = {\n blurRadius?: number;\n imagePath?: string;\n /** cannot be updated through the `update` method, needs a restart */\n segmenterOptions?: SegmenterOptions;\n /** cannot be updated through the `update` method, needs a restart */\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n /** called when a new frame is processed */\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n};\n\nexport default class BackgroundProcessor extends VideoTransformer<BackgroundOptions> {\n static get isSupported() {\n return (\n typeof OffscreenCanvas !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n typeof createImageBitmap !== 'undefined' &&\n !!document.createElement('canvas').getContext('webgl2')\n );\n }\n\n imageSegmenter?: vision.ImageSegmenter;\n\n segmentationResults: vision.ImageSegmenterResult | undefined;\n\n backgroundImage: ImageBitmap | null = null;\n\n options: BackgroundOptions;\n\n constructor(opts: BackgroundOptions) {\n super();\n this.options = opts;\n this.update(opts);\n }\n\n async init({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n // Initialize WebGL with appropriate options based on our current state\n\n await super.init({ outputCanvas, inputElement: inputVideo });\n\n const fileSet = await vision.FilesetResolver.forVisionTasks(\n this.options.assetPaths?.tasksVisionFileSet ??\n `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${dependencies['@mediapipe/tasks-vision']}/wasm`,\n );\n\n this.imageSegmenter = await vision.ImageSegmenter.createFromOptions(fileSet, {\n baseOptions: {\n modelAssetPath:\n this.options.assetPaths?.modelAssetPath ??\n 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/latest/selfie_segmenter.tflite',\n delegate: 'GPU',\n ...this.options.segmenterOptions,\n },\n canvas: this.canvas,\n runningMode: 'VIDEO',\n outputCategoryMask: true,\n outputConfidenceMasks: false,\n });\n\n // Skip loading the image here if update already loaded the image below\n if (this.options?.imagePath && !this.backgroundImage) {\n await this.loadBackground(this.options.imagePath).catch((err) =>\n console.error('Error while loading processor background image: ', err),\n );\n }\n if (this.options.blurRadius) {\n this.gl?.setBlurRadius(this.options.blurRadius);\n }\n }\n\n async destroy() {\n await super.destroy();\n await this.imageSegmenter?.close();\n this.backgroundImage = null;\n }\n\n async loadBackground(path: string) {\n const img = new Image();\n\n await new Promise((resolve, reject) => {\n img.crossOrigin = 'Anonymous';\n img.onload = () => resolve(img);\n img.onerror = (err) => reject(err);\n img.src = path;\n });\n const imageData = await createImageBitmap(img);\n this.gl?.setBackgroundImage(imageData);\n }\n\n async transform(frame: VideoFrame, controller: TransformStreamDefaultController<VideoFrame>) {\n try {\n if (!(frame instanceof VideoFrame) || frame.codedWidth === 0 || frame.codedHeight === 0) {\n console.debug('empty frame detected, ignoring');\n return;\n }\n\n if (this.isDisabled) {\n controller.enqueue(frame);\n return;\n }\n if (!this.canvas) {\n throw TypeError('Canvas needs to be initialized first');\n }\n this.canvas.width = frame.displayWidth;\n this.canvas.height = frame.displayHeight;\n let startTimeMs = performance.now();\n\n this.imageSegmenter?.segmentForVideo(frame, startTimeMs, (result) => {\n const segmentationTimeMs = performance.now() - startTimeMs;\n this.segmentationResults = result;\n this.drawFrame(frame);\n if (this.canvas && this.canvas.width > 0 && this.canvas.height > 0) {\n const newFrame = new VideoFrame(this.canvas, {\n timestamp: frame.timestamp || Date.now(),\n });\n const filterTimeMs = performance.now() - startTimeMs - segmentationTimeMs;\n const stats: FrameProcessingStats = {\n processingTimeMs: performance.now() - startTimeMs,\n segmentationTimeMs,\n filterTimeMs,\n };\n this.options.onFrameProcessed?.(stats);\n\n controller.enqueue(newFrame);\n } else {\n controller.enqueue(frame);\n }\n frame.close();\n });\n } catch (e) {\n console.error('Error while processing frame: ', e);\n frame?.close();\n }\n }\n\n async update(opts: BackgroundOptions) {\n this.options = { ...this.options, ...opts };\n if (opts.blurRadius) {\n this.gl?.setBlurRadius(opts.blurRadius);\n } else if (opts.imagePath) {\n await this.loadBackground(opts.imagePath);\n }\n }\n\n async drawFrame(frame: VideoFrame) {\n if (!this.canvas || !this.gl || !this.segmentationResults || !this.inputVideo) return;\n\n const mask = this.segmentationResults.categoryMask;\n if (mask) {\n this.gl.render(frame, mask);\n }\n }\n}\n","{\n \"name\": \"@livekit/track-processors\",\n \"version\": \"0.5.3\",\n \"description\": \"LiveKit track processors\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"source\": \"src/index.ts\",\n \"types\": \"dist/src/index.d.ts\",\n \"repository\": \"git@github.com:livekit/livekit-track-processors.git\",\n \"author\": \"Lukas Seiler\",\n \"license\": \"Apache-2.0\",\n \"scripts\": {\n \"build\": \"tsup --onSuccess \\\"tsc --declaration --emitDeclarationOnly\\\"\",\n \"build-sample\": \"cd example && vite build\",\n \"lint\": \"eslint src\",\n \"release\": \"pnpm build && changeset publish\",\n \"test\": \"jest\",\n \"sample\": \"vite serve example --port 8080 --open\"\n },\n \"files\": [\n \"dist\",\n \"src\"\n ],\n \"dependencies\": {\n \"@mediapipe/tasks-vision\": \"0.10.14\"\n },\n \"peerDependencies\": {\n \"livekit-client\": \"^1.12.0 || ^2.1.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.26.2\",\n \"@livekit/changesets-changelog-github\": \"^0.0.4\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.2.1\",\n \"@types/dom-mediacapture-transform\": \"^0.1.9\",\n \"@types/offscreencanvas\": \"^2019.7.3\",\n \"@typescript-eslint/eslint-plugin\": \"^5.62.0\",\n \"eslint\": \"8.39.0\",\n \"eslint-config-airbnb-typescript\": \"17.0.0\",\n \"eslint-config-prettier\": \"8.8.0\",\n \"eslint-plugin-ecmascript-compat\": \"^3.1.0\",\n \"eslint-plugin-import\": \"2.27.5\",\n \"prettier\": \"^2.8.8\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^4.5.0\"\n },\n \"packageManager\": \"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531\"\n}\n","import { MPMask } from '@mediapipe/tasks-vision';\n\n// Define the blur fragment shader\nconst blurFragmentShader = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D u_texture;\n uniform vec2 u_texelSize;\n uniform vec2 u_direction;\n uniform float u_radius;\n\n void main() {\n float sigma = u_radius;\n float twoSigmaSq = 2.0 * sigma * sigma;\n float totalWeight = 0.0;\n vec3 result = vec3(0.0);\n const int MAX_SAMPLES = 16;\n int radius = int(min(float(MAX_SAMPLES), ceil(u_radius)));\n\n for (int i = -MAX_SAMPLES; i <= MAX_SAMPLES; ++i) {\n float offset = float(i);\n if (abs(offset) > float(radius)) continue;\n float weight = exp(-(offset * offset) / twoSigmaSq);\n vec2 sampleCoord = texCoords + u_direction * u_texelSize * offset;\n result += texture2D(u_texture, sampleCoord).rgb * weight;\n totalWeight += weight;\n }\n\n gl_FragColor = vec4(result / totalWeight, 1.0);\n }\n`;\n\nconst createShaderProgram = (gl: WebGL2RenderingContext) => {\n const vs = `\n attribute vec2 position;\n varying vec2 texCoords;\n \n void main() {\n texCoords = (position + 1.0) / 2.0;\n texCoords.y = 1.0 - texCoords.y;\n gl_Position = vec4(position, 0, 1.0);\n }\n `;\n\n const cS = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D background;\n uniform sampler2D frame;\n uniform sampler2D mask;\n void main() {\n vec4 maskTex = texture2D(mask, texCoords); \n vec4 frameTex = texture2D(frame, texCoords);\n vec4 bgTex = texture2D(background, texCoords);\n \n \n float a = maskTex.r;\n \n gl_FragColor = mix(bgTex, vec4(frameTex.rgb, 1.0), 1.0 - a);\n \n }\n `;\n\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!vertexShader) {\n throw Error('can not create vertex shader');\n }\n gl.shaderSource(vertexShader, vs);\n gl.compileShader(vertexShader);\n\n // Create our fragment shader\n const compositeShader = gl.createShader(gl.FRAGMENT_SHADER);\n if (!compositeShader) {\n throw Error('can not create fragment shader');\n }\n gl.shaderSource(compositeShader, cS);\n gl.compileShader(compositeShader);\n\n // Create the composite program\n const compositeProgram = gl.createProgram();\n if (!compositeProgram) {\n throw Error('can not create composite program');\n }\n gl.attachShader(compositeProgram, vertexShader);\n gl.attachShader(compositeProgram, compositeShader);\n gl.linkProgram(compositeProgram);\n\n let blurProgram = null;\n let blurVertexShader = null;\n let blurFrag = null;\n let blurUniforms = null;\n\n // Create blur shader if enabled\n blurFrag = gl.createShader(gl.FRAGMENT_SHADER);\n if (!blurFrag) {\n throw Error('can not create blur shader');\n }\n gl.shaderSource(blurFrag, blurFragmentShader);\n gl.compileShader(blurFrag);\n\n // Get compile status and log errors if any\n if (!gl.getShaderParameter(blurFrag, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(blurFrag);\n throw Error(`Failed to compile blur shader: ${info}`);\n }\n\n // Create blur program\n blurVertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!blurVertexShader) {\n throw Error('can not create blur vertex shader');\n }\n gl.shaderSource(blurVertexShader, vs);\n gl.compileShader(blurVertexShader);\n\n blurProgram = gl.createProgram();\n if (!blurProgram) {\n throw Error('can not create blur program');\n }\n gl.attachShader(blurProgram, blurVertexShader);\n gl.attachShader(blurProgram, blurFrag);\n gl.linkProgram(blurProgram);\n\n // Check blur program link status\n if (!gl.getProgramParameter(blurProgram, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(blurProgram);\n throw Error(`Failed to link blur program: ${info}`);\n }\n\n blurUniforms = {\n position: gl.getAttribLocation(blurProgram, 'position'),\n texture: gl.getUniformLocation(blurProgram, 'u_texture'),\n texelSize: gl.getUniformLocation(blurProgram, 'u_texelSize'),\n direction: gl.getUniformLocation(blurProgram, 'u_direction'),\n radius: gl.getUniformLocation(blurProgram, 'u_radius'),\n };\n\n return {\n vertexShader,\n compositeShader,\n blurShader: blurFrag,\n compositeProgram,\n blurProgram,\n attribLocations: {\n position: gl.getAttribLocation(compositeProgram, 'position'),\n },\n uniformLocations: {\n mask: gl.getUniformLocation(compositeProgram, 'mask')!,\n frame: gl.getUniformLocation(compositeProgram, 'frame')!,\n background: gl.getUniformLocation(compositeProgram, 'background')!,\n },\n blurUniforms,\n };\n};\n\nexport function initTexture(gl: WebGL2RenderingContext, texIndex: number) {\n const texRef = gl.TEXTURE0 + texIndex;\n gl.activeTexture(texRef);\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n return texture;\n}\n\nexport function createFramebuffer(\n gl: WebGL2RenderingContext,\n texture: WebGLTexture,\n width: number,\n height: number,\n) {\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n\n // Set the texture as the color attachment\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n // Ensure texture dimensions match the provided width and height\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n // Check if framebuffer is complete\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer not complete');\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return framebuffer;\n}\n\nconst createVertexBuffer = (gl: WebGL2RenderingContext) => {\n if (!gl) {\n return null;\n }\n const vertexBuffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]),\n gl.STATIC_DRAW,\n );\n return vertexBuffer;\n};\n\nexport const setupWebGL = (canvas: OffscreenCanvas) => {\n const gl = canvas.getContext('webgl2', { premultipliedAlpha: false }) as WebGL2RenderingContext;\n\n let blurRadius: number | null = null;\n\n if (!gl) {\n return undefined;\n }\n\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n const {\n compositeProgram,\n blurProgram,\n attribLocations: { position: positionLocation },\n uniformLocations: {\n mask: maskTextureLocation,\n frame: frameTextureLocation,\n background: bgTextureLocation,\n },\n blurUniforms,\n } = createShaderProgram(gl);\n\n const bgTexture = initTexture(gl, 0);\n const frameTexture = initTexture(gl, 1);\n const vertexBuffer = createVertexBuffer(gl);\n\n // Create additional textures and framebuffers for processing\n let processTextures: WebGLTexture[] = [];\n let processFramebuffers: WebGLFramebuffer[] = [];\n\n // Create textures for processing (blur)\n processTextures.push(initTexture(gl, 3));\n processTextures.push(initTexture(gl, 4));\n\n // Create framebuffers for processing\n processFramebuffers.push(createFramebuffer(gl, processTextures[0], canvas.width, canvas.height));\n processFramebuffers.push(createFramebuffer(gl, processTextures[1], canvas.width, canvas.height));\n\n // Set up uniforms for the composite shader\n gl.useProgram(compositeProgram);\n gl.uniform1i(bgTextureLocation, 0);\n gl.uniform1i(frameTextureLocation, 1);\n gl.uniform1i(maskTextureLocation, 2);\n\n // Store custom background image\n let customBackgroundImage: ImageBitmap | null = null;\n\n function applyBlur(sourceTexture: WebGLTexture, width: number, height: number) {\n if (!blurRadius || !blurProgram || !blurUniforms) return bgTexture;\n\n gl.useProgram(blurProgram);\n\n // Set common attributes\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(blurUniforms.position, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(blurUniforms.position);\n\n const texelWidth = 1.0 / width;\n const texelHeight = 1.0 / height;\n\n // First pass - horizontal blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[0]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, sourceTexture);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.texelSize, texelWidth, texelHeight);\n gl.uniform2f(blurUniforms.direction, 1.0, 0.0); // Horizontal\n gl.uniform1f(blurUniforms.radius, blurRadius);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Second pass - vertical blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[1]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, processTextures[0]);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.direction, 0.0, 1.0); // Vertical\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Reset framebuffer\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n return processTextures[1];\n }\n\n function render(frame: VideoFrame, mask: MPMask) {\n if (frame.codedWidth === 0 || mask.width === 0) {\n return;\n }\n\n const width = frame.displayWidth;\n const height = frame.displayHeight;\n\n // Prepare frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);\n\n // Apply blur if enabled (and no custom background is set)\n let backgroundTexture = bgTexture;\n\n // If we have a custom background image, use that\n if (customBackgroundImage) {\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, customBackgroundImage);\n backgroundTexture = bgTexture;\n } else if (blurRadius) {\n // Otherwise, if blur is enabled, apply blur effect to the frame\n backgroundTexture = applyBlur(frameTexture, width, height);\n }\n\n // Get the mask texture\n const maskTexture = mask.getAsWebGLTexture();\n\n // Render the final composite\n gl.viewport(0, 0, width, height);\n gl.clearColor(1.0, 1.0, 1.0, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(compositeProgram);\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(positionLocation);\n\n // Set background texture (either original, blurred or custom)\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, backgroundTexture);\n gl.uniform1i(bgTextureLocation, 0);\n\n // Set frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.uniform1i(frameTextureLocation, 1);\n\n // Set mask texture\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, maskTexture);\n gl.uniform1i(maskTextureLocation, 2);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n mask.close();\n }\n\n /**\n * Set or update the background image\n * @param image The background image to use, or null to clear\n */\n async function setBackgroundImage(image: ImageBitmap | null) {\n // Clear existing background\n customBackgroundImage = null;\n\n if (image) {\n try {\n // Get current canvas dimensions\n const canvasWidth = canvas.width;\n const canvasHeight = canvas.height;\n\n // Calculate dimensions and crop for \"cover\" mode\n const imgAspect = image.width / image.height;\n const canvasAspect = canvasWidth / canvasHeight;\n\n let sx = 0;\n let sy = 0;\n let sWidth = image.width;\n let sHeight = image.height;\n\n // For cover mode, we need to crop some parts of the image\n // to ensure it covers the canvas while maintaining aspect ratio\n if (imgAspect > canvasAspect) {\n // Image is wider than canvas - crop the sides\n sWidth = Math.round(image.height * canvasAspect);\n sx = Math.round((image.width - sWidth) / 2); // Center the crop horizontally\n } else if (imgAspect < canvasAspect) {\n // Image is taller than canvas - crop the top/bottom\n sHeight = Math.round(image.width / canvasAspect);\n sy = Math.round((image.height - sHeight) / 2); // Center the crop vertically\n }\n\n // Create a new ImageBitmap with the cropped portion\n const croppedImage = await createImageBitmap(image, sx, sy, sWidth, sHeight, {\n resizeWidth: canvasWidth,\n resizeHeight: canvasHeight,\n resizeQuality: 'medium',\n });\n\n // Store the cropped and resized image\n customBackgroundImage = croppedImage;\n\n // Load the image into the texture\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, croppedImage);\n } catch (error) {\n console.error('Error processing background image:', error);\n // Fallback to original image on error\n customBackgroundImage = image;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n }\n } else {\n // set the background texture to an empty 2x2 image\n const emptyImage = new ImageData(2, 2);\n emptyImage.data[0] = 0;\n emptyImage.data[1] = 0;\n emptyImage.data[2] = 0;\n emptyImage.data[3] = 0;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, emptyImage);\n }\n }\n\n function setBlurRadius(radius: number | null) {\n blurRadius = radius;\n setBackgroundImage(null);\n }\n\n function cleanup() {\n gl.deleteProgram(compositeProgram);\n gl.deleteProgram(blurProgram);\n gl.deleteTexture(bgTexture);\n gl.deleteTexture(frameTexture);\n for (const texture of processTextures) {\n gl.deleteTexture(texture);\n }\n for (const framebuffer of processFramebuffers) {\n gl.deleteFramebuffer(framebuffer);\n }\n gl.deleteBuffer(vertexBuffer);\n\n // Release any ImageBitmap resources\n if (customBackgroundImage) {\n customBackgroundImage.close();\n customBackgroundImage = null;\n }\n processTextures = [];\n processFramebuffers = [];\n }\n\n return { render, setBackgroundImage, setBlurRadius, cleanup };\n};\n","import { setupWebGL } from '../webgl/index';\nimport { VideoTrackTransformer, VideoTransformerInitOptions } from './types';\n\nexport default abstract class VideoTransformer<Options extends Record<string, unknown>>\n implements VideoTrackTransformer<Options>\n{\n transformer?: TransformStream;\n\n canvas?: OffscreenCanvas;\n\n // ctx?: OffscreenCanvasRenderingContext2D;\n\n inputVideo?: HTMLVideoElement;\n\n gl?: ReturnType<typeof setupWebGL>;\n\n protected isDisabled?: Boolean = false;\n\n async init({\n outputCanvas,\n inputElement: inputVideo,\n }: VideoTransformerInitOptions): Promise<void> {\n if (!(inputVideo instanceof HTMLVideoElement)) {\n throw TypeError('Video transformer needs a HTMLVideoElement as input');\n }\n\n this.transformer = new TransformStream({\n transform: (frame, controller) => this.transform(frame, controller),\n });\n this.canvas = outputCanvas || null;\n if (outputCanvas) {\n // this.ctx = this.canvas?.getContext('2d') || undefined;\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n }\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async restart({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n this.canvas = outputCanvas || null;\n this.gl?.cleanup();\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async destroy() {\n this.isDisabled = true;\n this.canvas = undefined;\n this.gl?.cleanup();\n this.gl = undefined;\n }\n\n abstract transform(\n frame: VideoFrame,\n controller: TransformStreamDefaultController<VideoFrame>,\n ): void;\n\n abstract update(options: Options): void;\n}\n","import ProcessorWrapper, { ProcessorWrapperOptions } from './ProcessorWrapper';\nimport BackgroundTransformer, {\n BackgroundOptions,\n FrameProcessingStats,\n SegmenterOptions,\n} from './transformers/BackgroundTransformer';\n\nexport * from './transformers/types';\nexport { default as VideoTransformer } from './transformers/VideoTransformer';\nexport {\n ProcessorWrapper,\n type BackgroundOptions,\n type SegmenterOptions,\n BackgroundTransformer,\n type ProcessorWrapperOptions,\n};\n\n/**\n * Determines if the current browser supports background processors\n */\nexport const supportsBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.isSupported;\n\n/**\n * Determines if the current browser supports modern background processors, which yield better performance\n */\nexport const supportsModernBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.hasModernApiSupport;\n\nexport interface BackgroundProcessorOptions extends ProcessorWrapperOptions {\n blurRadius?: number;\n imagePath?: string;\n segmenterOptions?: SegmenterOptions;\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n}\n\nexport const BackgroundBlur = (\n blurRadius: number = 10,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n blurRadius,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'background-blur',\n );\n};\n\nexport const VirtualBackground = (\n imagePath: string,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n imagePath,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'virtual-background',\n );\n};\n\nexport const BackgroundProcessor = (\n options: BackgroundProcessorOptions,\n name = 'background-processor',\n) => {\n const isTransformerSupported = BackgroundTransformer.isSupported;\n const isProcessorSupported = ProcessorWrapper.isSupported;\n\n if (!isTransformerSupported) {\n throw new Error('Background transformer is not supported in this browser');\n }\n\n if (!isProcessorSupported) {\n throw new Error(\n 'Neither MediaStreamTrackProcessor nor canvas.captureStream() fallback is supported in this browser',\n );\n }\n\n // Extract transformer-specific options and processor options\n const {\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n ...processorOpts\n } = options;\n\n const processor = new ProcessorWrapper(\n new BackgroundTransformer({\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n }),\n name,\n processorOpts,\n );\n\n return processor;\n};\n"]}
package/dist/index.mjs CHANGED
@@ -248,7 +248,7 @@ import * as vision from "@mediapipe/tasks-vision";
248
248
 
249
249
  // package.json
250
250
  var dependencies = {
251
- "@mediapipe/tasks-vision": "^0.10.22-rc.20250304"
251
+ "@mediapipe/tasks-vision": "0.10.14"
252
252
  };
253
253
 
254
254
  // src/webgl/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/ProcessorWrapper.ts","../src/transformers/BackgroundTransformer.ts","../package.json","../src/webgl/index.ts","../src/transformers/VideoTransformer.ts","../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention */\nexport const supportsProcessor = typeof MediaStreamTrackGenerator !== 'undefined';\nexport const supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined';\n\nasync function sleep(time: number) {\n return new Promise((resolve) => setTimeout(resolve, time));\n}\n\nexport async function waitForTrackResolution(track: MediaStreamTrack) {\n const timeout = 500;\n\n // browsers report wrong initial resolution on iOS.\n // when slightly delaying the call to .getSettings(), the correct resolution is being reported\n await sleep(10);\n\n const started = Date.now();\n while (Date.now() - started < timeout) {\n const { width, height } = track.getSettings();\n if (width && height) {\n return { width, height };\n }\n await sleep(50);\n }\n return { width: undefined, height: undefined };\n}\n","import type { ProcessorOptions, Track, TrackProcessor } from 'livekit-client';\nimport { TrackTransformer } from './transformers';\nimport { waitForTrackResolution } from './utils';\n\nexport interface ProcessorWrapperOptions {\n /**\n * Maximum frame rate for fallback canvas.captureStream implementation\n * Default: 30\n */\n maxFps?: number;\n}\n\nexport default class ProcessorWrapper<TransformerOptions extends Record<string, unknown>>\n implements TrackProcessor<Track.Kind>\n{\n /**\n * Determines if the Processor is supported on the current browser\n */\n static get isSupported() {\n // Check for primary implementation support\n const hasStreamProcessor =\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined';\n\n // Check for fallback implementation support\n const hasFallbackSupport =\n typeof HTMLCanvasElement !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n 'captureStream' in HTMLCanvasElement.prototype;\n\n // We can work if either implementation is available\n return hasStreamProcessor || hasFallbackSupport;\n }\n\n /**\n * Determines if modern browser APIs are supported, which yield better performance\n */\n static get hasModernApiSupport() {\n return (\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined'\n );\n }\n\n name: string;\n\n source?: MediaStreamVideoTrack;\n\n processor?: MediaStreamTrackProcessor<VideoFrame>;\n\n trackGenerator?: MediaStreamTrackGenerator<VideoFrame>;\n\n canvas?: OffscreenCanvas;\n\n displayCanvas?: HTMLCanvasElement;\n\n sourceDummy?: HTMLMediaElement;\n\n processedTrack?: MediaStreamTrack;\n\n transformer: TrackTransformer<TransformerOptions>;\n\n // For tracking whether we're using the stream API fallback\n private useStreamFallback = false;\n\n // For fallback rendering with canvas.captureStream()\n private capturedStream?: MediaStream;\n\n private animationFrameId?: number;\n\n private renderContext?: CanvasRenderingContext2D;\n\n private frameCallback?: (frame: VideoFrame) => void;\n\n private processingEnabled = false;\n\n // FPS control for fallback implementation\n private maxFps: number;\n\n constructor(\n transformer: TrackTransformer<TransformerOptions>,\n name: string,\n options: ProcessorWrapperOptions = {},\n ) {\n this.name = name;\n this.transformer = transformer;\n this.maxFps = options.maxFps ?? 30;\n }\n\n private async setup(opts: ProcessorOptions<Track.Kind>) {\n this.source = opts.track as MediaStreamVideoTrack;\n\n const { width, height } = await waitForTrackResolution(this.source);\n this.sourceDummy = opts.element;\n\n if (!(this.sourceDummy instanceof HTMLVideoElement)) {\n throw TypeError('Currently only video transformers are supported');\n }\n\n if (this.sourceDummy instanceof HTMLVideoElement) {\n this.sourceDummy.height = height ?? 300;\n this.sourceDummy.width = width ?? 300;\n }\n\n this.useStreamFallback = !ProcessorWrapper.hasModernApiSupport;\n\n if (this.useStreamFallback) {\n // Create a visible canvas for the fallback implementation or use an existing one if provided\n const existingCanvas = document.querySelector(\n 'canvas[data-livekit-processor=\"' + this.name + '\"]',\n ) as HTMLCanvasElement;\n\n if (existingCanvas) {\n this.displayCanvas = existingCanvas;\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n } else {\n this.displayCanvas = document.createElement('canvas');\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n this.displayCanvas.style.display = 'none';\n this.displayCanvas.dataset.livekitProcessor = this.name;\n document.body.appendChild(this.displayCanvas);\n }\n\n this.renderContext = this.displayCanvas.getContext('2d')!;\n this.capturedStream = this.displayCanvas.captureStream();\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n } else {\n // Use MediaStreamTrackProcessor API\n this.processor = new MediaStreamTrackProcessor({ track: this.source });\n this.trackGenerator = new MediaStreamTrackGenerator({\n kind: 'video',\n signalTarget: this.source,\n });\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n }\n }\n\n async init(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.setup(opts);\n\n if (!this.canvas) {\n throw new TypeError('Expected canvas to be defined after setup');\n }\n\n await this.transformer.init({\n outputCanvas: this.canvas,\n inputElement: this.sourceDummy as HTMLVideoElement,\n });\n\n if (this.useStreamFallback) {\n this.initFallbackPath();\n } else {\n this.initStreamProcessorPath();\n }\n }\n\n private initStreamProcessorPath() {\n if (!this.processor || !this.trackGenerator) {\n throw new TypeError(\n 'Expected processor and trackGenerator to be defined for stream processor path',\n );\n }\n\n const readableStream = this.processor.readable;\n const pipedStream = readableStream.pipeThrough(this.transformer!.transformer!);\n\n pipedStream\n .pipeTo(this.trackGenerator.writable)\n .catch((e) => console.error('error when trying to pipe', e))\n .finally(() => this.destroy());\n\n this.processedTrack = this.trackGenerator as MediaStreamVideoTrack;\n }\n\n private initFallbackPath() {\n if (!this.capturedStream || !this.source || !this.canvas || !this.renderContext) {\n throw new TypeError('Missing required components for fallback implementation');\n }\n\n this.processedTrack = this.capturedStream.getVideoTracks()[0];\n this.processingEnabled = true;\n\n // Set up the frame callback for the transformer\n this.frameCallback = (frame: VideoFrame) => {\n if (!this.processingEnabled || !frame) {\n frame.close();\n return;\n }\n\n const controller = {\n enqueue: (processedFrame: VideoFrame) => {\n if (this.renderContext && this.displayCanvas) {\n // Draw the processed frame to the visible canvas\n this.renderContext.drawImage(\n processedFrame,\n 0,\n 0,\n this.displayCanvas.width,\n this.displayCanvas.height,\n );\n processedFrame.close();\n }\n },\n } as TransformStreamDefaultController<VideoFrame>;\n\n try {\n // Pass the frame through our transformer\n // @ts-ignore - The controller expects both VideoFrame & AudioData but we're only using VideoFrame\n this.transformer.transform(frame, controller);\n } catch (e) {\n console.error('Error in transform:', e);\n frame.close();\n }\n };\n\n // Start the rendering loop\n this.startRenderLoop();\n }\n\n private startRenderLoop() {\n if (!this.sourceDummy || !(this.sourceDummy instanceof HTMLVideoElement)) {\n return;\n }\n\n // Store the last processed timestamp to avoid duplicate processing\n let lastVideoTimestamp = -1;\n let lastFrameTime = 0;\n const videoElement = this.sourceDummy as HTMLVideoElement;\n const minFrameInterval = 1000 / this.maxFps; // Minimum time between frames\n\n // Estimate the video's native frame rate\n let estimatedVideoFps = this.maxFps;\n let frameTimeHistory: number[] = [];\n let lastVideoTimeChange = 0;\n let frameCount = 0;\n let lastFpsLog = 0;\n\n const renderLoop = () => {\n if (\n !this.processingEnabled ||\n !this.sourceDummy ||\n !(this.sourceDummy instanceof HTMLVideoElement)\n ) {\n return;\n }\n\n if (this.sourceDummy.paused) {\n console.warn('Video is paused, trying to play');\n this.sourceDummy.play();\n return;\n }\n\n // Only process a new frame if the video has actually updated\n const videoTime = videoElement.currentTime;\n const now = performance.now();\n const timeSinceLastFrame = now - lastFrameTime;\n\n // Detect if video has a new frame\n const hasNewFrame = videoTime !== lastVideoTimestamp;\n\n // Update frame rate estimation if we have a new frame\n if (hasNewFrame) {\n if (lastVideoTimeChange > 0) {\n const timeBetweenFrames = now - lastVideoTimeChange;\n frameTimeHistory.push(timeBetweenFrames);\n\n // Keep a rolling window of the last 10 frame times\n if (frameTimeHistory.length > 10) {\n frameTimeHistory.shift();\n }\n\n // Calculate average frame interval\n if (frameTimeHistory.length > 2) {\n const avgFrameTime =\n frameTimeHistory.reduce((sum, time) => sum + time, 0) / frameTimeHistory.length;\n estimatedVideoFps = 1000 / avgFrameTime;\n\n // Log estimated FPS every 5 seconds in development environments\n // Use a simpler check that works in browsers without process.env\n const isDevelopment =\n (typeof window !== 'undefined' && window.location.hostname === 'localhost') ||\n window.location.hostname === '127.0.0.1';\n\n if (isDevelopment && now - lastFpsLog > 5000) {\n console.debug(\n `[${this.name}] Estimated video FPS: ${estimatedVideoFps.toFixed(\n 1,\n )}, Processing at: ${(frameCount / 5).toFixed(1)} FPS`,\n );\n frameCount = 0;\n lastFpsLog = now;\n }\n }\n }\n lastVideoTimeChange = now;\n }\n\n // Determine if we should process this frame\n // We'll process if:\n // 1. The video has a new frame\n // 2. Enough time has passed since last frame (respecting maxFps)\n const timeThresholdMet = timeSinceLastFrame >= minFrameInterval;\n\n if (hasNewFrame && timeThresholdMet) {\n lastVideoTimestamp = videoTime;\n lastFrameTime = now;\n frameCount++;\n\n try {\n // Create a VideoFrame from the video element\n if (videoElement.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {\n const frame = new VideoFrame(videoElement);\n if (this.frameCallback) {\n this.frameCallback(frame);\n } else {\n frame.close();\n }\n }\n } catch (e) {\n console.error('Error in render loop:', e);\n }\n }\n this.animationFrameId = requestAnimationFrame(renderLoop);\n };\n\n this.animationFrameId = requestAnimationFrame(renderLoop);\n }\n\n async restart(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.destroy();\n await this.init(opts);\n }\n\n async restartTransformer(...options: Parameters<(typeof this.transformer)['restart']>) {\n // @ts-ignore unclear why the restart method only accepts VideoTransformerInitOptions instead of either those or AudioTransformerInitOptions\n await this.transformer.restart(options[0]);\n }\n\n async updateTransformerOptions(...options: Parameters<(typeof this.transformer)['update']>) {\n await this.transformer.update(options[0]);\n }\n\n async destroy() {\n if (this.useStreamFallback) {\n this.processingEnabled = false;\n if (this.animationFrameId) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = undefined;\n }\n if (this.displayCanvas && this.displayCanvas.parentNode) {\n this.displayCanvas.parentNode.removeChild(this.displayCanvas);\n }\n this.capturedStream?.getTracks().forEach((track) => track.stop());\n } else {\n await this.processor?.writableControl?.close();\n this.trackGenerator?.stop();\n }\n await this.transformer.destroy();\n }\n}\n","import * as vision from '@mediapipe/tasks-vision';\nimport { dependencies } from '../../package.json';\nimport VideoTransformer from './VideoTransformer';\nimport { VideoTransformerInitOptions } from './types';\n\nexport type SegmenterOptions = Partial<vision.ImageSegmenterOptions['baseOptions']>;\n\nexport interface FrameProcessingStats {\n processingTimeMs: number;\n segmentationTimeMs: number;\n filterTimeMs: number;\n}\n\nexport type BackgroundOptions = {\n blurRadius?: number;\n imagePath?: string;\n /** cannot be updated through the `update` method, needs a restart */\n segmenterOptions?: SegmenterOptions;\n /** cannot be updated through the `update` method, needs a restart */\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n /** called when a new frame is processed */\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n};\n\nexport default class BackgroundProcessor extends VideoTransformer<BackgroundOptions> {\n static get isSupported() {\n return (\n typeof OffscreenCanvas !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n typeof createImageBitmap !== 'undefined' &&\n !!document.createElement('canvas').getContext('webgl2')\n );\n }\n\n imageSegmenter?: vision.ImageSegmenter;\n\n segmentationResults: vision.ImageSegmenterResult | undefined;\n\n backgroundImage: ImageBitmap | null = null;\n\n options: BackgroundOptions;\n\n constructor(opts: BackgroundOptions) {\n super();\n this.options = opts;\n this.update(opts);\n }\n\n async init({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n // Initialize WebGL with appropriate options based on our current state\n\n await super.init({ outputCanvas, inputElement: inputVideo });\n\n const fileSet = await vision.FilesetResolver.forVisionTasks(\n this.options.assetPaths?.tasksVisionFileSet ??\n `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${dependencies['@mediapipe/tasks-vision']}/wasm`,\n );\n\n this.imageSegmenter = await vision.ImageSegmenter.createFromOptions(fileSet, {\n baseOptions: {\n modelAssetPath:\n this.options.assetPaths?.modelAssetPath ??\n 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/latest/selfie_segmenter.tflite',\n delegate: 'GPU',\n ...this.options.segmenterOptions,\n },\n canvas: this.canvas,\n runningMode: 'VIDEO',\n outputCategoryMask: true,\n outputConfidenceMasks: false,\n });\n\n // Skip loading the image here if update already loaded the image below\n if (this.options?.imagePath && !this.backgroundImage) {\n await this.loadBackground(this.options.imagePath).catch((err) =>\n console.error('Error while loading processor background image: ', err),\n );\n }\n if (this.options.blurRadius) {\n this.gl?.setBlurRadius(this.options.blurRadius);\n }\n }\n\n async destroy() {\n await super.destroy();\n await this.imageSegmenter?.close();\n this.backgroundImage = null;\n }\n\n async loadBackground(path: string) {\n const img = new Image();\n\n await new Promise((resolve, reject) => {\n img.crossOrigin = 'Anonymous';\n img.onload = () => resolve(img);\n img.onerror = (err) => reject(err);\n img.src = path;\n });\n const imageData = await createImageBitmap(img);\n this.gl?.setBackgroundImage(imageData);\n }\n\n async transform(frame: VideoFrame, controller: TransformStreamDefaultController<VideoFrame>) {\n try {\n if (!(frame instanceof VideoFrame) || frame.codedWidth === 0 || frame.codedHeight === 0) {\n console.debug('empty frame detected, ignoring');\n return;\n }\n\n if (this.isDisabled) {\n controller.enqueue(frame);\n return;\n }\n if (!this.canvas) {\n throw TypeError('Canvas needs to be initialized first');\n }\n this.canvas.width = frame.displayWidth;\n this.canvas.height = frame.displayHeight;\n let startTimeMs = performance.now();\n\n this.imageSegmenter?.segmentForVideo(frame, startTimeMs, (result) => {\n const segmentationTimeMs = performance.now() - startTimeMs;\n this.segmentationResults = result;\n this.drawFrame(frame);\n if (this.canvas && this.canvas.width > 0 && this.canvas.height > 0) {\n const newFrame = new VideoFrame(this.canvas, {\n timestamp: frame.timestamp || Date.now(),\n });\n const filterTimeMs = performance.now() - startTimeMs - segmentationTimeMs;\n const stats: FrameProcessingStats = {\n processingTimeMs: performance.now() - startTimeMs,\n segmentationTimeMs,\n filterTimeMs,\n };\n this.options.onFrameProcessed?.(stats);\n\n controller.enqueue(newFrame);\n } else {\n controller.enqueue(frame);\n }\n frame.close();\n });\n } catch (e) {\n console.error('Error while processing frame: ', e);\n frame?.close();\n }\n }\n\n async update(opts: BackgroundOptions) {\n this.options = { ...this.options, ...opts };\n if (opts.blurRadius) {\n this.gl?.setBlurRadius(opts.blurRadius);\n } else if (opts.imagePath) {\n await this.loadBackground(opts.imagePath);\n }\n }\n\n async drawFrame(frame: VideoFrame) {\n if (!this.canvas || !this.gl || !this.segmentationResults || !this.inputVideo) return;\n\n const mask = this.segmentationResults.categoryMask;\n if (mask) {\n this.gl.render(frame, mask);\n }\n }\n}\n","{\n \"name\": \"@livekit/track-processors\",\n \"version\": \"0.5.2\",\n \"description\": \"LiveKit track processors\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"source\": \"src/index.ts\",\n \"types\": \"dist/src/index.d.ts\",\n \"repository\": \"git@github.com:livekit/livekit-track-processors.git\",\n \"author\": \"Lukas Seiler\",\n \"license\": \"Apache-2.0\",\n \"scripts\": {\n \"build\": \"tsup --onSuccess \\\"tsc --declaration --emitDeclarationOnly\\\"\",\n \"build-sample\": \"cd example && vite build\",\n \"lint\": \"eslint src\",\n \"release\": \"pnpm build && changeset publish\",\n \"test\": \"jest\",\n \"sample\": \"vite serve example --port 8080 --open\"\n },\n \"files\": [\n \"dist\",\n \"src\"\n ],\n \"dependencies\": {\n \"@mediapipe/tasks-vision\": \"^0.10.22-rc.20250304\"\n },\n \"peerDependencies\": {\n \"livekit-client\": \"^1.12.0 || ^2.1.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.26.2\",\n \"@livekit/changesets-changelog-github\": \"^0.0.4\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.2.1\",\n \"@types/dom-mediacapture-transform\": \"^0.1.9\",\n \"@types/offscreencanvas\": \"^2019.7.3\",\n \"@typescript-eslint/eslint-plugin\": \"^5.62.0\",\n \"eslint\": \"8.39.0\",\n \"eslint-config-airbnb-typescript\": \"17.0.0\",\n \"eslint-config-prettier\": \"8.8.0\",\n \"eslint-plugin-ecmascript-compat\": \"^3.1.0\",\n \"eslint-plugin-import\": \"2.27.5\",\n \"prettier\": \"^2.8.8\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^4.5.0\"\n },\n \"packageManager\": \"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531\"\n}\n","import { MPMask } from '@mediapipe/tasks-vision';\n\n// Define the blur fragment shader\nconst blurFragmentShader = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D u_texture;\n uniform vec2 u_texelSize;\n uniform vec2 u_direction;\n uniform float u_radius;\n\n void main() {\n float sigma = u_radius;\n float twoSigmaSq = 2.0 * sigma * sigma;\n float totalWeight = 0.0;\n vec3 result = vec3(0.0);\n const int MAX_SAMPLES = 16;\n int radius = int(min(float(MAX_SAMPLES), ceil(u_radius)));\n\n for (int i = -MAX_SAMPLES; i <= MAX_SAMPLES; ++i) {\n float offset = float(i);\n if (abs(offset) > float(radius)) continue;\n float weight = exp(-(offset * offset) / twoSigmaSq);\n vec2 sampleCoord = texCoords + u_direction * u_texelSize * offset;\n result += texture2D(u_texture, sampleCoord).rgb * weight;\n totalWeight += weight;\n }\n\n gl_FragColor = vec4(result / totalWeight, 1.0);\n }\n`;\n\nconst createShaderProgram = (gl: WebGL2RenderingContext) => {\n const vs = `\n attribute vec2 position;\n varying vec2 texCoords;\n \n void main() {\n texCoords = (position + 1.0) / 2.0;\n texCoords.y = 1.0 - texCoords.y;\n gl_Position = vec4(position, 0, 1.0);\n }\n `;\n\n const cS = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D background;\n uniform sampler2D frame;\n uniform sampler2D mask;\n void main() {\n vec4 maskTex = texture2D(mask, texCoords); \n vec4 frameTex = texture2D(frame, texCoords);\n vec4 bgTex = texture2D(background, texCoords);\n \n \n float a = maskTex.r;\n \n gl_FragColor = mix(bgTex, vec4(frameTex.rgb, 1.0), 1.0 - a);\n \n }\n `;\n\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!vertexShader) {\n throw Error('can not create vertex shader');\n }\n gl.shaderSource(vertexShader, vs);\n gl.compileShader(vertexShader);\n\n // Create our fragment shader\n const compositeShader = gl.createShader(gl.FRAGMENT_SHADER);\n if (!compositeShader) {\n throw Error('can not create fragment shader');\n }\n gl.shaderSource(compositeShader, cS);\n gl.compileShader(compositeShader);\n\n // Create the composite program\n const compositeProgram = gl.createProgram();\n if (!compositeProgram) {\n throw Error('can not create composite program');\n }\n gl.attachShader(compositeProgram, vertexShader);\n gl.attachShader(compositeProgram, compositeShader);\n gl.linkProgram(compositeProgram);\n\n let blurProgram = null;\n let blurVertexShader = null;\n let blurFrag = null;\n let blurUniforms = null;\n\n // Create blur shader if enabled\n blurFrag = gl.createShader(gl.FRAGMENT_SHADER);\n if (!blurFrag) {\n throw Error('can not create blur shader');\n }\n gl.shaderSource(blurFrag, blurFragmentShader);\n gl.compileShader(blurFrag);\n\n // Get compile status and log errors if any\n if (!gl.getShaderParameter(blurFrag, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(blurFrag);\n throw Error(`Failed to compile blur shader: ${info}`);\n }\n\n // Create blur program\n blurVertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!blurVertexShader) {\n throw Error('can not create blur vertex shader');\n }\n gl.shaderSource(blurVertexShader, vs);\n gl.compileShader(blurVertexShader);\n\n blurProgram = gl.createProgram();\n if (!blurProgram) {\n throw Error('can not create blur program');\n }\n gl.attachShader(blurProgram, blurVertexShader);\n gl.attachShader(blurProgram, blurFrag);\n gl.linkProgram(blurProgram);\n\n // Check blur program link status\n if (!gl.getProgramParameter(blurProgram, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(blurProgram);\n throw Error(`Failed to link blur program: ${info}`);\n }\n\n blurUniforms = {\n position: gl.getAttribLocation(blurProgram, 'position'),\n texture: gl.getUniformLocation(blurProgram, 'u_texture'),\n texelSize: gl.getUniformLocation(blurProgram, 'u_texelSize'),\n direction: gl.getUniformLocation(blurProgram, 'u_direction'),\n radius: gl.getUniformLocation(blurProgram, 'u_radius'),\n };\n\n return {\n vertexShader,\n compositeShader,\n blurShader: blurFrag,\n compositeProgram,\n blurProgram,\n attribLocations: {\n position: gl.getAttribLocation(compositeProgram, 'position'),\n },\n uniformLocations: {\n mask: gl.getUniformLocation(compositeProgram, 'mask')!,\n frame: gl.getUniformLocation(compositeProgram, 'frame')!,\n background: gl.getUniformLocation(compositeProgram, 'background')!,\n },\n blurUniforms,\n };\n};\n\nexport function initTexture(gl: WebGL2RenderingContext, texIndex: number) {\n const texRef = gl.TEXTURE0 + texIndex;\n gl.activeTexture(texRef);\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n return texture;\n}\n\nexport function createFramebuffer(\n gl: WebGL2RenderingContext,\n texture: WebGLTexture,\n width: number,\n height: number,\n) {\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n\n // Set the texture as the color attachment\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n // Ensure texture dimensions match the provided width and height\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n // Check if framebuffer is complete\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer not complete');\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return framebuffer;\n}\n\nconst createVertexBuffer = (gl: WebGL2RenderingContext) => {\n if (!gl) {\n return null;\n }\n const vertexBuffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]),\n gl.STATIC_DRAW,\n );\n return vertexBuffer;\n};\n\nexport const setupWebGL = (canvas: OffscreenCanvas) => {\n const gl = canvas.getContext('webgl2', { premultipliedAlpha: false }) as WebGL2RenderingContext;\n\n let blurRadius: number | null = null;\n\n if (!gl) {\n return undefined;\n }\n\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n const {\n compositeProgram,\n blurProgram,\n attribLocations: { position: positionLocation },\n uniformLocations: {\n mask: maskTextureLocation,\n frame: frameTextureLocation,\n background: bgTextureLocation,\n },\n blurUniforms,\n } = createShaderProgram(gl);\n\n const bgTexture = initTexture(gl, 0);\n const frameTexture = initTexture(gl, 1);\n const vertexBuffer = createVertexBuffer(gl);\n\n // Create additional textures and framebuffers for processing\n let processTextures: WebGLTexture[] = [];\n let processFramebuffers: WebGLFramebuffer[] = [];\n\n // Create textures for processing (blur)\n processTextures.push(initTexture(gl, 3));\n processTextures.push(initTexture(gl, 4));\n\n // Create framebuffers for processing\n processFramebuffers.push(createFramebuffer(gl, processTextures[0], canvas.width, canvas.height));\n processFramebuffers.push(createFramebuffer(gl, processTextures[1], canvas.width, canvas.height));\n\n // Set up uniforms for the composite shader\n gl.useProgram(compositeProgram);\n gl.uniform1i(bgTextureLocation, 0);\n gl.uniform1i(frameTextureLocation, 1);\n gl.uniform1i(maskTextureLocation, 2);\n\n // Store custom background image\n let customBackgroundImage: ImageBitmap | null = null;\n\n function applyBlur(sourceTexture: WebGLTexture, width: number, height: number) {\n if (!blurRadius || !blurProgram || !blurUniforms) return bgTexture;\n\n gl.useProgram(blurProgram);\n\n // Set common attributes\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(blurUniforms.position, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(blurUniforms.position);\n\n const texelWidth = 1.0 / width;\n const texelHeight = 1.0 / height;\n\n // First pass - horizontal blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[0]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, sourceTexture);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.texelSize, texelWidth, texelHeight);\n gl.uniform2f(blurUniforms.direction, 1.0, 0.0); // Horizontal\n gl.uniform1f(blurUniforms.radius, blurRadius);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Second pass - vertical blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[1]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, processTextures[0]);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.direction, 0.0, 1.0); // Vertical\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Reset framebuffer\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n return processTextures[1];\n }\n\n function render(frame: VideoFrame, mask: MPMask) {\n if (frame.codedWidth === 0 || mask.width === 0) {\n return;\n }\n\n const width = frame.displayWidth;\n const height = frame.displayHeight;\n\n // Prepare frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);\n\n // Apply blur if enabled (and no custom background is set)\n let backgroundTexture = bgTexture;\n\n // If we have a custom background image, use that\n if (customBackgroundImage) {\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, customBackgroundImage);\n backgroundTexture = bgTexture;\n } else if (blurRadius) {\n // Otherwise, if blur is enabled, apply blur effect to the frame\n backgroundTexture = applyBlur(frameTexture, width, height);\n }\n\n // Get the mask texture\n const maskTexture = mask.getAsWebGLTexture();\n\n // Render the final composite\n gl.viewport(0, 0, width, height);\n gl.clearColor(1.0, 1.0, 1.0, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(compositeProgram);\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(positionLocation);\n\n // Set background texture (either original, blurred or custom)\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, backgroundTexture);\n gl.uniform1i(bgTextureLocation, 0);\n\n // Set frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.uniform1i(frameTextureLocation, 1);\n\n // Set mask texture\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, maskTexture);\n gl.uniform1i(maskTextureLocation, 2);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n mask.close();\n }\n\n /**\n * Set or update the background image\n * @param image The background image to use, or null to clear\n */\n async function setBackgroundImage(image: ImageBitmap | null) {\n // Clear existing background\n customBackgroundImage = null;\n\n if (image) {\n try {\n // Get current canvas dimensions\n const canvasWidth = canvas.width;\n const canvasHeight = canvas.height;\n\n // Calculate dimensions and crop for \"cover\" mode\n const imgAspect = image.width / image.height;\n const canvasAspect = canvasWidth / canvasHeight;\n\n let sx = 0;\n let sy = 0;\n let sWidth = image.width;\n let sHeight = image.height;\n\n // For cover mode, we need to crop some parts of the image\n // to ensure it covers the canvas while maintaining aspect ratio\n if (imgAspect > canvasAspect) {\n // Image is wider than canvas - crop the sides\n sWidth = Math.round(image.height * canvasAspect);\n sx = Math.round((image.width - sWidth) / 2); // Center the crop horizontally\n } else if (imgAspect < canvasAspect) {\n // Image is taller than canvas - crop the top/bottom\n sHeight = Math.round(image.width / canvasAspect);\n sy = Math.round((image.height - sHeight) / 2); // Center the crop vertically\n }\n\n // Create a new ImageBitmap with the cropped portion\n const croppedImage = await createImageBitmap(image, sx, sy, sWidth, sHeight, {\n resizeWidth: canvasWidth,\n resizeHeight: canvasHeight,\n resizeQuality: 'medium',\n });\n\n // Store the cropped and resized image\n customBackgroundImage = croppedImage;\n\n // Load the image into the texture\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, croppedImage);\n } catch (error) {\n console.error('Error processing background image:', error);\n // Fallback to original image on error\n customBackgroundImage = image;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n }\n } else {\n // set the background texture to an empty 2x2 image\n const emptyImage = new ImageData(2, 2);\n emptyImage.data[0] = 0;\n emptyImage.data[1] = 0;\n emptyImage.data[2] = 0;\n emptyImage.data[3] = 0;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, emptyImage);\n }\n }\n\n function setBlurRadius(radius: number | null) {\n blurRadius = radius;\n setBackgroundImage(null);\n }\n\n function cleanup() {\n gl.deleteProgram(compositeProgram);\n gl.deleteProgram(blurProgram);\n gl.deleteTexture(bgTexture);\n gl.deleteTexture(frameTexture);\n for (const texture of processTextures) {\n gl.deleteTexture(texture);\n }\n for (const framebuffer of processFramebuffers) {\n gl.deleteFramebuffer(framebuffer);\n }\n gl.deleteBuffer(vertexBuffer);\n\n // Release any ImageBitmap resources\n if (customBackgroundImage) {\n customBackgroundImage.close();\n customBackgroundImage = null;\n }\n processTextures = [];\n processFramebuffers = [];\n }\n\n return { render, setBackgroundImage, setBlurRadius, cleanup };\n};\n","import { setupWebGL } from '../webgl/index';\nimport { VideoTrackTransformer, VideoTransformerInitOptions } from './types';\n\nexport default abstract class VideoTransformer<Options extends Record<string, unknown>>\n implements VideoTrackTransformer<Options>\n{\n transformer?: TransformStream;\n\n canvas?: OffscreenCanvas;\n\n // ctx?: OffscreenCanvasRenderingContext2D;\n\n inputVideo?: HTMLVideoElement;\n\n gl?: ReturnType<typeof setupWebGL>;\n\n protected isDisabled?: Boolean = false;\n\n async init({\n outputCanvas,\n inputElement: inputVideo,\n }: VideoTransformerInitOptions): Promise<void> {\n if (!(inputVideo instanceof HTMLVideoElement)) {\n throw TypeError('Video transformer needs a HTMLVideoElement as input');\n }\n\n this.transformer = new TransformStream({\n transform: (frame, controller) => this.transform(frame, controller),\n });\n this.canvas = outputCanvas || null;\n if (outputCanvas) {\n // this.ctx = this.canvas?.getContext('2d') || undefined;\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n }\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async restart({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n this.canvas = outputCanvas || null;\n this.gl?.cleanup();\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async destroy() {\n this.isDisabled = true;\n this.canvas = undefined;\n this.gl?.cleanup();\n this.gl = undefined;\n }\n\n abstract transform(\n frame: VideoFrame,\n controller: TransformStreamDefaultController<VideoFrame>,\n ): void;\n\n abstract update(options: Options): void;\n}\n","import ProcessorWrapper, { ProcessorWrapperOptions } from './ProcessorWrapper';\nimport BackgroundTransformer, {\n BackgroundOptions,\n FrameProcessingStats,\n SegmenterOptions,\n} from './transformers/BackgroundTransformer';\n\nexport * from './transformers/types';\nexport { default as VideoTransformer } from './transformers/VideoTransformer';\nexport {\n ProcessorWrapper,\n type BackgroundOptions,\n type SegmenterOptions,\n BackgroundTransformer,\n type ProcessorWrapperOptions,\n};\n\n/**\n * Determines if the current browser supports background processors\n */\nexport const supportsBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.isSupported;\n\n/**\n * Determines if the current browser supports modern background processors, which yield better performance\n */\nexport const supportsModernBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.hasModernApiSupport;\n\nexport interface BackgroundProcessorOptions extends ProcessorWrapperOptions {\n blurRadius?: number;\n imagePath?: string;\n segmenterOptions?: SegmenterOptions;\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n}\n\nexport const BackgroundBlur = (\n blurRadius: number = 10,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n blurRadius,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'background-blur',\n );\n};\n\nexport const VirtualBackground = (\n imagePath: string,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n imagePath,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'virtual-background',\n );\n};\n\nexport const BackgroundProcessor = (\n options: BackgroundProcessorOptions,\n name = 'background-processor',\n) => {\n const isTransformerSupported = BackgroundTransformer.isSupported;\n const isProcessorSupported = ProcessorWrapper.isSupported;\n\n if (!isTransformerSupported) {\n throw new Error('Background transformer is not supported in this browser');\n }\n\n if (!isProcessorSupported) {\n throw new Error(\n 'Neither MediaStreamTrackProcessor nor canvas.captureStream() fallback is supported in this browser',\n );\n }\n\n // Extract transformer-specific options and processor options\n const {\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n ...processorOpts\n } = options;\n\n const processor = new ProcessorWrapper(\n new BackgroundTransformer({\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n }),\n name,\n processorOpts,\n );\n\n return processor;\n};\n"],"mappings":"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","names":["_a","BackgroundProcessor"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/ProcessorWrapper.ts","../src/transformers/BackgroundTransformer.ts","../package.json","../src/webgl/index.ts","../src/transformers/VideoTransformer.ts","../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention */\nexport const supportsProcessor = typeof MediaStreamTrackGenerator !== 'undefined';\nexport const supportsOffscreenCanvas = typeof OffscreenCanvas !== 'undefined';\n\nasync function sleep(time: number) {\n return new Promise((resolve) => setTimeout(resolve, time));\n}\n\nexport async function waitForTrackResolution(track: MediaStreamTrack) {\n const timeout = 500;\n\n // browsers report wrong initial resolution on iOS.\n // when slightly delaying the call to .getSettings(), the correct resolution is being reported\n await sleep(10);\n\n const started = Date.now();\n while (Date.now() - started < timeout) {\n const { width, height } = track.getSettings();\n if (width && height) {\n return { width, height };\n }\n await sleep(50);\n }\n return { width: undefined, height: undefined };\n}\n","import type { ProcessorOptions, Track, TrackProcessor } from 'livekit-client';\nimport { TrackTransformer } from './transformers';\nimport { waitForTrackResolution } from './utils';\n\nexport interface ProcessorWrapperOptions {\n /**\n * Maximum frame rate for fallback canvas.captureStream implementation\n * Default: 30\n */\n maxFps?: number;\n}\n\nexport default class ProcessorWrapper<TransformerOptions extends Record<string, unknown>>\n implements TrackProcessor<Track.Kind>\n{\n /**\n * Determines if the Processor is supported on the current browser\n */\n static get isSupported() {\n // Check for primary implementation support\n const hasStreamProcessor =\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined';\n\n // Check for fallback implementation support\n const hasFallbackSupport =\n typeof HTMLCanvasElement !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n 'captureStream' in HTMLCanvasElement.prototype;\n\n // We can work if either implementation is available\n return hasStreamProcessor || hasFallbackSupport;\n }\n\n /**\n * Determines if modern browser APIs are supported, which yield better performance\n */\n static get hasModernApiSupport() {\n return (\n typeof MediaStreamTrackGenerator !== 'undefined' &&\n typeof MediaStreamTrackProcessor !== 'undefined'\n );\n }\n\n name: string;\n\n source?: MediaStreamVideoTrack;\n\n processor?: MediaStreamTrackProcessor<VideoFrame>;\n\n trackGenerator?: MediaStreamTrackGenerator<VideoFrame>;\n\n canvas?: OffscreenCanvas;\n\n displayCanvas?: HTMLCanvasElement;\n\n sourceDummy?: HTMLMediaElement;\n\n processedTrack?: MediaStreamTrack;\n\n transformer: TrackTransformer<TransformerOptions>;\n\n // For tracking whether we're using the stream API fallback\n private useStreamFallback = false;\n\n // For fallback rendering with canvas.captureStream()\n private capturedStream?: MediaStream;\n\n private animationFrameId?: number;\n\n private renderContext?: CanvasRenderingContext2D;\n\n private frameCallback?: (frame: VideoFrame) => void;\n\n private processingEnabled = false;\n\n // FPS control for fallback implementation\n private maxFps: number;\n\n constructor(\n transformer: TrackTransformer<TransformerOptions>,\n name: string,\n options: ProcessorWrapperOptions = {},\n ) {\n this.name = name;\n this.transformer = transformer;\n this.maxFps = options.maxFps ?? 30;\n }\n\n private async setup(opts: ProcessorOptions<Track.Kind>) {\n this.source = opts.track as MediaStreamVideoTrack;\n\n const { width, height } = await waitForTrackResolution(this.source);\n this.sourceDummy = opts.element;\n\n if (!(this.sourceDummy instanceof HTMLVideoElement)) {\n throw TypeError('Currently only video transformers are supported');\n }\n\n if (this.sourceDummy instanceof HTMLVideoElement) {\n this.sourceDummy.height = height ?? 300;\n this.sourceDummy.width = width ?? 300;\n }\n\n this.useStreamFallback = !ProcessorWrapper.hasModernApiSupport;\n\n if (this.useStreamFallback) {\n // Create a visible canvas for the fallback implementation or use an existing one if provided\n const existingCanvas = document.querySelector(\n 'canvas[data-livekit-processor=\"' + this.name + '\"]',\n ) as HTMLCanvasElement;\n\n if (existingCanvas) {\n this.displayCanvas = existingCanvas;\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n } else {\n this.displayCanvas = document.createElement('canvas');\n this.displayCanvas.width = width ?? 300;\n this.displayCanvas.height = height ?? 300;\n this.displayCanvas.style.display = 'none';\n this.displayCanvas.dataset.livekitProcessor = this.name;\n document.body.appendChild(this.displayCanvas);\n }\n\n this.renderContext = this.displayCanvas.getContext('2d')!;\n this.capturedStream = this.displayCanvas.captureStream();\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n } else {\n // Use MediaStreamTrackProcessor API\n this.processor = new MediaStreamTrackProcessor({ track: this.source });\n this.trackGenerator = new MediaStreamTrackGenerator({\n kind: 'video',\n signalTarget: this.source,\n });\n this.canvas = new OffscreenCanvas(width ?? 300, height ?? 300);\n }\n }\n\n async init(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.setup(opts);\n\n if (!this.canvas) {\n throw new TypeError('Expected canvas to be defined after setup');\n }\n\n await this.transformer.init({\n outputCanvas: this.canvas,\n inputElement: this.sourceDummy as HTMLVideoElement,\n });\n\n if (this.useStreamFallback) {\n this.initFallbackPath();\n } else {\n this.initStreamProcessorPath();\n }\n }\n\n private initStreamProcessorPath() {\n if (!this.processor || !this.trackGenerator) {\n throw new TypeError(\n 'Expected processor and trackGenerator to be defined for stream processor path',\n );\n }\n\n const readableStream = this.processor.readable;\n const pipedStream = readableStream.pipeThrough(this.transformer!.transformer!);\n\n pipedStream\n .pipeTo(this.trackGenerator.writable)\n .catch((e) => console.error('error when trying to pipe', e))\n .finally(() => this.destroy());\n\n this.processedTrack = this.trackGenerator as MediaStreamVideoTrack;\n }\n\n private initFallbackPath() {\n if (!this.capturedStream || !this.source || !this.canvas || !this.renderContext) {\n throw new TypeError('Missing required components for fallback implementation');\n }\n\n this.processedTrack = this.capturedStream.getVideoTracks()[0];\n this.processingEnabled = true;\n\n // Set up the frame callback for the transformer\n this.frameCallback = (frame: VideoFrame) => {\n if (!this.processingEnabled || !frame) {\n frame.close();\n return;\n }\n\n const controller = {\n enqueue: (processedFrame: VideoFrame) => {\n if (this.renderContext && this.displayCanvas) {\n // Draw the processed frame to the visible canvas\n this.renderContext.drawImage(\n processedFrame,\n 0,\n 0,\n this.displayCanvas.width,\n this.displayCanvas.height,\n );\n processedFrame.close();\n }\n },\n } as TransformStreamDefaultController<VideoFrame>;\n\n try {\n // Pass the frame through our transformer\n // @ts-ignore - The controller expects both VideoFrame & AudioData but we're only using VideoFrame\n this.transformer.transform(frame, controller);\n } catch (e) {\n console.error('Error in transform:', e);\n frame.close();\n }\n };\n\n // Start the rendering loop\n this.startRenderLoop();\n }\n\n private startRenderLoop() {\n if (!this.sourceDummy || !(this.sourceDummy instanceof HTMLVideoElement)) {\n return;\n }\n\n // Store the last processed timestamp to avoid duplicate processing\n let lastVideoTimestamp = -1;\n let lastFrameTime = 0;\n const videoElement = this.sourceDummy as HTMLVideoElement;\n const minFrameInterval = 1000 / this.maxFps; // Minimum time between frames\n\n // Estimate the video's native frame rate\n let estimatedVideoFps = this.maxFps;\n let frameTimeHistory: number[] = [];\n let lastVideoTimeChange = 0;\n let frameCount = 0;\n let lastFpsLog = 0;\n\n const renderLoop = () => {\n if (\n !this.processingEnabled ||\n !this.sourceDummy ||\n !(this.sourceDummy instanceof HTMLVideoElement)\n ) {\n return;\n }\n\n if (this.sourceDummy.paused) {\n console.warn('Video is paused, trying to play');\n this.sourceDummy.play();\n return;\n }\n\n // Only process a new frame if the video has actually updated\n const videoTime = videoElement.currentTime;\n const now = performance.now();\n const timeSinceLastFrame = now - lastFrameTime;\n\n // Detect if video has a new frame\n const hasNewFrame = videoTime !== lastVideoTimestamp;\n\n // Update frame rate estimation if we have a new frame\n if (hasNewFrame) {\n if (lastVideoTimeChange > 0) {\n const timeBetweenFrames = now - lastVideoTimeChange;\n frameTimeHistory.push(timeBetweenFrames);\n\n // Keep a rolling window of the last 10 frame times\n if (frameTimeHistory.length > 10) {\n frameTimeHistory.shift();\n }\n\n // Calculate average frame interval\n if (frameTimeHistory.length > 2) {\n const avgFrameTime =\n frameTimeHistory.reduce((sum, time) => sum + time, 0) / frameTimeHistory.length;\n estimatedVideoFps = 1000 / avgFrameTime;\n\n // Log estimated FPS every 5 seconds in development environments\n // Use a simpler check that works in browsers without process.env\n const isDevelopment =\n (typeof window !== 'undefined' && window.location.hostname === 'localhost') ||\n window.location.hostname === '127.0.0.1';\n\n if (isDevelopment && now - lastFpsLog > 5000) {\n console.debug(\n `[${this.name}] Estimated video FPS: ${estimatedVideoFps.toFixed(\n 1,\n )}, Processing at: ${(frameCount / 5).toFixed(1)} FPS`,\n );\n frameCount = 0;\n lastFpsLog = now;\n }\n }\n }\n lastVideoTimeChange = now;\n }\n\n // Determine if we should process this frame\n // We'll process if:\n // 1. The video has a new frame\n // 2. Enough time has passed since last frame (respecting maxFps)\n const timeThresholdMet = timeSinceLastFrame >= minFrameInterval;\n\n if (hasNewFrame && timeThresholdMet) {\n lastVideoTimestamp = videoTime;\n lastFrameTime = now;\n frameCount++;\n\n try {\n // Create a VideoFrame from the video element\n if (videoElement.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {\n const frame = new VideoFrame(videoElement);\n if (this.frameCallback) {\n this.frameCallback(frame);\n } else {\n frame.close();\n }\n }\n } catch (e) {\n console.error('Error in render loop:', e);\n }\n }\n this.animationFrameId = requestAnimationFrame(renderLoop);\n };\n\n this.animationFrameId = requestAnimationFrame(renderLoop);\n }\n\n async restart(opts: ProcessorOptions<Track.Kind>): Promise<void> {\n await this.destroy();\n await this.init(opts);\n }\n\n async restartTransformer(...options: Parameters<(typeof this.transformer)['restart']>) {\n // @ts-ignore unclear why the restart method only accepts VideoTransformerInitOptions instead of either those or AudioTransformerInitOptions\n await this.transformer.restart(options[0]);\n }\n\n async updateTransformerOptions(...options: Parameters<(typeof this.transformer)['update']>) {\n await this.transformer.update(options[0]);\n }\n\n async destroy() {\n if (this.useStreamFallback) {\n this.processingEnabled = false;\n if (this.animationFrameId) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = undefined;\n }\n if (this.displayCanvas && this.displayCanvas.parentNode) {\n this.displayCanvas.parentNode.removeChild(this.displayCanvas);\n }\n this.capturedStream?.getTracks().forEach((track) => track.stop());\n } else {\n await this.processor?.writableControl?.close();\n this.trackGenerator?.stop();\n }\n await this.transformer.destroy();\n }\n}\n","import * as vision from '@mediapipe/tasks-vision';\nimport { dependencies } from '../../package.json';\nimport VideoTransformer from './VideoTransformer';\nimport { VideoTransformerInitOptions } from './types';\n\nexport type SegmenterOptions = Partial<vision.ImageSegmenterOptions['baseOptions']>;\n\nexport interface FrameProcessingStats {\n processingTimeMs: number;\n segmentationTimeMs: number;\n filterTimeMs: number;\n}\n\nexport type BackgroundOptions = {\n blurRadius?: number;\n imagePath?: string;\n /** cannot be updated through the `update` method, needs a restart */\n segmenterOptions?: SegmenterOptions;\n /** cannot be updated through the `update` method, needs a restart */\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n /** called when a new frame is processed */\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n};\n\nexport default class BackgroundProcessor extends VideoTransformer<BackgroundOptions> {\n static get isSupported() {\n return (\n typeof OffscreenCanvas !== 'undefined' &&\n typeof VideoFrame !== 'undefined' &&\n typeof createImageBitmap !== 'undefined' &&\n !!document.createElement('canvas').getContext('webgl2')\n );\n }\n\n imageSegmenter?: vision.ImageSegmenter;\n\n segmentationResults: vision.ImageSegmenterResult | undefined;\n\n backgroundImage: ImageBitmap | null = null;\n\n options: BackgroundOptions;\n\n constructor(opts: BackgroundOptions) {\n super();\n this.options = opts;\n this.update(opts);\n }\n\n async init({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n // Initialize WebGL with appropriate options based on our current state\n\n await super.init({ outputCanvas, inputElement: inputVideo });\n\n const fileSet = await vision.FilesetResolver.forVisionTasks(\n this.options.assetPaths?.tasksVisionFileSet ??\n `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${dependencies['@mediapipe/tasks-vision']}/wasm`,\n );\n\n this.imageSegmenter = await vision.ImageSegmenter.createFromOptions(fileSet, {\n baseOptions: {\n modelAssetPath:\n this.options.assetPaths?.modelAssetPath ??\n 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/latest/selfie_segmenter.tflite',\n delegate: 'GPU',\n ...this.options.segmenterOptions,\n },\n canvas: this.canvas,\n runningMode: 'VIDEO',\n outputCategoryMask: true,\n outputConfidenceMasks: false,\n });\n\n // Skip loading the image here if update already loaded the image below\n if (this.options?.imagePath && !this.backgroundImage) {\n await this.loadBackground(this.options.imagePath).catch((err) =>\n console.error('Error while loading processor background image: ', err),\n );\n }\n if (this.options.blurRadius) {\n this.gl?.setBlurRadius(this.options.blurRadius);\n }\n }\n\n async destroy() {\n await super.destroy();\n await this.imageSegmenter?.close();\n this.backgroundImage = null;\n }\n\n async loadBackground(path: string) {\n const img = new Image();\n\n await new Promise((resolve, reject) => {\n img.crossOrigin = 'Anonymous';\n img.onload = () => resolve(img);\n img.onerror = (err) => reject(err);\n img.src = path;\n });\n const imageData = await createImageBitmap(img);\n this.gl?.setBackgroundImage(imageData);\n }\n\n async transform(frame: VideoFrame, controller: TransformStreamDefaultController<VideoFrame>) {\n try {\n if (!(frame instanceof VideoFrame) || frame.codedWidth === 0 || frame.codedHeight === 0) {\n console.debug('empty frame detected, ignoring');\n return;\n }\n\n if (this.isDisabled) {\n controller.enqueue(frame);\n return;\n }\n if (!this.canvas) {\n throw TypeError('Canvas needs to be initialized first');\n }\n this.canvas.width = frame.displayWidth;\n this.canvas.height = frame.displayHeight;\n let startTimeMs = performance.now();\n\n this.imageSegmenter?.segmentForVideo(frame, startTimeMs, (result) => {\n const segmentationTimeMs = performance.now() - startTimeMs;\n this.segmentationResults = result;\n this.drawFrame(frame);\n if (this.canvas && this.canvas.width > 0 && this.canvas.height > 0) {\n const newFrame = new VideoFrame(this.canvas, {\n timestamp: frame.timestamp || Date.now(),\n });\n const filterTimeMs = performance.now() - startTimeMs - segmentationTimeMs;\n const stats: FrameProcessingStats = {\n processingTimeMs: performance.now() - startTimeMs,\n segmentationTimeMs,\n filterTimeMs,\n };\n this.options.onFrameProcessed?.(stats);\n\n controller.enqueue(newFrame);\n } else {\n controller.enqueue(frame);\n }\n frame.close();\n });\n } catch (e) {\n console.error('Error while processing frame: ', e);\n frame?.close();\n }\n }\n\n async update(opts: BackgroundOptions) {\n this.options = { ...this.options, ...opts };\n if (opts.blurRadius) {\n this.gl?.setBlurRadius(opts.blurRadius);\n } else if (opts.imagePath) {\n await this.loadBackground(opts.imagePath);\n }\n }\n\n async drawFrame(frame: VideoFrame) {\n if (!this.canvas || !this.gl || !this.segmentationResults || !this.inputVideo) return;\n\n const mask = this.segmentationResults.categoryMask;\n if (mask) {\n this.gl.render(frame, mask);\n }\n }\n}\n","{\n \"name\": \"@livekit/track-processors\",\n \"version\": \"0.5.3\",\n \"description\": \"LiveKit track processors\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"source\": \"src/index.ts\",\n \"types\": \"dist/src/index.d.ts\",\n \"repository\": \"git@github.com:livekit/livekit-track-processors.git\",\n \"author\": \"Lukas Seiler\",\n \"license\": \"Apache-2.0\",\n \"scripts\": {\n \"build\": \"tsup --onSuccess \\\"tsc --declaration --emitDeclarationOnly\\\"\",\n \"build-sample\": \"cd example && vite build\",\n \"lint\": \"eslint src\",\n \"release\": \"pnpm build && changeset publish\",\n \"test\": \"jest\",\n \"sample\": \"vite serve example --port 8080 --open\"\n },\n \"files\": [\n \"dist\",\n \"src\"\n ],\n \"dependencies\": {\n \"@mediapipe/tasks-vision\": \"0.10.14\"\n },\n \"peerDependencies\": {\n \"livekit-client\": \"^1.12.0 || ^2.1.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.26.2\",\n \"@livekit/changesets-changelog-github\": \"^0.0.4\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.2.1\",\n \"@types/dom-mediacapture-transform\": \"^0.1.9\",\n \"@types/offscreencanvas\": \"^2019.7.3\",\n \"@typescript-eslint/eslint-plugin\": \"^5.62.0\",\n \"eslint\": \"8.39.0\",\n \"eslint-config-airbnb-typescript\": \"17.0.0\",\n \"eslint-config-prettier\": \"8.8.0\",\n \"eslint-plugin-ecmascript-compat\": \"^3.1.0\",\n \"eslint-plugin-import\": \"2.27.5\",\n \"prettier\": \"^2.8.8\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^4.5.0\"\n },\n \"packageManager\": \"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531\"\n}\n","import { MPMask } from '@mediapipe/tasks-vision';\n\n// Define the blur fragment shader\nconst blurFragmentShader = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D u_texture;\n uniform vec2 u_texelSize;\n uniform vec2 u_direction;\n uniform float u_radius;\n\n void main() {\n float sigma = u_radius;\n float twoSigmaSq = 2.0 * sigma * sigma;\n float totalWeight = 0.0;\n vec3 result = vec3(0.0);\n const int MAX_SAMPLES = 16;\n int radius = int(min(float(MAX_SAMPLES), ceil(u_radius)));\n\n for (int i = -MAX_SAMPLES; i <= MAX_SAMPLES; ++i) {\n float offset = float(i);\n if (abs(offset) > float(radius)) continue;\n float weight = exp(-(offset * offset) / twoSigmaSq);\n vec2 sampleCoord = texCoords + u_direction * u_texelSize * offset;\n result += texture2D(u_texture, sampleCoord).rgb * weight;\n totalWeight += weight;\n }\n\n gl_FragColor = vec4(result / totalWeight, 1.0);\n }\n`;\n\nconst createShaderProgram = (gl: WebGL2RenderingContext) => {\n const vs = `\n attribute vec2 position;\n varying vec2 texCoords;\n \n void main() {\n texCoords = (position + 1.0) / 2.0;\n texCoords.y = 1.0 - texCoords.y;\n gl_Position = vec4(position, 0, 1.0);\n }\n `;\n\n const cS = `\n precision highp float;\n varying vec2 texCoords;\n uniform sampler2D background;\n uniform sampler2D frame;\n uniform sampler2D mask;\n void main() {\n vec4 maskTex = texture2D(mask, texCoords); \n vec4 frameTex = texture2D(frame, texCoords);\n vec4 bgTex = texture2D(background, texCoords);\n \n \n float a = maskTex.r;\n \n gl_FragColor = mix(bgTex, vec4(frameTex.rgb, 1.0), 1.0 - a);\n \n }\n `;\n\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!vertexShader) {\n throw Error('can not create vertex shader');\n }\n gl.shaderSource(vertexShader, vs);\n gl.compileShader(vertexShader);\n\n // Create our fragment shader\n const compositeShader = gl.createShader(gl.FRAGMENT_SHADER);\n if (!compositeShader) {\n throw Error('can not create fragment shader');\n }\n gl.shaderSource(compositeShader, cS);\n gl.compileShader(compositeShader);\n\n // Create the composite program\n const compositeProgram = gl.createProgram();\n if (!compositeProgram) {\n throw Error('can not create composite program');\n }\n gl.attachShader(compositeProgram, vertexShader);\n gl.attachShader(compositeProgram, compositeShader);\n gl.linkProgram(compositeProgram);\n\n let blurProgram = null;\n let blurVertexShader = null;\n let blurFrag = null;\n let blurUniforms = null;\n\n // Create blur shader if enabled\n blurFrag = gl.createShader(gl.FRAGMENT_SHADER);\n if (!blurFrag) {\n throw Error('can not create blur shader');\n }\n gl.shaderSource(blurFrag, blurFragmentShader);\n gl.compileShader(blurFrag);\n\n // Get compile status and log errors if any\n if (!gl.getShaderParameter(blurFrag, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(blurFrag);\n throw Error(`Failed to compile blur shader: ${info}`);\n }\n\n // Create blur program\n blurVertexShader = gl.createShader(gl.VERTEX_SHADER);\n if (!blurVertexShader) {\n throw Error('can not create blur vertex shader');\n }\n gl.shaderSource(blurVertexShader, vs);\n gl.compileShader(blurVertexShader);\n\n blurProgram = gl.createProgram();\n if (!blurProgram) {\n throw Error('can not create blur program');\n }\n gl.attachShader(blurProgram, blurVertexShader);\n gl.attachShader(blurProgram, blurFrag);\n gl.linkProgram(blurProgram);\n\n // Check blur program link status\n if (!gl.getProgramParameter(blurProgram, gl.LINK_STATUS)) {\n const info = gl.getProgramInfoLog(blurProgram);\n throw Error(`Failed to link blur program: ${info}`);\n }\n\n blurUniforms = {\n position: gl.getAttribLocation(blurProgram, 'position'),\n texture: gl.getUniformLocation(blurProgram, 'u_texture'),\n texelSize: gl.getUniformLocation(blurProgram, 'u_texelSize'),\n direction: gl.getUniformLocation(blurProgram, 'u_direction'),\n radius: gl.getUniformLocation(blurProgram, 'u_radius'),\n };\n\n return {\n vertexShader,\n compositeShader,\n blurShader: blurFrag,\n compositeProgram,\n blurProgram,\n attribLocations: {\n position: gl.getAttribLocation(compositeProgram, 'position'),\n },\n uniformLocations: {\n mask: gl.getUniformLocation(compositeProgram, 'mask')!,\n frame: gl.getUniformLocation(compositeProgram, 'frame')!,\n background: gl.getUniformLocation(compositeProgram, 'background')!,\n },\n blurUniforms,\n };\n};\n\nexport function initTexture(gl: WebGL2RenderingContext, texIndex: number) {\n const texRef = gl.TEXTURE0 + texIndex;\n gl.activeTexture(texRef);\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n\n return texture;\n}\n\nexport function createFramebuffer(\n gl: WebGL2RenderingContext,\n texture: WebGLTexture,\n width: number,\n height: number,\n) {\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n\n // Set the texture as the color attachment\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n // Ensure texture dimensions match the provided width and height\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n // Check if framebuffer is complete\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer not complete');\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return framebuffer;\n}\n\nconst createVertexBuffer = (gl: WebGL2RenderingContext) => {\n if (!gl) {\n return null;\n }\n const vertexBuffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]),\n gl.STATIC_DRAW,\n );\n return vertexBuffer;\n};\n\nexport const setupWebGL = (canvas: OffscreenCanvas) => {\n const gl = canvas.getContext('webgl2', { premultipliedAlpha: false }) as WebGL2RenderingContext;\n\n let blurRadius: number | null = null;\n\n if (!gl) {\n return undefined;\n }\n\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n const {\n compositeProgram,\n blurProgram,\n attribLocations: { position: positionLocation },\n uniformLocations: {\n mask: maskTextureLocation,\n frame: frameTextureLocation,\n background: bgTextureLocation,\n },\n blurUniforms,\n } = createShaderProgram(gl);\n\n const bgTexture = initTexture(gl, 0);\n const frameTexture = initTexture(gl, 1);\n const vertexBuffer = createVertexBuffer(gl);\n\n // Create additional textures and framebuffers for processing\n let processTextures: WebGLTexture[] = [];\n let processFramebuffers: WebGLFramebuffer[] = [];\n\n // Create textures for processing (blur)\n processTextures.push(initTexture(gl, 3));\n processTextures.push(initTexture(gl, 4));\n\n // Create framebuffers for processing\n processFramebuffers.push(createFramebuffer(gl, processTextures[0], canvas.width, canvas.height));\n processFramebuffers.push(createFramebuffer(gl, processTextures[1], canvas.width, canvas.height));\n\n // Set up uniforms for the composite shader\n gl.useProgram(compositeProgram);\n gl.uniform1i(bgTextureLocation, 0);\n gl.uniform1i(frameTextureLocation, 1);\n gl.uniform1i(maskTextureLocation, 2);\n\n // Store custom background image\n let customBackgroundImage: ImageBitmap | null = null;\n\n function applyBlur(sourceTexture: WebGLTexture, width: number, height: number) {\n if (!blurRadius || !blurProgram || !blurUniforms) return bgTexture;\n\n gl.useProgram(blurProgram);\n\n // Set common attributes\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(blurUniforms.position, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(blurUniforms.position);\n\n const texelWidth = 1.0 / width;\n const texelHeight = 1.0 / height;\n\n // First pass - horizontal blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[0]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, sourceTexture);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.texelSize, texelWidth, texelHeight);\n gl.uniform2f(blurUniforms.direction, 1.0, 0.0); // Horizontal\n gl.uniform1f(blurUniforms.radius, blurRadius);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Second pass - vertical blur\n gl.bindFramebuffer(gl.FRAMEBUFFER, processFramebuffers[1]);\n gl.viewport(0, 0, width, height);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, processTextures[0]);\n gl.uniform1i(blurUniforms.texture, 0);\n gl.uniform2f(blurUniforms.direction, 0.0, 1.0); // Vertical\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Reset framebuffer\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n return processTextures[1];\n }\n\n function render(frame: VideoFrame, mask: MPMask) {\n if (frame.codedWidth === 0 || mask.width === 0) {\n return;\n }\n\n const width = frame.displayWidth;\n const height = frame.displayHeight;\n\n // Prepare frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);\n\n // Apply blur if enabled (and no custom background is set)\n let backgroundTexture = bgTexture;\n\n // If we have a custom background image, use that\n if (customBackgroundImage) {\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, customBackgroundImage);\n backgroundTexture = bgTexture;\n } else if (blurRadius) {\n // Otherwise, if blur is enabled, apply blur effect to the frame\n backgroundTexture = applyBlur(frameTexture, width, height);\n }\n\n // Get the mask texture\n const maskTexture = mask.getAsWebGLTexture();\n\n // Render the final composite\n gl.viewport(0, 0, width, height);\n gl.clearColor(1.0, 1.0, 1.0, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(compositeProgram);\n gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);\n gl.enableVertexAttribArray(positionLocation);\n\n // Set background texture (either original, blurred or custom)\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, backgroundTexture);\n gl.uniform1i(bgTextureLocation, 0);\n\n // Set frame texture\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, frameTexture);\n gl.uniform1i(frameTextureLocation, 1);\n\n // Set mask texture\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, maskTexture);\n gl.uniform1i(maskTextureLocation, 2);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n mask.close();\n }\n\n /**\n * Set or update the background image\n * @param image The background image to use, or null to clear\n */\n async function setBackgroundImage(image: ImageBitmap | null) {\n // Clear existing background\n customBackgroundImage = null;\n\n if (image) {\n try {\n // Get current canvas dimensions\n const canvasWidth = canvas.width;\n const canvasHeight = canvas.height;\n\n // Calculate dimensions and crop for \"cover\" mode\n const imgAspect = image.width / image.height;\n const canvasAspect = canvasWidth / canvasHeight;\n\n let sx = 0;\n let sy = 0;\n let sWidth = image.width;\n let sHeight = image.height;\n\n // For cover mode, we need to crop some parts of the image\n // to ensure it covers the canvas while maintaining aspect ratio\n if (imgAspect > canvasAspect) {\n // Image is wider than canvas - crop the sides\n sWidth = Math.round(image.height * canvasAspect);\n sx = Math.round((image.width - sWidth) / 2); // Center the crop horizontally\n } else if (imgAspect < canvasAspect) {\n // Image is taller than canvas - crop the top/bottom\n sHeight = Math.round(image.width / canvasAspect);\n sy = Math.round((image.height - sHeight) / 2); // Center the crop vertically\n }\n\n // Create a new ImageBitmap with the cropped portion\n const croppedImage = await createImageBitmap(image, sx, sy, sWidth, sHeight, {\n resizeWidth: canvasWidth,\n resizeHeight: canvasHeight,\n resizeQuality: 'medium',\n });\n\n // Store the cropped and resized image\n customBackgroundImage = croppedImage;\n\n // Load the image into the texture\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, croppedImage);\n } catch (error) {\n console.error('Error processing background image:', error);\n // Fallback to original image on error\n customBackgroundImage = image;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n }\n } else {\n // set the background texture to an empty 2x2 image\n const emptyImage = new ImageData(2, 2);\n emptyImage.data[0] = 0;\n emptyImage.data[1] = 0;\n emptyImage.data[2] = 0;\n emptyImage.data[3] = 0;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, bgTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, emptyImage);\n }\n }\n\n function setBlurRadius(radius: number | null) {\n blurRadius = radius;\n setBackgroundImage(null);\n }\n\n function cleanup() {\n gl.deleteProgram(compositeProgram);\n gl.deleteProgram(blurProgram);\n gl.deleteTexture(bgTexture);\n gl.deleteTexture(frameTexture);\n for (const texture of processTextures) {\n gl.deleteTexture(texture);\n }\n for (const framebuffer of processFramebuffers) {\n gl.deleteFramebuffer(framebuffer);\n }\n gl.deleteBuffer(vertexBuffer);\n\n // Release any ImageBitmap resources\n if (customBackgroundImage) {\n customBackgroundImage.close();\n customBackgroundImage = null;\n }\n processTextures = [];\n processFramebuffers = [];\n }\n\n return { render, setBackgroundImage, setBlurRadius, cleanup };\n};\n","import { setupWebGL } from '../webgl/index';\nimport { VideoTrackTransformer, VideoTransformerInitOptions } from './types';\n\nexport default abstract class VideoTransformer<Options extends Record<string, unknown>>\n implements VideoTrackTransformer<Options>\n{\n transformer?: TransformStream;\n\n canvas?: OffscreenCanvas;\n\n // ctx?: OffscreenCanvasRenderingContext2D;\n\n inputVideo?: HTMLVideoElement;\n\n gl?: ReturnType<typeof setupWebGL>;\n\n protected isDisabled?: Boolean = false;\n\n async init({\n outputCanvas,\n inputElement: inputVideo,\n }: VideoTransformerInitOptions): Promise<void> {\n if (!(inputVideo instanceof HTMLVideoElement)) {\n throw TypeError('Video transformer needs a HTMLVideoElement as input');\n }\n\n this.transformer = new TransformStream({\n transform: (frame, controller) => this.transform(frame, controller),\n });\n this.canvas = outputCanvas || null;\n if (outputCanvas) {\n // this.ctx = this.canvas?.getContext('2d') || undefined;\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n }\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async restart({ outputCanvas, inputElement: inputVideo }: VideoTransformerInitOptions) {\n this.canvas = outputCanvas || null;\n this.gl?.cleanup();\n this.gl = setupWebGL(\n this.canvas || new OffscreenCanvas(inputVideo.videoWidth, inputVideo.videoHeight),\n );\n\n this.inputVideo = inputVideo;\n this.isDisabled = false;\n }\n\n async destroy() {\n this.isDisabled = true;\n this.canvas = undefined;\n this.gl?.cleanup();\n this.gl = undefined;\n }\n\n abstract transform(\n frame: VideoFrame,\n controller: TransformStreamDefaultController<VideoFrame>,\n ): void;\n\n abstract update(options: Options): void;\n}\n","import ProcessorWrapper, { ProcessorWrapperOptions } from './ProcessorWrapper';\nimport BackgroundTransformer, {\n BackgroundOptions,\n FrameProcessingStats,\n SegmenterOptions,\n} from './transformers/BackgroundTransformer';\n\nexport * from './transformers/types';\nexport { default as VideoTransformer } from './transformers/VideoTransformer';\nexport {\n ProcessorWrapper,\n type BackgroundOptions,\n type SegmenterOptions,\n BackgroundTransformer,\n type ProcessorWrapperOptions,\n};\n\n/**\n * Determines if the current browser supports background processors\n */\nexport const supportsBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.isSupported;\n\n/**\n * Determines if the current browser supports modern background processors, which yield better performance\n */\nexport const supportsModernBackgroundProcessors = () =>\n BackgroundTransformer.isSupported && ProcessorWrapper.hasModernApiSupport;\n\nexport interface BackgroundProcessorOptions extends ProcessorWrapperOptions {\n blurRadius?: number;\n imagePath?: string;\n segmenterOptions?: SegmenterOptions;\n assetPaths?: { tasksVisionFileSet?: string; modelAssetPath?: string };\n onFrameProcessed?: (stats: FrameProcessingStats) => void;\n}\n\nexport const BackgroundBlur = (\n blurRadius: number = 10,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n blurRadius,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'background-blur',\n );\n};\n\nexport const VirtualBackground = (\n imagePath: string,\n segmenterOptions?: SegmenterOptions,\n onFrameProcessed?: (stats: FrameProcessingStats) => void,\n processorOptions?: ProcessorWrapperOptions,\n) => {\n return BackgroundProcessor(\n {\n imagePath,\n segmenterOptions,\n onFrameProcessed,\n ...processorOptions,\n },\n 'virtual-background',\n );\n};\n\nexport const BackgroundProcessor = (\n options: BackgroundProcessorOptions,\n name = 'background-processor',\n) => {\n const isTransformerSupported = BackgroundTransformer.isSupported;\n const isProcessorSupported = ProcessorWrapper.isSupported;\n\n if (!isTransformerSupported) {\n throw new Error('Background transformer is not supported in this browser');\n }\n\n if (!isProcessorSupported) {\n throw new Error(\n 'Neither MediaStreamTrackProcessor nor canvas.captureStream() fallback is supported in this browser',\n );\n }\n\n // Extract transformer-specific options and processor options\n const {\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n ...processorOpts\n } = options;\n\n const processor = new ProcessorWrapper(\n new BackgroundTransformer({\n blurRadius,\n imagePath,\n segmenterOptions,\n assetPaths,\n onFrameProcessed,\n }),\n name,\n processorOpts,\n );\n\n return processor;\n};\n"],"mappings":"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","names":["_a","BackgroundProcessor"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livekit/track-processors",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "LiveKit track processors",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -14,7 +14,7 @@
14
14
  "src"
15
15
  ],
16
16
  "dependencies": {
17
- "@mediapipe/tasks-vision": "^0.10.22-rc.20250304"
17
+ "@mediapipe/tasks-vision": "0.10.14"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "livekit-client": "^1.12.0 || ^2.1.0"