@meframe/core 0.0.6 → 0.0.7
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/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +1 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/types.d.ts +1 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +0 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +24 -37
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/VideoClipSession.d.ts +1 -0
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
- package/dist/orchestrator/VideoClipSession.js +96 -82
- package/dist/orchestrator/VideoClipSession.js.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.js +11 -3
- package/dist/stages/compose/GlobalAudioSession.js.map +1 -1
- package/dist/stages/load/ResourceLoader.js +1 -1
- package/dist/stages/load/ResourceLoader.js.map +1 -1
- package/dist/worker/WorkerPool.d.ts.map +1 -1
- package/dist/worker/WorkerPool.js +6 -2
- package/dist/worker/WorkerPool.js.map +1 -1
- package/dist/worker/types.d.ts +1 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/types.js.map +1 -1
- package/dist/worker/worker-event-whitelist.d.ts.map +1 -1
- package/dist/workers/BaseDecoder.js +130 -0
- package/dist/workers/BaseDecoder.js.map +1 -0
- package/dist/workers/WorkerChannel.js.map +1 -1
- package/dist/workers/stages/compose/video-compose.worker.js +13 -9
- package/dist/workers/stages/compose/video-compose.worker.js.map +1 -1
- package/dist/workers/stages/decode/audio-decode.worker.js +243 -0
- package/dist/workers/stages/decode/audio-decode.worker.js.map +1 -0
- package/dist/workers/stages/decode/video-decode.worker.js +346 -0
- package/dist/workers/stages/decode/video-decode.worker.js.map +1 -0
- package/dist/workers/stages/encode/video-encode.worker.js +340 -0
- package/dist/workers/stages/encode/video-encode.worker.js.map +1 -0
- package/package.json +1 -1
- package/dist/workers/stages/decode/decode.worker.js +0 -826
- package/dist/workers/stages/decode/decode.worker.js.map +0 -1
- package/dist/workers/stages/encode/encode.worker.js +0 -547
- package/dist/workers/stages/encode/encode.worker.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"encode.worker.js","sources":["../../../../src/stages/encode/BaseEncoder.ts","../../../../src/stages/encode/VideoChunkEncoder.ts","../../../../src/stages/encode/AudioChunkEncoder.ts","../../../../src/stages/encode/ClipEncoderManager.ts","../../../../src/stages/encode/encode.worker.ts"],"sourcesContent":["// Base encoder implementation\n\n/**\n * Base encoder class for both video and audio encoding\n * Handles common WebCodecs encoder operations\n */\n\nexport interface EncoderChunk {\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n}\n\nexport abstract class BaseEncoder<\n TEncoder extends VideoEncoder | AudioEncoder,\n TConfig extends VideoEncoderConfig | AudioEncoderConfig,\n TInput extends VideoFrame | AudioData,\n TChunk extends EncodedVideoChunk | EncodedAudioChunk,\n TMetadata extends EncodedVideoChunkMetadata | EncodedAudioChunkMetadata,\n> {\n protected encoder?: TEncoder;\n protected config: TConfig;\n protected controller: TransformStreamDefaultController<EncoderChunk> | null = null;\n\n constructor(config: TConfig) {\n this.config = config;\n }\n\n getConfig(): TConfig {\n return { ...this.config };\n }\n\n protected get currentConfig(): TConfig {\n return this.config;\n }\n\n protected shouldReconfigure(partial: Partial<TConfig>): boolean {\n const next = { ...this.config, ...partial } as TConfig;\n const keys = Object.keys(partial ?? {}) as Array<keyof TConfig>;\n for (const key of keys) {\n if (partial[key] !== undefined && next[key] !== this.config[key]) {\n return true;\n }\n }\n return false;\n }\n\n protected hasConfigChanged(next: TConfig): boolean {\n const currentEntries = Object.entries(this.config) as Array<[keyof TConfig, any]>;\n for (const [key, value] of currentEntries) {\n if (next[key] !== value) {\n return true;\n }\n }\n\n for (const key of Object.keys(next) as Array<keyof TConfig>) {\n if (this.config[key] !== next[key]) {\n return true;\n }\n }\n\n return false;\n }\n\n protected configsEqual(a: TConfig, b: TConfig): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n }\n\n async initialize(): Promise<void> {\n if (this.encoder?.state === 'configured') {\n return;\n }\n\n const isSupported = await this.isConfigSupported(this.config);\n if (!isSupported.supported) {\n throw new Error(`Codec not supported: ${JSON.stringify(this.config)}`);\n }\n\n this.encoder = this.createEncoder({\n output: this.handleOutput.bind(this),\n error: this.handleError.bind(this),\n });\n\n (this.encoder as any).configure(this.config);\n }\n\n async reconfigure(config: Partial<TConfig>): Promise<void> {\n if (!config || Object.keys(config).length === 0) {\n return;\n }\n\n const nextConfig = { ...this.config, ...config } as TConfig;\n\n if (this.configsEqual(this.config, nextConfig)) {\n return;\n }\n\n if (!this.encoder) {\n this.config = nextConfig;\n await this.initialize();\n return;\n }\n\n if (this.encoder.state === 'configured') {\n await this.encoder.flush();\n }\n\n const isSupported = await this.isConfigSupported(nextConfig);\n if (!isSupported.supported) {\n throw new Error(`New configuration not supported: ${nextConfig.codec}`);\n }\n\n this.config = nextConfig;\n (this.encoder as any).configure(this.config);\n }\n\n async flush(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n await this.encoder.flush();\n }\n\n async reset(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n this.encoder.reset();\n this.onReset();\n }\n\n async close(): Promise<void> {\n if (!this.encoder) {\n return;\n }\n\n if (this.encoder.state === 'configured') {\n await this.encoder.flush();\n }\n\n this.encoder.close();\n this.encoder = undefined;\n }\n\n get isReady(): boolean {\n return this.encoder?.state === 'configured';\n }\n\n get queueSize(): number {\n return this.encoder?.encodeQueueSize ?? 0;\n }\n\n protected handleOutput(chunk: TChunk, metadata: TMetadata): void {\n // Only enqueue if controller exists and stream is not closed\n if (this.controller) {\n try {\n this.controller.enqueue({ chunk, metadata });\n } catch (error) {\n // Stream may be closed during flush, ignore enqueue errors\n if (!(error instanceof TypeError && error.message.includes('closed'))) {\n throw error;\n }\n }\n }\n }\n\n protected handleError(error: DOMException): void {\n console.error(`${this.getEncoderType()} encoder error:`, error);\n this.controller?.error(error);\n }\n\n // Abstract methods to be implemented by subclasses\n protected abstract isConfigSupported(config: TConfig): Promise<{ supported: boolean }>;\n protected abstract createEncoder(init: EncoderInit): TEncoder;\n protected abstract getEncoderType(): string;\n\n // Hook for subclasses to handle reset\n protected onReset(): void {\n // Override in subclasses if needed\n }\n\n // Abstract properties for backpressure configuration\n protected abstract readonly highWaterMark: number;\n protected abstract readonly encodeQueueThreshold: number;\n\n /**\n * Create transform stream for encoding\n * Implements common stream logic with backpressure handling\n */\n createStream(): TransformStream<TInput, EncoderChunk> {\n return new TransformStream<TInput, EncoderChunk>(\n {\n start: async (controller) => {\n this.controller = controller;\n\n // Initialize encoder if not already initialized\n if (!this.isReady) {\n await this.initialize();\n }\n },\n\n transform: async (input) => {\n if (!this.encoder || this.encoder.state !== 'configured') {\n throw new Error('Encoder not configured');\n }\n\n // Check encoder queue pressure\n if (this.encoder.encodeQueueSize >= this.encodeQueueThreshold) {\n // Wait for queue to drain\n await new Promise<void>((resolve) => {\n const check = () => {\n if (!this.encoder || this.encoder.encodeQueueSize < this.encodeQueueThreshold - 1) {\n resolve();\n } else {\n setTimeout(check, 10);\n }\n };\n check();\n });\n }\n\n // Encode the input\n const frame = (input as any).frame || input;\n this.encode(frame);\n },\n\n flush: async () => {\n await this.flush();\n },\n },\n // Queuing strategy with backpressure configuration\n {\n highWaterMark: this.highWaterMark,\n size: () => 1, // Count-based\n }\n );\n }\n\n // Abstract method for encoding\n abstract encode(input: TInput): void;\n}\n\ninterface EncoderInit {\n output: (chunk: any, metadata: any) => void;\n error: (error: DOMException) => void;\n}\n","import { BaseEncoder } from './BaseEncoder';\nimport type { VideoEncoderConfig } from './types';\n\n/**\n * VideoChunkEncoder - Encodes VideoFrame to EncodedVideoChunk\n * Stream-based encoder with backpressure handling\n */\nexport class VideoChunkEncoder extends BaseEncoder<\n VideoEncoder,\n VideoEncoderConfig,\n VideoFrame,\n EncodedVideoChunk,\n EncodedVideoChunkMetadata\n> {\n private static readonly DEFAULT_HIGH_WATER_MARK = 2;\n private static readonly DEFAULT_ENCODE_QUEUE_THRESHOLD = 8;\n\n protected readonly highWaterMark: number;\n protected readonly encodeQueueThreshold: number;\n\n private frameCount = 0;\n private keyFrameInterval = 60; // 2 seconds at 30fps\n\n constructor(config: VideoEncoderConfig) {\n super(config);\n\n // Initialize backpressure settings from config or use defaults\n this.highWaterMark =\n config.backpressure?.highWaterMark ?? VideoChunkEncoder.DEFAULT_HIGH_WATER_MARK;\n this.encodeQueueThreshold =\n config.backpressure?.encodeQueueThreshold ?? VideoChunkEncoder.DEFAULT_ENCODE_QUEUE_THRESHOLD;\n }\n\n protected async isConfigSupported(config: VideoEncoderConfig): Promise<{ supported: boolean }> {\n const result = await VideoEncoder.isConfigSupported(config);\n return { supported: result.supported ?? false };\n }\n\n protected createEncoder(init: VideoEncoderInit): VideoEncoder {\n return new VideoEncoder(init);\n }\n\n protected getEncoderType(): string {\n return 'Video';\n }\n\n protected override onReset(): void {\n this.frameCount = 0;\n }\n\n encode(frame: VideoFrame): void {\n const keyFrame = this.shouldGenerateKeyFrame();\n const encodeOptions: VideoEncoderEncodeOptions = {\n keyFrame,\n };\n\n this.encoder!.encode(frame, encodeOptions);\n this.frameCount++;\n frame.close();\n }\n\n setKeyFrameInterval(interval: number): void {\n this.keyFrameInterval = Math.max(1, interval);\n }\n\n private shouldGenerateKeyFrame(): boolean {\n if (this.frameCount === 0) {\n return true;\n }\n return this.frameCount % this.keyFrameInterval === 0;\n }\n}\n","import { BaseEncoder } from './BaseEncoder';\nimport type { AudioEncoderConfig } from './types';\n\n/**\n * AudioChunkEncoder - Encodes AudioData to EncodedAudioChunk\n * Stream-based encoder with backpressure handling\n */\nexport class AudioChunkEncoder extends BaseEncoder<\n AudioEncoder,\n AudioEncoderConfig,\n AudioData,\n EncodedAudioChunk,\n EncodedAudioChunkMetadata\n> {\n private static readonly DEFAULT_HIGH_WATER_MARK = 4;\n private static readonly DEFAULT_ENCODE_QUEUE_THRESHOLD = 16;\n\n static readonly DEFAULT_CONFIG: AudioEncoderConfig = {\n codec: 'mp4a.40.2', // AAC-LC\n sampleRate: 48000,\n numberOfChannels: 2,\n bitrate: 128000,\n };\n\n protected readonly highWaterMark: number;\n protected readonly encodeQueueThreshold: number;\n\n constructor(config?: Partial<AudioEncoderConfig>) {\n const fullConfig = { ...AudioChunkEncoder.DEFAULT_CONFIG, ...config };\n super(fullConfig);\n\n // Initialize backpressure settings from config or use defaults\n this.highWaterMark =\n fullConfig.backpressure?.highWaterMark ?? AudioChunkEncoder.DEFAULT_HIGH_WATER_MARK;\n this.encodeQueueThreshold =\n fullConfig.backpressure?.encodeQueueThreshold ??\n AudioChunkEncoder.DEFAULT_ENCODE_QUEUE_THRESHOLD;\n }\n\n protected async isConfigSupported(config: AudioEncoderConfig): Promise<{ supported: boolean }> {\n const result = await AudioEncoder.isConfigSupported(config);\n return { supported: result.supported ?? false };\n }\n\n protected createEncoder(init: AudioEncoderInit): AudioEncoder {\n return new AudioEncoder(init);\n }\n\n protected getEncoderType(): string {\n return 'Audio';\n }\n\n encode(data: AudioData): void {\n if (this.encoder?.state !== 'configured') {\n throw new Error('Audio encoder not configured');\n }\n\n this.encoder.encode(data);\n data.close();\n }\n}\n","import { VideoChunkEncoder } from './VideoChunkEncoder';\nimport { AudioChunkEncoder } from './AudioChunkEncoder';\nimport type { VideoEncoderConfig, AudioEncoderConfig } from './types';\n\n/**\n * ClipEncoderManager - Per-Clip Encoder Instance Manager\n *\n * Responsibilities:\n * - Maintain separate encoder instances per clip (avoid frameCount pollution)\n * - Limit concurrent encoder instances (maxEncoders = 6)\n * - FIFO eviction strategy\n *\n * Note: This is NOT a traditional object pool, as it does not support\n * cross-clip instance reuse. Each sessionId gets its own dedicated encoder\n * that is destroyed (not recycled) when released.\n */\nexport class ClipEncoderManager {\n private videoEncoders = new Map<string, VideoChunkEncoder>();\n private audioEncoders = new Map<string, AudioChunkEncoder>();\n private videoCreationOrder: string[] = [];\n private audioCreationOrder: string[] = [];\n private readonly maxEncoders: number;\n\n constructor(maxEncoders = 6) {\n this.maxEncoders = maxEncoders;\n }\n\n /**\n * Acquire a video encoder for the given sessionId\n * Creates new encoder if not exists; returns existing one if already created\n */\n async acquireVideo(sessionId: string, config: VideoEncoderConfig): Promise<VideoChunkEncoder> {\n let encoder = this.videoEncoders.get(sessionId);\n\n if (!encoder) {\n // Check limit - throw error instead of auto-evicting\n // Auto-eviction is dangerous because encoder might still be in use by active streams\n if (this.videoEncoders.size >= this.maxEncoders) {\n throw new Error(\n `[ClipEncoderManager] Video encoder limit reached (${this.maxEncoders}). ` +\n `Active clips: ${Array.from(this.videoEncoders.keys()).join(', ')}. ` +\n `Please release unused encoders before acquiring new ones.`\n );\n }\n\n // Create new encoder\n encoder = new VideoChunkEncoder(config);\n await encoder.initialize();\n\n this.videoEncoders.set(sessionId, encoder);\n this.videoCreationOrder.push(sessionId);\n }\n\n return encoder;\n }\n\n /**\n * Acquire an audio encoder for the given sessionId\n */\n async acquireAudio(sessionId: string, config: AudioEncoderConfig): Promise<AudioChunkEncoder> {\n let encoder = this.audioEncoders.get(sessionId);\n\n if (!encoder) {\n // Check limit - throw error instead of auto-evicting\n if (this.audioEncoders.size >= this.maxEncoders) {\n throw new Error(\n `[ClipEncoderManager] Audio encoder limit reached (${this.maxEncoders}). ` +\n `Active clips: ${Array.from(this.audioEncoders.keys()).join(', ')}. ` +\n `Please release unused encoders before acquiring new ones.`\n );\n }\n\n // Create new encoder\n encoder = new AudioChunkEncoder(config);\n await encoder.initialize();\n\n this.audioEncoders.set(sessionId, encoder);\n this.audioCreationOrder.push(sessionId);\n }\n\n return encoder;\n }\n\n /**\n * Release video encoder for the given sessionId\n */\n async releaseVideo(sessionId: string): Promise<void> {\n const encoder = this.videoEncoders.get(sessionId);\n if (encoder) {\n await encoder.close();\n this.videoEncoders.delete(sessionId);\n\n // Remove from creation order\n const index = this.videoCreationOrder.indexOf(sessionId);\n if (index !== -1) {\n this.videoCreationOrder.splice(index, 1);\n }\n }\n }\n\n /**\n * Release audio encoder for the given sessionId\n */\n async releaseAudio(sessionId: string): Promise<void> {\n const encoder = this.audioEncoders.get(sessionId);\n if (encoder) {\n await encoder.close();\n this.audioEncoders.delete(sessionId);\n\n // Remove from creation order\n const index = this.audioCreationOrder.indexOf(sessionId);\n if (index !== -1) {\n this.audioCreationOrder.splice(index, 1);\n }\n }\n }\n\n /**\n * Release both video and audio encoders for the given sessionId\n */\n async releaseClip(sessionId: string): Promise<void> {\n await Promise.all([this.releaseVideo(sessionId), this.releaseAudio(sessionId)]);\n }\n\n /**\n * Close all encoders and clear state\n */\n async closeAll(): Promise<void> {\n const promises = [\n ...Array.from(this.videoEncoders.values()).map((e) => e.close()),\n ...Array.from(this.audioEncoders.values()).map((e) => e.close()),\n ];\n\n await Promise.all(promises);\n\n this.videoEncoders.clear();\n this.audioEncoders.clear();\n this.videoCreationOrder = [];\n this.audioCreationOrder = [];\n }\n\n /**\n * Check if encoders exist for the given sessionId\n */\n has(sessionId: string): boolean {\n return this.videoEncoders.has(sessionId) || this.audioEncoders.has(sessionId);\n }\n\n /**\n * Get statistics about current encoder state\n */\n getStats() {\n return {\n videoEncoders: this.videoEncoders.size,\n audioEncoders: this.audioEncoders.size,\n maxEncoders: this.maxEncoders,\n videoCreationOrder: [...this.videoCreationOrder],\n audioCreationOrder: [...this.audioCreationOrder],\n };\n }\n}\n","import { WorkerChannel } from '../../worker/WorkerChannel';\nimport { WorkerMessageType, WorkerState } from '../../worker/types';\nimport { VideoChunkEncoder } from './VideoChunkEncoder';\nimport { AudioChunkEncoder } from './AudioChunkEncoder';\nimport { VideoEncoderConfig, AudioEncoderConfig } from './types';\nimport { ClipEncoderManager } from './ClipEncoderManager';\n\n/**\n * EncodeWorker - Seventh stage in the pipeline\n * Receives composed frames from ComposeWorkers and outputs encoded chunks to CacheManager/MuxWorker\n *\n * Pipeline: VideoComposeWorker/AudioComposeWorker → EncodeWorker → CacheManager/MuxWorker\n *\n * Features:\n * - Hardware-accelerated encoding via WebCodecs\n * - Configurable bitrate and quality settings\n * - Batch flush for efficient I/O (0.5s batches)\n * - Direct streaming to cache/mux workers\n */\nclass EncodeWorker {\n private channel: WorkerChannel;\n private encoderManager = new ClipEncoderManager(12); // Increased to prevent eviction during active streams\n\n // Default encoder configs\n private defaultVideoConfig: VideoEncoderConfig | null = null;\n private defaultAudioConfig: AudioEncoderConfig | null = null;\n\n // Connections to other workers\n private muxPort: MessagePort | null = null;\n private composePorts = new Map<string, MessagePort>(); // Connections from compose workers\n\n constructor() {\n // Initialize WorkerChannel with MessagePort\n this.channel = new WorkerChannel(self as any, {\n name: 'EncodeWorker',\n timeout: 30000,\n });\n\n this.setupHandlers();\n }\n\n private setupHandlers(): void {\n // Register message handlers\n this.channel.registerHandler('configure', this.handleConfigure.bind(this));\n this.channel.registerHandler('connect', this.handleConnect.bind(this));\n this.channel.registerHandler('configure_video', this.handleConfigureVideo.bind(this));\n this.channel.registerHandler('flush', this.handleFlush.bind(this));\n this.channel.registerHandler('reset', this.handleReset.bind(this));\n this.channel.registerHandler('release_clip_encoder', this.handleReleaseClipEncoder.bind(this));\n this.channel.registerHandler('get_stats', this.handleGetStats.bind(this));\n this.channel.registerHandler(WorkerMessageType.Dispose, this.handleDispose.bind(this));\n }\n\n /**\n * Connect handler used by stream pipeline\n */\n private async handleConnect(payload: {\n direction: 'upstream' | 'downstream';\n port: MessagePort;\n streamType: 'video' | 'audio' | 'frame' | 'chunk';\n sessionId?: string;\n }): Promise<{ success: boolean }> {\n const { port, streamType, sessionId } = payload;\n\n if (streamType === 'video') {\n return this.handleConnectComposer({ composeType: 'video', port, sessionId });\n }\n if (streamType === 'audio') {\n return this.handleConnectComposer({ composeType: 'audio', port, sessionId });\n }\n if (streamType === 'chunk') return this.handleConnectMux({ port });\n return { success: true };\n }\n\n /**\n * Handle configuration message from orchestrator\n * @param payload.initial - If true, initialize worker; saves default encoder configs\n */\n private async handleConfigure(payload: {\n config: {\n video?: Partial<VideoEncoderConfig> & { stream?: ReadableStream<VideoFrame> };\n audio?: Partial<AudioEncoderConfig> & { stream?: ReadableStream<AudioData> };\n };\n initial?: boolean;\n }): Promise<{ success: boolean }> {\n const { config, initial = false } = payload;\n\n // Set worker state to ready on initial configuration\n if (initial) {\n this.channel.state = WorkerState.Ready;\n }\n\n // Save default encoder configs (used when creating per-clip encoders)\n if (config.video) {\n this.defaultVideoConfig = config.video as VideoEncoderConfig;\n }\n\n if (config.audio) {\n this.defaultAudioConfig = config.audio as AudioEncoderConfig;\n }\n\n return { success: true };\n }\n\n /**\n * Connect to a compose worker to receive frames/audio data\n */\n private async handleConnectComposer(payload: {\n composeType: 'video' | 'audio';\n port: MessagePort;\n sessionId?: string;\n }): Promise<{ success: boolean }> {\n const { composeType, port, sessionId } = payload;\n\n // Store the port\n this.composePorts.set(composeType, port);\n\n // Setup channel for receiving streams\n const composeChannel = new WorkerChannel(port, {\n name: `Encode-${composeType}Compose`,\n timeout: 30000,\n });\n // Receive stream from composer\n composeChannel.receiveStream(async (stream, metadata) => {\n // Extract sessionId from metadata or use the one from connection\n const streamSessionId = (metadata as any)?.sessionId || sessionId || 'unknown';\n\n if (metadata?.streamType === 'video' && this.defaultVideoConfig) {\n // Acquire session-specific video encoder\n const encoder = await this.encoderManager.acquireVideo(\n streamSessionId,\n this.defaultVideoConfig\n );\n\n // Create encoding stream pipeline - pipeThrough returns the readable side\n const encodingTransform = encoder.createStream();\n const encodedStream = (stream as unknown as ReadableStream<VideoFrame>).pipeThrough(\n encodingTransform\n );\n\n // Send encoded chunks back to main thread\n this.channel.sendStream(encodedStream, {\n streamType: 'video',\n track: 'video',\n sessionId: streamSessionId,\n });\n }\n });\n\n return { success: true };\n }\n\n /**\n * Connect to cache manager for output streaming\n */\n // private async handleConnectCache(payload: { port: MessagePort }): Promise<{ success: boolean }> {\n // this.cachePort = payload.port;\n // return { success: true };\n // }\n\n /**\n * Connect to mux worker for output streaming\n */\n private async handleConnectMux(payload: { port: MessagePort }): Promise<{ success: boolean }> {\n this.muxPort = payload.port;\n return { success: true };\n }\n\n /**\n * Configure video encoder with specific settings\n */\n private async handleConfigureVideo(config: VideoEncoderConfig): Promise<{ success: boolean }> {\n try {\n // Update default video config\n this.defaultVideoConfig = config;\n\n // Notify configuration complete\n this.channel.notify('video_configured', {\n codec: config.codec,\n width: config.width,\n height: config.height,\n bitrate: config.bitrate,\n });\n\n return { success: true };\n } catch (error: any) {\n throw {\n code: 'VIDEO_CONFIG_ERROR',\n message: error.message,\n };\n }\n }\n\n /**\n * Flush encoders (deprecated with per-clip encoder architecture)\n */\n private async handleFlush(_payload?: { type?: 'video' | 'audio' }): Promise<{\n videoChunks?: any[];\n audioChunks?: any[];\n }> {\n // With per-clip encoders, flushing is handled automatically by streams\n // This method is kept for backward compatibility\n console.warn('[EncodeWorker] handleFlush is deprecated with per-clip encoder architecture');\n return {};\n }\n\n /**\n * Reset encoders (deprecated with per-clip encoder architecture)\n */\n private async handleReset(payload?: { type?: 'video' | 'audio' }): Promise<{ success: boolean }> {\n // With per-clip encoders, reset is handled by releasing and recreating clip encoders\n // This method is kept for backward compatibility\n console.warn('[EncodeWorker] handleReset is deprecated with per-clip encoder architecture');\n\n // Notify reset complete for compatibility\n this.channel.notify('reset_complete', {\n type: payload?.type || 'all',\n });\n\n return { success: true };\n }\n\n /**\n * Release encoder for a specific clip\n */\n private async handleReleaseClipEncoder(payload: {\n sessionId: string;\n }): Promise<{ success: boolean }> {\n const { sessionId } = payload;\n\n await this.encoderManager.releaseClip(sessionId);\n\n return { success: true };\n }\n\n /**\n * Get encoder statistics\n */\n private async handleGetStats(): Promise<{\n encoders?: any;\n video?: any;\n audio?: any;\n }> {\n const stats: any = {\n encoders: this.encoderManager.getStats(),\n };\n\n return stats;\n }\n\n /**\n * Dispose worker and cleanup resources\n */\n private async handleDispose(): Promise<{ success: boolean }> {\n // Close all encoders in the manager\n await this.encoderManager.closeAll();\n\n // Clear default configs\n this.defaultVideoConfig = null;\n this.defaultAudioConfig = null;\n\n // Close connections\n this.muxPort?.close();\n this.muxPort = null;\n\n for (const port of this.composePorts.values()) {\n port.close();\n }\n this.composePorts.clear();\n\n this.channel.state = WorkerState.Disposed;\n\n return { success: true };\n }\n}\n\n// Initialize worker\nconst worker = new EncodeWorker();\n\n// Handle worker termination\nself.addEventListener('beforeunload', () => {\n worker['handleDispose']();\n});\n\nexport default null; // Required for TypeScript worker compilation\n"],"names":[],"mappings":"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"}
|