@meframe/core 0.1.7 → 0.1.8

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.
Files changed (64) hide show
  1. package/dist/cache/CacheManager.d.ts.map +1 -1
  2. package/dist/cache/CacheManager.js +3 -2
  3. package/dist/cache/CacheManager.js.map +1 -1
  4. package/dist/cache/l1/AudioL1Cache.d.ts +3 -0
  5. package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -1
  6. package/dist/cache/l1/AudioL1Cache.js +27 -33
  7. package/dist/cache/l1/AudioL1Cache.js.map +1 -1
  8. package/dist/controllers/PlaybackController.d.ts +2 -0
  9. package/dist/controllers/PlaybackController.d.ts.map +1 -1
  10. package/dist/controllers/PlaybackController.js +82 -13
  11. package/dist/controllers/PlaybackController.js.map +1 -1
  12. package/dist/controllers/PlaybackStateMachine.d.ts.map +1 -1
  13. package/dist/controllers/PlaybackStateMachine.js +13 -8
  14. package/dist/controllers/PlaybackStateMachine.js.map +1 -1
  15. package/dist/controllers/types.d.ts +10 -3
  16. package/dist/controllers/types.d.ts.map +1 -1
  17. package/dist/controllers/types.js +1 -0
  18. package/dist/controllers/types.js.map +1 -1
  19. package/dist/model/types.d.ts +0 -1
  20. package/dist/model/types.d.ts.map +1 -1
  21. package/dist/model/types.js.map +1 -1
  22. package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
  23. package/dist/orchestrator/ExportScheduler.js +22 -19
  24. package/dist/orchestrator/ExportScheduler.js.map +1 -1
  25. package/dist/orchestrator/GlobalAudioSession.d.ts +14 -1
  26. package/dist/orchestrator/GlobalAudioSession.d.ts.map +1 -1
  27. package/dist/orchestrator/GlobalAudioSession.js +39 -10
  28. package/dist/orchestrator/GlobalAudioSession.js.map +1 -1
  29. package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
  30. package/dist/orchestrator/Orchestrator.js +8 -3
  31. package/dist/orchestrator/Orchestrator.js.map +1 -1
  32. package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
  33. package/dist/orchestrator/VideoClipSession.js +4 -2
  34. package/dist/orchestrator/VideoClipSession.js.map +1 -1
  35. package/dist/orchestrator/types.d.ts +7 -1
  36. package/dist/orchestrator/types.d.ts.map +1 -1
  37. package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
  38. package/dist/stages/load/ResourceLoader.js +13 -6
  39. package/dist/stages/load/ResourceLoader.js.map +1 -1
  40. package/dist/worker/BaseWorker.d.ts +2 -0
  41. package/dist/worker/BaseWorker.d.ts.map +1 -1
  42. package/dist/worker/BaseWorker.js.map +1 -1
  43. package/dist/worker/WorkerChannel.d.ts +2 -0
  44. package/dist/worker/WorkerChannel.d.ts.map +1 -1
  45. package/dist/worker/WorkerChannel.js +17 -1
  46. package/dist/worker/WorkerChannel.js.map +1 -1
  47. package/dist/workers/{WorkerChannel.DjBEVvEA.js → WorkerChannel.DQK8rAab.js} +18 -2
  48. package/dist/workers/{WorkerChannel.DjBEVvEA.js.map → WorkerChannel.DQK8rAab.js.map} +1 -1
  49. package/dist/workers/stages/compose/{audio-compose.worker.CiM_KP27.js → audio-compose.worker.B4Io5w9i.js} +2 -2
  50. package/dist/workers/stages/compose/{audio-compose.worker.CiM_KP27.js.map → audio-compose.worker.B4Io5w9i.js.map} +1 -1
  51. package/dist/workers/stages/compose/{video-compose.worker.CQwmNfXT.js → video-compose.worker.CA2_Kpg-.js} +2 -2
  52. package/dist/workers/stages/compose/{video-compose.worker.CQwmNfXT.js.map → video-compose.worker.CA2_Kpg-.js.map} +1 -1
  53. package/dist/workers/stages/decode/{audio-decode.worker.CpjkrZtT.js → audio-decode.worker.-DGlQrJD.js} +2 -2
  54. package/dist/workers/stages/decode/{audio-decode.worker.CpjkrZtT.js.map → audio-decode.worker.-DGlQrJD.js.map} +1 -1
  55. package/dist/workers/stages/decode/{video-decode.worker.BQtw6eWn.js → video-decode.worker.BnWVUkng.js} +2 -2
  56. package/dist/workers/stages/decode/{video-decode.worker.BQtw6eWn.js.map → video-decode.worker.BnWVUkng.js.map} +1 -1
  57. package/dist/workers/stages/demux/{audio-demux.worker.C4V11GQi.js → audio-demux.worker.D-_LoVqW.js} +2 -2
  58. package/dist/workers/stages/demux/{audio-demux.worker.C4V11GQi.js.map → audio-demux.worker.D-_LoVqW.js.map} +1 -1
  59. package/dist/workers/stages/demux/{video-demux.worker.5pJr0Ij-.js → video-demux.worker.BWDrLGni.js} +2 -2
  60. package/dist/workers/stages/demux/{video-demux.worker.5pJr0Ij-.js.map → video-demux.worker.BWDrLGni.js.map} +1 -1
  61. package/dist/workers/stages/encode/{video-encode.worker.CX2_3YhQ.js → video-encode.worker.D6aB_rF9.js} +2 -2
  62. package/dist/workers/stages/encode/{video-encode.worker.CX2_3YhQ.js.map → video-encode.worker.D6aB_rF9.js.map} +1 -1
  63. package/dist/workers/worker-manifest.json +7 -7
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"audio-compose.worker.CiM_KP27.js","sources":["../../../../src/stages/compose/AudioMixer.ts","../../../../src/stages/compose/AudioDucker.ts","../../../../src/stages/compose/audio-compose.worker.ts"],"sourcesContent":["import type {\n AudioComposeConfig,\n AudioTrack,\n AudioTrackConfig,\n FadeConfig,\n MixRequest,\n MixResult,\n} from './types';\nimport type { AudioDucker } from './AudioDucker';\n\nexport class AudioMixer {\n config: AudioComposeConfig;\n private tracksMap = new Map<string, AudioTrack>();\n\n constructor(config: AudioComposeConfig) {\n this.config = config;\n }\n\n getConfig(): AudioComposeConfig {\n return { ...this.config };\n }\n\n updateConfig(update: Partial<AudioComposeConfig>): void {\n this.config = { ...this.config, ...update };\n }\n\n get tracks(): AudioTrack[] {\n return Array.from(this.tracksMap.values());\n }\n\n createMixStream(ducker?: AudioDucker): TransformStream<MixRequest, MixResult> {\n return new TransformStream<MixRequest, MixResult>(\n {\n transform: async (request, controller) => {\n try {\n const frameCount = this.getFrameCount(request.durationUs);\n\n if (ducker && request.duckingConfig?.enabled && frameCount > 0) {\n const envelope = await ducker.generateDuckingEnvelope(request.tracks, frameCount);\n\n for (const track of request.tracks) {\n if (request.duckingConfig.targetTracks.includes(track.trackId)) {\n track.duckingEnvelope = ducker.applyEnvelopeToVolume(1, envelope);\n }\n }\n }\n\n const result = await this.mixTracks(request, frameCount);\n controller.enqueue(result);\n } catch (error) {\n controller.error(error);\n }\n },\n },\n {\n highWaterMark: 2,\n size: () => 1,\n }\n );\n }\n\n async mixTracks(request: MixRequest, precomputedFrameCount?: number): Promise<MixResult> {\n const tracks = request.tracks ?? [];\n const frameCount = precomputedFrameCount ?? this.getFrameCount(request.durationUs);\n\n const requestedChannelCount = this.config.numberOfChannels ?? 0;\n const inferredChannelCount = tracks.reduce((max, track) => {\n const trackChannels =\n track?.numberOfChannels ??\n track?.audioData?.numberOfChannels ??\n this.config.numberOfChannels ??\n 0;\n return trackChannels > max ? trackChannels : max;\n }, 0);\n const channelCount =\n requestedChannelCount > 0 ? requestedChannelCount : Math.max(inferredChannelCount, 1);\n\n const outputChannels: Float32Array[] = Array.from({ length: channelCount }, () => {\n return new Float32Array(frameCount);\n });\n\n for (const track of tracks) {\n if (!track) {\n continue;\n }\n\n const resolvedAudioData = track.audioData;\n if (!resolvedAudioData) {\n continue;\n }\n\n this.mixTrackIntoOutput(\n outputChannels,\n {\n ...track,\n audioData: resolvedAudioData,\n numberOfChannels:\n track.numberOfChannels ??\n resolvedAudioData.numberOfChannels ??\n this.config.numberOfChannels,\n sampleRate: track.sampleRate ?? resolvedAudioData.sampleRate ?? this.config.sampleRate,\n },\n request.timeUs,\n frameCount\n );\n }\n\n const { peakLevel, rmsLevel } = this.limitAndMeasure(outputChannels);\n const audioData = this.createAudioData(outputChannels, request.timeUs);\n\n return {\n audioData,\n timeUs: request.timeUs,\n durationUs: request.durationUs,\n peakLevel,\n rmsLevel,\n };\n }\n\n addTrack(track: AudioTrack): void {\n this.tracksMap.set(track.id, track);\n }\n\n removeTrack(trackId: string): void {\n this.tracksMap.delete(trackId);\n }\n\n updateTrack(\n trackId: string,\n patch: Partial<AudioTrack> & { config?: Partial<AudioTrackConfig> }\n ): void {\n const track = this.tracksMap.get(trackId);\n if (!track) {\n return;\n }\n\n const { config, ...rest } = patch;\n if (config) {\n Object.assign(track.config, config);\n }\n Object.assign(track, rest);\n }\n\n private mixTrackIntoOutput(\n outputChannels: Float32Array[],\n track: MixRequest['tracks'][0],\n mixStartUs: number,\n totalFrameCount: number\n ): void {\n if (totalFrameCount === 0) {\n track.audioData.close();\n return;\n }\n\n if (track.sampleRate !== this.config.sampleRate) {\n track.audioData.close();\n throw new Error('AudioMixer: sample rate mismatch');\n }\n\n const trackChannelCount = track.audioData.numberOfChannels ?? track.numberOfChannels ?? 0;\n if (trackChannelCount === 0) {\n track.audioData.close();\n return;\n }\n\n const trackChannels = this.extractChannels(track.audioData);\n if (trackChannels.length === 0) {\n track.audioData.close();\n return;\n }\n const trackFrameCount = track.audioData.numberOfFrames;\n\n if (trackFrameCount === 0) {\n track.audioData.close();\n return;\n }\n\n const timestampUs = track.audioData.timestamp ?? mixStartUs;\n const deltaUs = timestampUs - mixStartUs;\n let outputOffsetFrames = Math.round((deltaUs / 1_000_000) * this.config.sampleRate);\n let sourceOffsetFrames = 0;\n\n if (outputOffsetFrames < 0) {\n sourceOffsetFrames = Math.min(trackFrameCount, -outputOffsetFrames);\n outputOffsetFrames = 0;\n }\n\n if (outputOffsetFrames >= totalFrameCount) {\n track.audioData.close();\n return;\n }\n\n const availableFrames = Math.min(\n trackFrameCount - sourceOffsetFrames,\n totalFrameCount - outputOffsetFrames\n );\n\n if (availableFrames <= 0) {\n track.audioData.close();\n return;\n }\n\n const gains = this.buildGainEnvelope(\n track,\n availableFrames,\n outputOffsetFrames,\n sourceOffsetFrames,\n trackFrameCount\n );\n\n const destinationChannelCount = outputChannels.length;\n const sourceChannelCount = trackChannels.length;\n\n for (let channelIndex = 0; channelIndex < destinationChannelCount; channelIndex++) {\n const destination = outputChannels[channelIndex];\n const source = trackChannels[channelIndex] ?? trackChannels[sourceChannelCount - 1];\n if (!destination || !source) continue;\n\n for (let frameIndex = 0; frameIndex < availableFrames; frameIndex++) {\n const sample = source[sourceOffsetFrames + frameIndex] ?? 0;\n const gain = gains[frameIndex] ?? 0;\n destination[outputOffsetFrames + frameIndex] =\n (destination[outputOffsetFrames + frameIndex] ?? 0) + sample * gain;\n }\n }\n\n track.audioData.close();\n }\n\n private buildGainEnvelope(\n track: MixRequest['tracks'][0],\n length: number,\n outputOffsetFrames: number,\n sourceOffsetFrames: number,\n trackFrameCount: number\n ): Float32Array {\n const gains = new Float32Array(length);\n const baseVolume = typeof track.config.volume === 'number' ? track.config.volume : 1;\n gains.fill(baseVolume);\n\n const fadeInSamples = this.getFadeSampleCount(track.config.fadeIn);\n const fadeOutSamples = this.getFadeSampleCount(track.config.fadeOut);\n const clipDurationSamples = this.getClipSampleCount(track.config.durationUs) || trackFrameCount;\n const trackStartFrame = this.computeTrackStartFrame(track);\n\n for (let i = 0; i < length; i++) {\n const envelopeIndex = outputOffsetFrames + i;\n const absoluteFrame = trackStartFrame + sourceOffsetFrames + i;\n let gain = baseVolume;\n\n if (fadeInSamples > 0 && absoluteFrame < fadeInSamples) {\n const progress = Math.min(1, absoluteFrame / fadeInSamples);\n gain *= this.getCurveValue(progress, track.config.fadeIn?.curve);\n }\n\n if (fadeOutSamples > 0 && clipDurationSamples > 0) {\n const fadeStart = Math.max(0, clipDurationSamples - fadeOutSamples);\n if (absoluteFrame >= fadeStart) {\n const progress = Math.min(1, (absoluteFrame - fadeStart) / fadeOutSamples);\n const remaining = Math.max(0, 1 - progress);\n gain *= this.getCurveValue(remaining, track.config.fadeOut?.curve);\n }\n }\n\n if (\n track.duckingEnvelope &&\n envelopeIndex < track.duckingEnvelope.length &&\n envelopeIndex >= 0\n ) {\n gain *= track.duckingEnvelope[envelopeIndex] ?? 1;\n }\n\n gains[i] = gain;\n }\n\n return gains;\n }\n\n private extractChannels(audioData: AudioData): Float32Array[] {\n const configuredChannels = this.config.numberOfChannels ?? 0;\n const channelCount = audioData.numberOfChannels ?? configuredChannels;\n const frameCount = audioData.numberOfFrames;\n const format: string = (audioData as any).format ?? 'f32';\n\n if (!channelCount || !frameCount) {\n return [];\n }\n\n const toFloat = (value: number): number => value / 32768;\n\n const zeroChannels = (): Float32Array[] =>\n Array.from(\n { length: configuredChannels || channelCount },\n () => new Float32Array(frameCount)\n );\n\n if (format === 'f32') {\n const interleaved = new Float32Array(frameCount * channelCount);\n audioData.copyTo(interleaved, { format: 'f32', planeIndex: 0 });\n const channels = zeroChannels();\n for (let frame = 0; frame < frameCount; frame++) {\n const offset = frame * channelCount;\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n channelArray[frame] = interleaved[offset + sourceChannel] ?? 0;\n }\n }\n return channels;\n }\n\n if (format === 's16') {\n const interleaved = new Int16Array(frameCount * channelCount);\n audioData.copyTo(interleaved, { format: 's16', planeIndex: 0 });\n const channels = zeroChannels();\n for (let frame = 0; frame < frameCount; frame++) {\n const offset = frame * channelCount;\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n channelArray[frame] = toFloat(interleaved[offset + sourceChannel] ?? 0);\n }\n }\n return channels;\n }\n\n if (format === 'f32-planar') {\n const channels = zeroChannels();\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n audioData.copyTo(channelArray, { planeIndex: sourceChannel, format: 'f32-planar' });\n }\n return channels;\n }\n\n if (format === 's16-planar') {\n const tmp = new Int16Array(frameCount);\n const channels = zeroChannels();\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n audioData.copyTo(tmp, { planeIndex: sourceChannel, format: 's16-planar' as any });\n for (let i = 0; i < frameCount; i++) {\n channelArray[i] = toFloat(tmp[i] ?? 0);\n }\n }\n return channels;\n }\n\n const channels = zeroChannels();\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n audioData.copyTo(channelArray, { planeIndex: sourceChannel });\n }\n return channels;\n }\n\n private limitAndMeasure(channels: Float32Array[]): { peakLevel: number; rmsLevel: number } {\n let peak = 0;\n let sumSquares = 0;\n let samples = 0;\n\n for (const channel of channels) {\n for (let i = 0; i < channel.length; i++) {\n let sample = channel[i] ?? 0;\n if (sample > 1) {\n sample = 1;\n } else if (sample < -1) {\n sample = -1;\n }\n\n channel[i] = sample;\n\n const absSample = Math.abs(sample);\n if (absSample > peak) {\n peak = absSample;\n }\n\n sumSquares += sample * sample;\n samples++;\n }\n }\n\n const rmsLevel = samples > 0 ? Math.sqrt(sumSquares / samples) : 0;\n\n return {\n peakLevel: peak,\n rmsLevel,\n };\n }\n\n private createAudioData(channels: Float32Array[], timestampUs: number): AudioData {\n const configuredChannels = this.config.numberOfChannels ?? 0;\n const inferredChannels = channels.length;\n const numberOfChannels = (inferredChannels > 0 ? inferredChannels : configuredChannels) || 1;\n const numberOfFrames = channels[0]?.length ?? 0;\n // console.log('>>>>>>>>>>>>>> createAudioData', channels, this.config, numberOfChannels, numberOfFrames);\n if (numberOfFrames === 0) {\n return new AudioData({\n format: 'f32',\n sampleRate: this.config.sampleRate,\n numberOfFrames: 0,\n numberOfChannels,\n timestamp: timestampUs,\n data: new Float32Array(0),\n });\n }\n\n const interleaved = new Float32Array(numberOfFrames * numberOfChannels);\n\n for (let frame = 0; frame < numberOfFrames; frame++) {\n for (let channel = 0; channel < numberOfChannels; channel++) {\n const sourceChannel = channels[channel] ?? channels[channels.length - 1];\n interleaved[frame * numberOfChannels + channel] = sourceChannel?.[frame] ?? 0;\n }\n }\n\n return new AudioData({\n format: 'f32',\n sampleRate: this.config.sampleRate,\n numberOfFrames,\n numberOfChannels,\n timestamp: timestampUs,\n data: interleaved,\n });\n }\n\n private getFrameCount(durationUs: number): number {\n if (durationUs <= 0) {\n return 0;\n }\n\n return Math.ceil((durationUs / 1_000_000) * this.config.sampleRate);\n }\n\n private getFadeSampleCount(fade?: FadeConfig): number {\n if (!fade || fade.durationUs <= 0) {\n return 0;\n }\n\n return Math.round((fade.durationUs / 1_000_000) * this.config.sampleRate);\n }\n\n private getClipSampleCount(durationUs?: number): number {\n if (!durationUs || durationUs <= 0) {\n return 0;\n }\n\n return Math.round((durationUs / 1_000_000) * this.config.sampleRate);\n }\n\n private computeTrackStartFrame(track: MixRequest['tracks'][0]): number {\n const audioTimestamp = track.audioData.timestamp ?? track.config.startTimeUs;\n const relativeUs = audioTimestamp - track.config.startTimeUs;\n const relativeFrames = Math.round((relativeUs / 1_000_000) * this.config.sampleRate);\n return relativeFrames > 0 ? relativeFrames : 0;\n }\n\n private getCurveValue(progress: number, curve: FadeConfig['curve'] = 'linear'): number {\n const clamped = Math.min(Math.max(progress, 0), 1);\n\n switch (curve) {\n case 'exponential':\n return clamped * clamped;\n case 'logarithmic':\n return Math.log10(clamped * 9 + 1);\n case 'cosine':\n return (1 - Math.cos(clamped * Math.PI)) / 2;\n default:\n return clamped;\n }\n }\n}\n","import type { DuckingConfig, MixRequest } from './types';\n\n/**\n * AudioDucker - Automatic volume ducking for background music\n *\n * Ducking: Audio engineering technique where the volume of one audio source\n * is automatically reduced when another audio source is present.\n *\n * Common use case: Reduce background music volume when voice/narration plays\n * to improve speech intelligibility without completely muting the music.\n *\n * Key parameters:\n * - Threshold: Level at which ducking triggers\n * - Ratio: How much to reduce volume (e.g., 3:1 means reduce by 1/3)\n * - Attack: How quickly volume reduces (typically 10-50ms)\n * - Release: How quickly volume returns to normal (typically 100-500ms)\n * - Hold: Time to maintain ducking after trigger ends\n */\nexport class AudioDucker {\n private config: DuckingConfig | null = null;\n private sampleRate: number;\n\n constructor(sampleRate: number) {\n this.sampleRate = sampleRate;\n }\n\n configure(config: DuckingConfig): void {\n this.config = config;\n }\n\n /**\n * Analyze trigger tracks (voice) and generate ducking envelope\n * Returns gain values (0-1) to apply to target tracks (BGM)\n */\n async generateDuckingEnvelope(\n tracks: MixRequest['tracks'],\n frameCount: number\n ): Promise<Float32Array> {\n if (!this.config?.enabled) {\n return new Float32Array(frameCount).fill(1.0);\n }\n\n // Initialize envelope with no ducking (gain = 1.0)\n const envelope = new Float32Array(frameCount);\n envelope.fill(1.0);\n\n // Find trigger tracks (typically voice/narration)\n const triggerTracks = tracks.filter((t) => this.config!.triggerTracks.includes(t.trackId));\n\n if (triggerTracks.length === 0) {\n return envelope;\n }\n\n // Analyze each trigger track for voice activity\n for (const track of triggerTracks) {\n const voiceActivity = await this.detectVoiceActivity(track.audioData);\n this.applyDuckingToEnvelope(envelope, voiceActivity);\n }\n\n return envelope;\n }\n\n /**\n * Voice Activity Detection (VAD)\n * Simple energy-based detection with smoothing\n * More sophisticated implementations could use:\n * - Zero-crossing rate (ZCR) for speech/music discrimination\n * - Spectral centroid for voice frequency detection\n * - Machine learning models for robust VAD\n */\n private async detectVoiceActivity(audioData: AudioData): Promise<Float32Array> {\n const frameCount = audioData.numberOfFrames;\n const activity = new Float32Array(frameCount);\n\n // Convert to mono for analysis\n const monoData = new Float32Array(frameCount);\n const channelData = new Float32Array(frameCount);\n\n for (let ch = 0; ch < audioData.numberOfChannels; ch++) {\n audioData.copyTo(channelData, {\n planeIndex: ch,\n format: 'f32-planar' as const,\n });\n\n for (let i = 0; i < frameCount; i++) {\n if (monoData && channelData) {\n monoData[i] = (monoData[i] || 0) + (channelData[i] || 0) / audioData.numberOfChannels;\n }\n }\n }\n\n // Energy calculation with windowing\n // Window size: 20ms is typical for speech analysis\n const windowSize = Math.floor(this.sampleRate * 0.02);\n const hopSize = Math.floor(windowSize / 2); // 50% overlap\n\n for (let i = 0; i < frameCount; i += hopSize) {\n const end = Math.min(i + windowSize, frameCount);\n\n // Calculate RMS energy in window\n let energy = 0;\n for (let j = i; j < end; j++) {\n if (monoData && monoData[j] !== undefined) {\n const sample = monoData[j];\n if (sample !== undefined) {\n energy += sample * sample;\n }\n }\n }\n energy = Math.sqrt(energy / (end - i));\n\n // Simple threshold-based VAD\n // Typical speech energy threshold: -40dB to -30dB\n const threshold = 0.01; // Approximately -40dB\n const isVoice = energy > threshold;\n\n // Fill activity array for this window\n for (let j = i; j < end; j++) {\n activity[j] = isVoice ? 1.0 : 0.0;\n }\n }\n\n // Smooth activity detection to avoid rapid changes\n return this.smoothActivityDetection(activity);\n }\n\n /**\n * Smooth voice activity detection to avoid choppy ducking\n * Uses a simple moving average filter\n */\n private smoothActivityDetection(activity: Float32Array): Float32Array {\n const smoothed = new Float32Array(activity.length);\n const smoothWindow = Math.floor(this.sampleRate * 0.05); // 50ms smoothing\n\n for (let i = 0; i < activity.length; i++) {\n let sum = 0;\n let count = 0;\n\n for (\n let j = Math.max(0, i - smoothWindow);\n j <= Math.min(activity.length - 1, i + smoothWindow);\n j++\n ) {\n if (activity && activity[j] !== undefined) {\n const val = activity[j];\n if (val !== undefined) {\n sum += val;\n }\n }\n count++;\n }\n\n smoothed[i] = sum / count;\n }\n\n return smoothed;\n }\n\n /**\n * Apply ducking based on voice activity\n * Implements attack/release envelope shaping\n */\n private applyDuckingToEnvelope(envelope: Float32Array, voiceActivity: Float32Array): void {\n if (!this.config) return;\n\n const duckingLevel = 1.0 - this.config.duckingLevel;\n const attackSamples = Math.floor((this.config.attackTimeMs / 1000) * this.sampleRate);\n const releaseSamples = Math.floor((this.config.releaseTimeMs / 1000) * this.sampleRate);\n const lookAheadSamples = this.config.lookAheadMs\n ? Math.floor((this.config.lookAheadMs / 1000) * this.sampleRate)\n : 0;\n\n let currentGain = 1.0;\n let releaseCounter = 0;\n\n for (let i = 0; i < envelope.length; i++) {\n // Look ahead for upcoming voice activity\n const lookAheadIndex = Math.min(i + lookAheadSamples, voiceActivity.length - 1);\n const activity = voiceActivity[lookAheadIndex];\n\n if (activity !== undefined && activity > 0.5) {\n // Voice detected - apply ducking with attack curve\n if (currentGain > duckingLevel) {\n // Attack phase - reduce gain\n currentGain = Math.max(duckingLevel, currentGain - (1.0 - duckingLevel) / attackSamples);\n } else {\n currentGain = duckingLevel;\n }\n releaseCounter = 0;\n } else if (currentGain < 1.0) {\n // No voice - apply release curve\n releaseCounter++;\n if (releaseCounter > releaseSamples * 0.1) {\n // Small hold time\n currentGain = Math.min(1.0, currentGain + (1.0 - duckingLevel) / releaseSamples);\n }\n }\n\n // Apply the calculated gain\n envelope[i] = Math.min(envelope[i] || 1, currentGain);\n }\n }\n\n /**\n * Apply ducking envelope to audio buffer\n * This modulates the volume over time according to the envelope\n */\n applyEnvelopeToVolume(baseVolume: number, envelope: Float32Array): Float32Array {\n const result = new Float32Array(envelope.length);\n for (let i = 0; i < envelope.length; i++) {\n result[i] = baseVolume * (envelope[i] || 1);\n }\n return result;\n }\n\n /**\n * Calculate dynamic range to avoid over-compression\n * Returns the difference between peak and RMS levels in dB\n */\n calculateDynamicRange(envelope: Float32Array): number {\n let peak = 0;\n let sumSquares = 0;\n\n for (const value of envelope) {\n peak = Math.max(peak, value);\n sumSquares += value * value;\n }\n\n const rms = Math.sqrt(sumSquares / envelope.length);\n\n // Convert to dB (20 * log10(ratio))\n const peakDb = 20 * Math.log10(peak);\n const rmsDb = 20 * Math.log10(rms);\n\n return peakDb - rmsDb;\n }\n}\n","import { WorkerChannel } from '../../worker/WorkerChannel';\nimport { WorkerMessageType, WorkerState } from '../../worker/types';\nimport { AudioMixer } from './AudioMixer';\nimport { AudioDucker } from './AudioDucker';\nimport {\n AudioComposeConfig,\n MixRequest,\n MixResult,\n DuckingConfig,\n AudioTrack,\n AudioTrackConfig,\n} from './types';\n\ntype TimeUs = number;\n\ninterface TrackBufferItem {\n audioData: AudioData;\n timestampUs: TimeUs;\n durationUs: TimeUs;\n}\n\ninterface TrackBuffer {\n clipId: string;\n queue: TrackBufferItem[];\n ended: boolean;\n config: AudioTrackConfig;\n type: AudioTrack['type'];\n}\n\n/**\n * AudioComposeWorker - Audio mixing and ducking stage\n * Mixes multiple audio tracks with volume, ducking, and effects\n *\n * Pipeline: DecodeWorker → AudioComposeWorker → EncodeWorker\n *\n * Features:\n * - Multi-track PCM mixing\n * - BGM ducking for voice tracks\n * - Stream-based processing with backpressure\n * - Real-time volume and effect adjustments\n */\nexport class AudioComposeWorker {\n private channel: WorkerChannel;\n private mixer: AudioMixer | null = null;\n private ducker: AudioDucker | null = null;\n private mixStream: TransformStream<MixRequest, MixResult> | null = null;\n\n // Connections to other workers\n private decoderPort: MessagePort | null = null;\n private encoderPort: MessagePort | null = null;\n // Track buffer map\n private trackBuffers = new Map<string, TrackBuffer>();\n private trackQueueWaiters = new Map<string, Array<() => void>>();\n private encoderStreamAttached = false;\n private readonly mixWindowUs: TimeUs = 40_000; // 40ms window\n private readonly maxQueuedSegments = 8;\n private mixing = false;\n\n constructor() {\n // Initialize WorkerChannel\n this.channel = new WorkerChannel(self as any, {\n name: 'AudioComposeWorker',\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 // Unified stream connect\n this.channel.registerHandler('connect' as any, this.handleConnect.bind(this));\n this.channel.registerHandler('add_track', this.handleAddTrack.bind(this));\n this.channel.registerHandler('remove_track', this.handleRemoveTrack.bind(this));\n this.channel.registerHandler('update_track', this.handleUpdateTrack.bind(this));\n this.channel.registerHandler('configure_ducking', this.handleConfigureDucking.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 /** Unified connect handler mapping for stream pipeline */\n private async handleConnect(payload: {\n direction: 'upstream' | 'downstream';\n port: MessagePort;\n streamType?: string;\n }): Promise<{ success: boolean }> {\n if (payload.direction === 'upstream') {\n this.decoderPort = payload.port;\n const decoderChannel = new WorkerChannel(this.decoderPort, {\n name: 'AudioCompose-Decoder',\n timeout: 30000,\n });\n\n decoderChannel.registerHandler('audio_track:add', this.handleAddTrack.bind(this));\n decoderChannel.registerHandler('audio_track:remove', this.handleRemoveTrack.bind(this));\n decoderChannel.registerHandler('audio_track:update', this.handleUpdateTrack.bind(this));\n\n decoderChannel.receiveStream(this.handleReceiveStream.bind(this));\n return { success: true };\n }\n\n if (payload.direction === 'downstream') {\n // if (payload.streamType === 'preview') {\n // this.previewPort = payload.port;\n // this.previewChannel?.dispose?.();\n // this.previewChannel = new WorkerChannel(this.previewPort, {\n // name: 'AudioCompose-Preview',\n // timeout: 30000,\n // });\n // return { success: true };\n // }\n\n this.encoderPort = payload.port;\n return { success: true };\n }\n\n return { success: true };\n }\n\n private async handleReceiveStream(\n stream: ReadableStream,\n metadata?: Record<string, any>\n ): Promise<void> {\n if (metadata?.streamType !== 'audio' || !this.mixStream || !this.mixer) {\n return;\n }\n\n const update: Partial<AudioComposeConfig> = {};\n const currentConfig = this.mixer.getConfig();\n\n if (typeof metadata?.sampleRate === 'number' && metadata.sampleRate > 0) {\n if (!currentConfig.sampleRate || currentConfig.sampleRate !== metadata.sampleRate) {\n update.sampleRate = metadata.sampleRate;\n }\n }\n\n if (typeof metadata?.numberOfChannels === 'number' && metadata.numberOfChannels > 0) {\n if (\n !currentConfig.numberOfChannels ||\n metadata.numberOfChannels > currentConfig.numberOfChannels\n ) {\n update.numberOfChannels = metadata.numberOfChannels;\n }\n }\n\n if (Object.keys(update).length > 0) {\n this.mixer.updateConfig(update);\n }\n\n const mixerConfig = this.mixer.getConfig();\n\n const streamMetadata = {\n ...metadata,\n streamType: 'audio',\n sampleRate: mixerConfig.sampleRate,\n numberOfChannels: mixerConfig.numberOfChannels,\n };\n\n await this.attachEncodeStream(streamMetadata);\n const trackId = (metadata as any)?.trackId ?? (metadata as any)?.clipId;\n if (!trackId) {\n console.warn('[AudioComposeWorker] Missing track identifier in audio stream metadata');\n await stream.cancel();\n return;\n }\n\n await this.bufferTrackStream(trackId, stream as ReadableStream<AudioData>, streamMetadata);\n this.scheduleMix();\n }\n\n /**\n * Configure audio composer\n * @param payload.config - Audio composition configuration\n * @param payload.initial - If true, initialize worker state; otherwise just update config\n */\n private async handleConfigure(payload: {\n config: AudioComposeConfig;\n initial?: boolean;\n }): Promise<{ success: boolean }> {\n const { config, initial = false } = payload;\n\n try {\n if (initial) {\n // Initial setup - set worker state to ready\n this.channel.state = WorkerState.Ready;\n\n // Create new mixer and ducker instances\n // Previous instances will be garbage collected\n\n this.mixer = new AudioMixer(config);\n this.ducker = new AudioDucker(config.sampleRate);\n\n // Create stream with ducking support\n this.mixStream = this.mixer.createMixStream(this.ducker);\n\n // Notify configuration complete\n this.channel.notify('configured', {\n sampleRate: config.sampleRate,\n numberOfChannels: config.numberOfChannels,\n });\n } else {\n // Update configuration only (e.g., backpressure settings)\n if (!this.mixer || !this.ducker) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Audio composer not initialized. Call configure with initial=true first',\n };\n }\n\n // AudioMixer doesn't support runtime config updates\n // Would need initial=true for changes\n }\n\n return { success: true };\n } catch (error: any) {\n throw {\n code: error.code || 'CONFIG_ERROR',\n message: error.message,\n };\n }\n }\n\n /**\n * Connect to decoder worker to receive audio streams\n */\n /**\n * Add an audio track\n */\n private handleAddTrack(payload: {\n clipId: string;\n trackId: string;\n config: AudioTrackConfig;\n type?: AudioTrack['type'];\n }): { success: boolean } {\n if (!this.mixer) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Mixer not configured',\n };\n }\n\n const config = this.cloneTrackConfig(payload.config);\n const track: AudioTrack = {\n id: payload.trackId,\n clipId: payload.clipId,\n type: payload.type ?? 'other',\n config,\n };\n\n this.mixer.addTrack(track);\n this.trackBuffers.set(payload.trackId, {\n clipId: payload.clipId,\n queue: [],\n ended: false,\n config,\n type: payload.type ?? 'other',\n });\n\n this.channel.notify('track_added', {\n trackId: track.id,\n trackType: track.type,\n });\n\n return { success: true };\n }\n\n /**\n * Remove an audio track\n */\n private handleRemoveTrack(payload: { clipId?: string; trackId: string }): { success: boolean } {\n if (!this.mixer) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Mixer not configured',\n };\n }\n\n this.mixer.removeTrack(payload.trackId);\n this.disposeTrackBuffer(payload.trackId);\n\n this.channel.notify('track_removed', {\n trackId: payload.trackId,\n });\n\n return { success: true };\n }\n\n /**\n * Update track configuration\n */\n private handleUpdateTrack(payload: {\n trackId: string;\n config: Partial<AudioTrackConfig> & { type?: AudioTrack['type'] };\n }): {\n success: boolean;\n } {\n if (!this.mixer) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Mixer not configured',\n };\n }\n\n this.mixer.updateTrack(payload.trackId, payload.config);\n const buffer = this.trackBuffers.get(payload.trackId);\n if (buffer) {\n if (payload.config.type) {\n buffer.type = payload.config.type;\n }\n this.applyTrackConfigPatch(buffer.config, payload.config);\n }\n\n this.channel.notify('track_updated', {\n trackId: payload.trackId,\n });\n\n return { success: true };\n }\n\n /**\n * Configure audio ducking\n */\n private handleConfigureDucking(config: DuckingConfig): { success: boolean } {\n if (!this.ducker) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Ducker not configured',\n };\n }\n\n this.ducker.configure(config);\n\n this.channel.notify('ducking_configured', {\n enabled: config.enabled,\n });\n\n return { success: true };\n }\n\n /**\n * Get mixer statistics\n */\n private async handleGetStats(): Promise<{\n tracks?: any[];\n ducking?: any;\n state?: WorkerState;\n }> {\n if (!this.mixer) {\n return { state: this.channel.state };\n }\n\n return {\n tracks: this.mixer.tracks,\n ducking: this.ducker\n ? {\n configured: this.ducker !== null,\n }\n : null,\n state: this.channel.state,\n };\n }\n\n /**\n * Dispose worker and cleanup resources\n */\n private async handleDispose(): Promise<{ success: boolean }> {\n // Clean up references\n this.mixer = null;\n this.ducker = null;\n this.mixStream = null;\n\n // Close connections\n this.decoderPort?.close();\n this.decoderPort = null;\n this.encoderPort?.close();\n this.encoderPort = null;\n\n this.channel.state = WorkerState.Disposed;\n\n return { success: true };\n }\n\n private async attachEncodeStream(metadata: Record<string, any>): Promise<void> {\n if (!this.mixStream || !this.encoderPort || this.encoderStreamAttached || !this.mixer) {\n return;\n }\n\n const encoderChannel = new WorkerChannel(this.encoderPort, {\n name: 'AudioCompose-Encoder',\n timeout: 30000,\n });\n\n const mixerConfig = this.mixer?.getConfig();\n\n const streamMetadata = {\n ...metadata,\n streamType: 'audio',\n sampleRate: mixerConfig?.sampleRate ?? metadata?.sampleRate,\n numberOfChannels: mixerConfig?.numberOfChannels ?? metadata?.numberOfChannels,\n };\n\n const [encoderResultStream, previewResultStream] = this.mixStream.readable.tee();\n\n const createAudioDataStream = (\n source: ReadableStream<MixResult>\n ): ReadableStream<AudioData> => {\n return new ReadableStream<AudioData>({\n start: (controller) => {\n const reader = source.getReader();\n\n const pump = async (): Promise<void> => {\n const { done, value } = await reader.read();\n if (done) {\n reader.releaseLock();\n controller.close();\n return;\n }\n\n try {\n controller.enqueue(value.audioData);\n } catch (error) {\n controller.error(error);\n reader.releaseLock();\n return;\n }\n\n await pump();\n };\n\n pump().catch((error) => {\n reader.releaseLock();\n controller.error(error);\n });\n },\n });\n };\n\n const encoderStream = createAudioDataStream(encoderResultStream);\n const previewStream = createAudioDataStream(previewResultStream);\n\n await encoderChannel.sendStream(encoderStream, streamMetadata);\n\n this.channel.sendStream(previewStream, streamMetadata);\n\n this.encoderStreamAttached = true;\n await this.scheduleMix();\n }\n\n private async bufferTrackStream(\n trackId: string,\n stream: ReadableStream<AudioData>,\n metadata: Record<string, any>\n ): Promise<void> {\n const buffer = this.trackBuffers.get(trackId);\n if (!buffer) {\n await stream.cancel();\n return;\n }\n\n const reader = stream.getReader();\n const process = async (): Promise<void> => {\n while (true) {\n if (buffer.queue.length >= this.maxQueuedSegments) {\n await this.waitForQueueSpace(trackId);\n }\n\n const { done, value } = await reader.read();\n if (done) {\n buffer.ended = true;\n reader.releaseLock();\n return;\n }\n\n buffer.queue.push({\n audioData: value,\n timestampUs: value.timestamp ?? 0,\n durationUs:\n value.duration ??\n Math.round((value.numberOfFrames / (metadata.sampleRate ?? 48_000)) * 1_000_000),\n });\n\n // mix scheduling is triggered after queue updates via scheduleMix()\n this.scheduleMix();\n }\n };\n\n process().catch((error) => {\n buffer.ended = true;\n reader.releaseLock();\n console.error('[AudioComposeWorker] Track stream error:', error);\n });\n }\n\n private async scheduleMix(): Promise<void> {\n if (this.mixing || !this.mixStream || !this.encoderStreamAttached || !this.mixer) {\n return;\n }\n\n const window = this.computeNextWindow();\n if (!window) {\n return;\n }\n\n this.mixing = true;\n try {\n const request = this.buildMixRequest(window.timeUs, window.durationUs);\n if (!request) {\n return;\n }\n\n const writer = this.mixStream.writable.getWriter();\n try {\n await writer.write(request);\n } finally {\n writer.releaseLock();\n }\n } catch (error) {\n console.error('[AudioComposeWorker] Failed to enqueue mix request:', error);\n } finally {\n this.mixing = false;\n if (this.hasBufferedAudio()) {\n queueMicrotask(() => {\n void this.scheduleMix();\n });\n }\n }\n }\n\n private computeNextWindow(): { timeUs: TimeUs; durationUs: TimeUs } | null {\n let earliest: TimeUs | null = null;\n\n for (const buffer of this.trackBuffers.values()) {\n if (buffer.queue.length === 0) {\n continue;\n }\n const firstFrame = buffer.queue[0];\n if (!firstFrame) {\n continue;\n }\n const ts = firstFrame.timestampUs;\n if (earliest === null || ts < earliest) {\n earliest = ts;\n }\n }\n\n if (earliest === null) {\n return null;\n }\n\n return {\n timeUs: earliest,\n durationUs: this.mixWindowUs,\n };\n }\n\n private buildMixRequest(timeUs: TimeUs, _durationUs: TimeUs): MixRequest | null {\n if (!this.mixer) {\n return null;\n }\n\n const tracks: MixRequest['tracks'] = [];\n let resolvedDurationUs = this.mixWindowUs;\n\n for (const [trackId, buffer] of this.trackBuffers.entries()) {\n const segment = this.consumeSegment(trackId, buffer);\n if (!segment) {\n continue;\n }\n\n tracks.push({\n trackId,\n clipId: buffer.clipId,\n audioData: segment.audioData,\n config: segment.config,\n type: buffer.type,\n sampleRate: this.mixer.config.sampleRate,\n numberOfChannels: this.mixer.config.numberOfChannels,\n });\n\n resolvedDurationUs = Math.min(resolvedDurationUs, segment.durationUs ?? this.mixWindowUs);\n }\n\n if (tracks.length === 0) {\n return null;\n }\n\n return {\n tracks,\n timeUs,\n durationUs: resolvedDurationUs,\n };\n }\n\n private consumeSegment(\n trackId: string,\n buffer: TrackBuffer\n ): {\n audioData: AudioData;\n config: AudioTrackConfig;\n sampleRate: number;\n numberOfChannels: number;\n durationUs?: TimeUs;\n } | null {\n if (buffer.queue.length === 0) {\n return null;\n }\n\n const head = buffer.queue[0];\n if (!head) {\n return null;\n }\n\n const queueItem = buffer.queue.shift();\n if (!queueItem) {\n return null;\n }\n\n this.resolveQueueWaiter(trackId);\n\n return {\n audioData: queueItem.audioData,\n config: buffer.config,\n sampleRate: this.mixer!.config.sampleRate,\n numberOfChannels: this.mixer!.config.numberOfChannels,\n durationUs: queueItem.durationUs,\n };\n }\n\n private hasBufferedAudio(): boolean {\n for (const buffer of this.trackBuffers.values()) {\n if (buffer.queue.length > 0) {\n return true;\n }\n }\n return false;\n }\n\n private cloneTrackConfig(config: AudioTrackConfig): AudioTrackConfig {\n return {\n startTimeUs: config.startTimeUs,\n durationUs: config.durationUs,\n volume: config.volume,\n fadeIn: config.fadeIn ? { ...config.fadeIn } : undefined,\n fadeOut: config.fadeOut ? { ...config.fadeOut } : undefined,\n effects: config.effects\n ? config.effects.map((effect) => ({\n type: effect.type,\n params: effect.params ?? {},\n }))\n : undefined,\n duckingTag: config.duckingTag,\n };\n }\n\n private applyTrackConfigPatch(target: AudioTrackConfig, patch: Partial<AudioTrackConfig>): void {\n if (patch.fadeIn) {\n target.fadeIn = { ...patch.fadeIn };\n } else if (patch.fadeIn === null) {\n target.fadeIn = undefined;\n }\n\n if (patch.fadeOut) {\n target.fadeOut = { ...patch.fadeOut };\n } else if (patch.fadeOut === null) {\n target.fadeOut = undefined;\n }\n\n if (patch.effects) {\n target.effects = patch.effects.map((effect) => ({\n type: effect.type,\n params: effect.params ?? {},\n }));\n }\n\n if (typeof patch.volume === 'number') {\n target.volume = patch.volume;\n }\n\n if (patch.startTimeUs !== undefined) {\n target.startTimeUs = patch.startTimeUs;\n }\n\n if (patch.durationUs !== undefined) {\n target.durationUs = patch.durationUs;\n }\n\n if (patch.duckingTag !== undefined) {\n target.duckingTag = patch.duckingTag;\n }\n }\n\n private async waitForQueueSpace(trackId: string): Promise<void> {\n const existing = this.trackQueueWaiters.get(trackId);\n if (existing && existing.length === 0) {\n this.trackQueueWaiters.delete(trackId);\n }\n\n await new Promise<void>((resolve) => {\n const waiters = this.trackQueueWaiters.get(trackId);\n if (waiters) {\n waiters.push(resolve);\n } else {\n this.trackQueueWaiters.set(trackId, [resolve]);\n }\n });\n }\n\n private resolveQueueWaiter(trackId: string): void {\n const waiters = this.trackQueueWaiters.get(trackId);\n if (!waiters || waiters.length === 0) {\n return;\n }\n\n const resolve = waiters.shift();\n resolve?.();\n if (!waiters.length) {\n this.trackQueueWaiters.delete(trackId);\n }\n }\n\n private disposeTrackBuffer(trackId: string): void {\n const buffer = this.trackBuffers.get(trackId);\n if (!buffer) {\n return;\n }\n\n for (const item of buffer.queue) {\n try {\n item.audioData.close();\n } catch (error) {\n console.warn('[AudioComposeWorker] Failed to close AudioData on disposal', error);\n }\n }\n\n this.trackBuffers.delete(trackId);\n\n const waiters = this.trackQueueWaiters.get(trackId);\n if (waiters) {\n waiters.forEach((resolve) => resolve());\n this.trackQueueWaiters.delete(trackId);\n }\n }\n}\n\n// Initialize worker\nconst worker = new AudioComposeWorker();\n\n// Handle worker termination\nself.addEventListener('beforeunload', () => {\n worker['handleDispose']();\n});\n\nexport default null; // Required for TypeScript worker compilation\n"],"names":["channels"],"mappings":"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"}
1
+ {"version":3,"file":"audio-compose.worker.B4Io5w9i.js","sources":["../../../../src/stages/compose/AudioMixer.ts","../../../../src/stages/compose/AudioDucker.ts","../../../../src/stages/compose/audio-compose.worker.ts"],"sourcesContent":["import type {\n AudioComposeConfig,\n AudioTrack,\n AudioTrackConfig,\n FadeConfig,\n MixRequest,\n MixResult,\n} from './types';\nimport type { AudioDucker } from './AudioDucker';\n\nexport class AudioMixer {\n config: AudioComposeConfig;\n private tracksMap = new Map<string, AudioTrack>();\n\n constructor(config: AudioComposeConfig) {\n this.config = config;\n }\n\n getConfig(): AudioComposeConfig {\n return { ...this.config };\n }\n\n updateConfig(update: Partial<AudioComposeConfig>): void {\n this.config = { ...this.config, ...update };\n }\n\n get tracks(): AudioTrack[] {\n return Array.from(this.tracksMap.values());\n }\n\n createMixStream(ducker?: AudioDucker): TransformStream<MixRequest, MixResult> {\n return new TransformStream<MixRequest, MixResult>(\n {\n transform: async (request, controller) => {\n try {\n const frameCount = this.getFrameCount(request.durationUs);\n\n if (ducker && request.duckingConfig?.enabled && frameCount > 0) {\n const envelope = await ducker.generateDuckingEnvelope(request.tracks, frameCount);\n\n for (const track of request.tracks) {\n if (request.duckingConfig.targetTracks.includes(track.trackId)) {\n track.duckingEnvelope = ducker.applyEnvelopeToVolume(1, envelope);\n }\n }\n }\n\n const result = await this.mixTracks(request, frameCount);\n controller.enqueue(result);\n } catch (error) {\n controller.error(error);\n }\n },\n },\n {\n highWaterMark: 2,\n size: () => 1,\n }\n );\n }\n\n async mixTracks(request: MixRequest, precomputedFrameCount?: number): Promise<MixResult> {\n const tracks = request.tracks ?? [];\n const frameCount = precomputedFrameCount ?? this.getFrameCount(request.durationUs);\n\n const requestedChannelCount = this.config.numberOfChannels ?? 0;\n const inferredChannelCount = tracks.reduce((max, track) => {\n const trackChannels =\n track?.numberOfChannels ??\n track?.audioData?.numberOfChannels ??\n this.config.numberOfChannels ??\n 0;\n return trackChannels > max ? trackChannels : max;\n }, 0);\n const channelCount =\n requestedChannelCount > 0 ? requestedChannelCount : Math.max(inferredChannelCount, 1);\n\n const outputChannels: Float32Array[] = Array.from({ length: channelCount }, () => {\n return new Float32Array(frameCount);\n });\n\n for (const track of tracks) {\n if (!track) {\n continue;\n }\n\n const resolvedAudioData = track.audioData;\n if (!resolvedAudioData) {\n continue;\n }\n\n this.mixTrackIntoOutput(\n outputChannels,\n {\n ...track,\n audioData: resolvedAudioData,\n numberOfChannels:\n track.numberOfChannels ??\n resolvedAudioData.numberOfChannels ??\n this.config.numberOfChannels,\n sampleRate: track.sampleRate ?? resolvedAudioData.sampleRate ?? this.config.sampleRate,\n },\n request.timeUs,\n frameCount\n );\n }\n\n const { peakLevel, rmsLevel } = this.limitAndMeasure(outputChannels);\n const audioData = this.createAudioData(outputChannels, request.timeUs);\n\n return {\n audioData,\n timeUs: request.timeUs,\n durationUs: request.durationUs,\n peakLevel,\n rmsLevel,\n };\n }\n\n addTrack(track: AudioTrack): void {\n this.tracksMap.set(track.id, track);\n }\n\n removeTrack(trackId: string): void {\n this.tracksMap.delete(trackId);\n }\n\n updateTrack(\n trackId: string,\n patch: Partial<AudioTrack> & { config?: Partial<AudioTrackConfig> }\n ): void {\n const track = this.tracksMap.get(trackId);\n if (!track) {\n return;\n }\n\n const { config, ...rest } = patch;\n if (config) {\n Object.assign(track.config, config);\n }\n Object.assign(track, rest);\n }\n\n private mixTrackIntoOutput(\n outputChannels: Float32Array[],\n track: MixRequest['tracks'][0],\n mixStartUs: number,\n totalFrameCount: number\n ): void {\n if (totalFrameCount === 0) {\n track.audioData.close();\n return;\n }\n\n if (track.sampleRate !== this.config.sampleRate) {\n track.audioData.close();\n throw new Error('AudioMixer: sample rate mismatch');\n }\n\n const trackChannelCount = track.audioData.numberOfChannels ?? track.numberOfChannels ?? 0;\n if (trackChannelCount === 0) {\n track.audioData.close();\n return;\n }\n\n const trackChannels = this.extractChannels(track.audioData);\n if (trackChannels.length === 0) {\n track.audioData.close();\n return;\n }\n const trackFrameCount = track.audioData.numberOfFrames;\n\n if (trackFrameCount === 0) {\n track.audioData.close();\n return;\n }\n\n const timestampUs = track.audioData.timestamp ?? mixStartUs;\n const deltaUs = timestampUs - mixStartUs;\n let outputOffsetFrames = Math.round((deltaUs / 1_000_000) * this.config.sampleRate);\n let sourceOffsetFrames = 0;\n\n if (outputOffsetFrames < 0) {\n sourceOffsetFrames = Math.min(trackFrameCount, -outputOffsetFrames);\n outputOffsetFrames = 0;\n }\n\n if (outputOffsetFrames >= totalFrameCount) {\n track.audioData.close();\n return;\n }\n\n const availableFrames = Math.min(\n trackFrameCount - sourceOffsetFrames,\n totalFrameCount - outputOffsetFrames\n );\n\n if (availableFrames <= 0) {\n track.audioData.close();\n return;\n }\n\n const gains = this.buildGainEnvelope(\n track,\n availableFrames,\n outputOffsetFrames,\n sourceOffsetFrames,\n trackFrameCount\n );\n\n const destinationChannelCount = outputChannels.length;\n const sourceChannelCount = trackChannels.length;\n\n for (let channelIndex = 0; channelIndex < destinationChannelCount; channelIndex++) {\n const destination = outputChannels[channelIndex];\n const source = trackChannels[channelIndex] ?? trackChannels[sourceChannelCount - 1];\n if (!destination || !source) continue;\n\n for (let frameIndex = 0; frameIndex < availableFrames; frameIndex++) {\n const sample = source[sourceOffsetFrames + frameIndex] ?? 0;\n const gain = gains[frameIndex] ?? 0;\n destination[outputOffsetFrames + frameIndex] =\n (destination[outputOffsetFrames + frameIndex] ?? 0) + sample * gain;\n }\n }\n\n track.audioData.close();\n }\n\n private buildGainEnvelope(\n track: MixRequest['tracks'][0],\n length: number,\n outputOffsetFrames: number,\n sourceOffsetFrames: number,\n trackFrameCount: number\n ): Float32Array {\n const gains = new Float32Array(length);\n const baseVolume = typeof track.config.volume === 'number' ? track.config.volume : 1;\n gains.fill(baseVolume);\n\n const fadeInSamples = this.getFadeSampleCount(track.config.fadeIn);\n const fadeOutSamples = this.getFadeSampleCount(track.config.fadeOut);\n const clipDurationSamples = this.getClipSampleCount(track.config.durationUs) || trackFrameCount;\n const trackStartFrame = this.computeTrackStartFrame(track);\n\n for (let i = 0; i < length; i++) {\n const envelopeIndex = outputOffsetFrames + i;\n const absoluteFrame = trackStartFrame + sourceOffsetFrames + i;\n let gain = baseVolume;\n\n if (fadeInSamples > 0 && absoluteFrame < fadeInSamples) {\n const progress = Math.min(1, absoluteFrame / fadeInSamples);\n gain *= this.getCurveValue(progress, track.config.fadeIn?.curve);\n }\n\n if (fadeOutSamples > 0 && clipDurationSamples > 0) {\n const fadeStart = Math.max(0, clipDurationSamples - fadeOutSamples);\n if (absoluteFrame >= fadeStart) {\n const progress = Math.min(1, (absoluteFrame - fadeStart) / fadeOutSamples);\n const remaining = Math.max(0, 1 - progress);\n gain *= this.getCurveValue(remaining, track.config.fadeOut?.curve);\n }\n }\n\n if (\n track.duckingEnvelope &&\n envelopeIndex < track.duckingEnvelope.length &&\n envelopeIndex >= 0\n ) {\n gain *= track.duckingEnvelope[envelopeIndex] ?? 1;\n }\n\n gains[i] = gain;\n }\n\n return gains;\n }\n\n private extractChannels(audioData: AudioData): Float32Array[] {\n const configuredChannels = this.config.numberOfChannels ?? 0;\n const channelCount = audioData.numberOfChannels ?? configuredChannels;\n const frameCount = audioData.numberOfFrames;\n const format: string = (audioData as any).format ?? 'f32';\n\n if (!channelCount || !frameCount) {\n return [];\n }\n\n const toFloat = (value: number): number => value / 32768;\n\n const zeroChannels = (): Float32Array[] =>\n Array.from(\n { length: configuredChannels || channelCount },\n () => new Float32Array(frameCount)\n );\n\n if (format === 'f32') {\n const interleaved = new Float32Array(frameCount * channelCount);\n audioData.copyTo(interleaved, { format: 'f32', planeIndex: 0 });\n const channels = zeroChannels();\n for (let frame = 0; frame < frameCount; frame++) {\n const offset = frame * channelCount;\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n channelArray[frame] = interleaved[offset + sourceChannel] ?? 0;\n }\n }\n return channels;\n }\n\n if (format === 's16') {\n const interleaved = new Int16Array(frameCount * channelCount);\n audioData.copyTo(interleaved, { format: 's16', planeIndex: 0 });\n const channels = zeroChannels();\n for (let frame = 0; frame < frameCount; frame++) {\n const offset = frame * channelCount;\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n channelArray[frame] = toFloat(interleaved[offset + sourceChannel] ?? 0);\n }\n }\n return channels;\n }\n\n if (format === 'f32-planar') {\n const channels = zeroChannels();\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n audioData.copyTo(channelArray, { planeIndex: sourceChannel, format: 'f32-planar' });\n }\n return channels;\n }\n\n if (format === 's16-planar') {\n const tmp = new Int16Array(frameCount);\n const channels = zeroChannels();\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n audioData.copyTo(tmp, { planeIndex: sourceChannel, format: 's16-planar' as any });\n for (let i = 0; i < frameCount; i++) {\n channelArray[i] = toFloat(tmp[i] ?? 0);\n }\n }\n return channels;\n }\n\n const channels = zeroChannels();\n for (let channel = 0; channel < channels.length; channel++) {\n const channelArray = channels[channel];\n if (!channelArray) continue;\n const sourceChannel = channel < channelCount ? channel : channelCount - 1;\n audioData.copyTo(channelArray, { planeIndex: sourceChannel });\n }\n return channels;\n }\n\n private limitAndMeasure(channels: Float32Array[]): { peakLevel: number; rmsLevel: number } {\n let peak = 0;\n let sumSquares = 0;\n let samples = 0;\n\n for (const channel of channels) {\n for (let i = 0; i < channel.length; i++) {\n let sample = channel[i] ?? 0;\n if (sample > 1) {\n sample = 1;\n } else if (sample < -1) {\n sample = -1;\n }\n\n channel[i] = sample;\n\n const absSample = Math.abs(sample);\n if (absSample > peak) {\n peak = absSample;\n }\n\n sumSquares += sample * sample;\n samples++;\n }\n }\n\n const rmsLevel = samples > 0 ? Math.sqrt(sumSquares / samples) : 0;\n\n return {\n peakLevel: peak,\n rmsLevel,\n };\n }\n\n private createAudioData(channels: Float32Array[], timestampUs: number): AudioData {\n const configuredChannels = this.config.numberOfChannels ?? 0;\n const inferredChannels = channels.length;\n const numberOfChannels = (inferredChannels > 0 ? inferredChannels : configuredChannels) || 1;\n const numberOfFrames = channels[0]?.length ?? 0;\n // console.log('>>>>>>>>>>>>>> createAudioData', channels, this.config, numberOfChannels, numberOfFrames);\n if (numberOfFrames === 0) {\n return new AudioData({\n format: 'f32',\n sampleRate: this.config.sampleRate,\n numberOfFrames: 0,\n numberOfChannels,\n timestamp: timestampUs,\n data: new Float32Array(0),\n });\n }\n\n const interleaved = new Float32Array(numberOfFrames * numberOfChannels);\n\n for (let frame = 0; frame < numberOfFrames; frame++) {\n for (let channel = 0; channel < numberOfChannels; channel++) {\n const sourceChannel = channels[channel] ?? channels[channels.length - 1];\n interleaved[frame * numberOfChannels + channel] = sourceChannel?.[frame] ?? 0;\n }\n }\n\n return new AudioData({\n format: 'f32',\n sampleRate: this.config.sampleRate,\n numberOfFrames,\n numberOfChannels,\n timestamp: timestampUs,\n data: interleaved,\n });\n }\n\n private getFrameCount(durationUs: number): number {\n if (durationUs <= 0) {\n return 0;\n }\n\n return Math.ceil((durationUs / 1_000_000) * this.config.sampleRate);\n }\n\n private getFadeSampleCount(fade?: FadeConfig): number {\n if (!fade || fade.durationUs <= 0) {\n return 0;\n }\n\n return Math.round((fade.durationUs / 1_000_000) * this.config.sampleRate);\n }\n\n private getClipSampleCount(durationUs?: number): number {\n if (!durationUs || durationUs <= 0) {\n return 0;\n }\n\n return Math.round((durationUs / 1_000_000) * this.config.sampleRate);\n }\n\n private computeTrackStartFrame(track: MixRequest['tracks'][0]): number {\n const audioTimestamp = track.audioData.timestamp ?? track.config.startTimeUs;\n const relativeUs = audioTimestamp - track.config.startTimeUs;\n const relativeFrames = Math.round((relativeUs / 1_000_000) * this.config.sampleRate);\n return relativeFrames > 0 ? relativeFrames : 0;\n }\n\n private getCurveValue(progress: number, curve: FadeConfig['curve'] = 'linear'): number {\n const clamped = Math.min(Math.max(progress, 0), 1);\n\n switch (curve) {\n case 'exponential':\n return clamped * clamped;\n case 'logarithmic':\n return Math.log10(clamped * 9 + 1);\n case 'cosine':\n return (1 - Math.cos(clamped * Math.PI)) / 2;\n default:\n return clamped;\n }\n }\n}\n","import type { DuckingConfig, MixRequest } from './types';\n\n/**\n * AudioDucker - Automatic volume ducking for background music\n *\n * Ducking: Audio engineering technique where the volume of one audio source\n * is automatically reduced when another audio source is present.\n *\n * Common use case: Reduce background music volume when voice/narration plays\n * to improve speech intelligibility without completely muting the music.\n *\n * Key parameters:\n * - Threshold: Level at which ducking triggers\n * - Ratio: How much to reduce volume (e.g., 3:1 means reduce by 1/3)\n * - Attack: How quickly volume reduces (typically 10-50ms)\n * - Release: How quickly volume returns to normal (typically 100-500ms)\n * - Hold: Time to maintain ducking after trigger ends\n */\nexport class AudioDucker {\n private config: DuckingConfig | null = null;\n private sampleRate: number;\n\n constructor(sampleRate: number) {\n this.sampleRate = sampleRate;\n }\n\n configure(config: DuckingConfig): void {\n this.config = config;\n }\n\n /**\n * Analyze trigger tracks (voice) and generate ducking envelope\n * Returns gain values (0-1) to apply to target tracks (BGM)\n */\n async generateDuckingEnvelope(\n tracks: MixRequest['tracks'],\n frameCount: number\n ): Promise<Float32Array> {\n if (!this.config?.enabled) {\n return new Float32Array(frameCount).fill(1.0);\n }\n\n // Initialize envelope with no ducking (gain = 1.0)\n const envelope = new Float32Array(frameCount);\n envelope.fill(1.0);\n\n // Find trigger tracks (typically voice/narration)\n const triggerTracks = tracks.filter((t) => this.config!.triggerTracks.includes(t.trackId));\n\n if (triggerTracks.length === 0) {\n return envelope;\n }\n\n // Analyze each trigger track for voice activity\n for (const track of triggerTracks) {\n const voiceActivity = await this.detectVoiceActivity(track.audioData);\n this.applyDuckingToEnvelope(envelope, voiceActivity);\n }\n\n return envelope;\n }\n\n /**\n * Voice Activity Detection (VAD)\n * Simple energy-based detection with smoothing\n * More sophisticated implementations could use:\n * - Zero-crossing rate (ZCR) for speech/music discrimination\n * - Spectral centroid for voice frequency detection\n * - Machine learning models for robust VAD\n */\n private async detectVoiceActivity(audioData: AudioData): Promise<Float32Array> {\n const frameCount = audioData.numberOfFrames;\n const activity = new Float32Array(frameCount);\n\n // Convert to mono for analysis\n const monoData = new Float32Array(frameCount);\n const channelData = new Float32Array(frameCount);\n\n for (let ch = 0; ch < audioData.numberOfChannels; ch++) {\n audioData.copyTo(channelData, {\n planeIndex: ch,\n format: 'f32-planar' as const,\n });\n\n for (let i = 0; i < frameCount; i++) {\n if (monoData && channelData) {\n monoData[i] = (monoData[i] || 0) + (channelData[i] || 0) / audioData.numberOfChannels;\n }\n }\n }\n\n // Energy calculation with windowing\n // Window size: 20ms is typical for speech analysis\n const windowSize = Math.floor(this.sampleRate * 0.02);\n const hopSize = Math.floor(windowSize / 2); // 50% overlap\n\n for (let i = 0; i < frameCount; i += hopSize) {\n const end = Math.min(i + windowSize, frameCount);\n\n // Calculate RMS energy in window\n let energy = 0;\n for (let j = i; j < end; j++) {\n if (monoData && monoData[j] !== undefined) {\n const sample = monoData[j];\n if (sample !== undefined) {\n energy += sample * sample;\n }\n }\n }\n energy = Math.sqrt(energy / (end - i));\n\n // Simple threshold-based VAD\n // Typical speech energy threshold: -40dB to -30dB\n const threshold = 0.01; // Approximately -40dB\n const isVoice = energy > threshold;\n\n // Fill activity array for this window\n for (let j = i; j < end; j++) {\n activity[j] = isVoice ? 1.0 : 0.0;\n }\n }\n\n // Smooth activity detection to avoid rapid changes\n return this.smoothActivityDetection(activity);\n }\n\n /**\n * Smooth voice activity detection to avoid choppy ducking\n * Uses a simple moving average filter\n */\n private smoothActivityDetection(activity: Float32Array): Float32Array {\n const smoothed = new Float32Array(activity.length);\n const smoothWindow = Math.floor(this.sampleRate * 0.05); // 50ms smoothing\n\n for (let i = 0; i < activity.length; i++) {\n let sum = 0;\n let count = 0;\n\n for (\n let j = Math.max(0, i - smoothWindow);\n j <= Math.min(activity.length - 1, i + smoothWindow);\n j++\n ) {\n if (activity && activity[j] !== undefined) {\n const val = activity[j];\n if (val !== undefined) {\n sum += val;\n }\n }\n count++;\n }\n\n smoothed[i] = sum / count;\n }\n\n return smoothed;\n }\n\n /**\n * Apply ducking based on voice activity\n * Implements attack/release envelope shaping\n */\n private applyDuckingToEnvelope(envelope: Float32Array, voiceActivity: Float32Array): void {\n if (!this.config) return;\n\n const duckingLevel = 1.0 - this.config.duckingLevel;\n const attackSamples = Math.floor((this.config.attackTimeMs / 1000) * this.sampleRate);\n const releaseSamples = Math.floor((this.config.releaseTimeMs / 1000) * this.sampleRate);\n const lookAheadSamples = this.config.lookAheadMs\n ? Math.floor((this.config.lookAheadMs / 1000) * this.sampleRate)\n : 0;\n\n let currentGain = 1.0;\n let releaseCounter = 0;\n\n for (let i = 0; i < envelope.length; i++) {\n // Look ahead for upcoming voice activity\n const lookAheadIndex = Math.min(i + lookAheadSamples, voiceActivity.length - 1);\n const activity = voiceActivity[lookAheadIndex];\n\n if (activity !== undefined && activity > 0.5) {\n // Voice detected - apply ducking with attack curve\n if (currentGain > duckingLevel) {\n // Attack phase - reduce gain\n currentGain = Math.max(duckingLevel, currentGain - (1.0 - duckingLevel) / attackSamples);\n } else {\n currentGain = duckingLevel;\n }\n releaseCounter = 0;\n } else if (currentGain < 1.0) {\n // No voice - apply release curve\n releaseCounter++;\n if (releaseCounter > releaseSamples * 0.1) {\n // Small hold time\n currentGain = Math.min(1.0, currentGain + (1.0 - duckingLevel) / releaseSamples);\n }\n }\n\n // Apply the calculated gain\n envelope[i] = Math.min(envelope[i] || 1, currentGain);\n }\n }\n\n /**\n * Apply ducking envelope to audio buffer\n * This modulates the volume over time according to the envelope\n */\n applyEnvelopeToVolume(baseVolume: number, envelope: Float32Array): Float32Array {\n const result = new Float32Array(envelope.length);\n for (let i = 0; i < envelope.length; i++) {\n result[i] = baseVolume * (envelope[i] || 1);\n }\n return result;\n }\n\n /**\n * Calculate dynamic range to avoid over-compression\n * Returns the difference between peak and RMS levels in dB\n */\n calculateDynamicRange(envelope: Float32Array): number {\n let peak = 0;\n let sumSquares = 0;\n\n for (const value of envelope) {\n peak = Math.max(peak, value);\n sumSquares += value * value;\n }\n\n const rms = Math.sqrt(sumSquares / envelope.length);\n\n // Convert to dB (20 * log10(ratio))\n const peakDb = 20 * Math.log10(peak);\n const rmsDb = 20 * Math.log10(rms);\n\n return peakDb - rmsDb;\n }\n}\n","import { WorkerChannel } from '../../worker/WorkerChannel';\nimport { WorkerMessageType, WorkerState } from '../../worker/types';\nimport { AudioMixer } from './AudioMixer';\nimport { AudioDucker } from './AudioDucker';\nimport {\n AudioComposeConfig,\n MixRequest,\n MixResult,\n DuckingConfig,\n AudioTrack,\n AudioTrackConfig,\n} from './types';\n\ntype TimeUs = number;\n\ninterface TrackBufferItem {\n audioData: AudioData;\n timestampUs: TimeUs;\n durationUs: TimeUs;\n}\n\ninterface TrackBuffer {\n clipId: string;\n queue: TrackBufferItem[];\n ended: boolean;\n config: AudioTrackConfig;\n type: AudioTrack['type'];\n}\n\n/**\n * AudioComposeWorker - Audio mixing and ducking stage\n * Mixes multiple audio tracks with volume, ducking, and effects\n *\n * Pipeline: DecodeWorker → AudioComposeWorker → EncodeWorker\n *\n * Features:\n * - Multi-track PCM mixing\n * - BGM ducking for voice tracks\n * - Stream-based processing with backpressure\n * - Real-time volume and effect adjustments\n */\nexport class AudioComposeWorker {\n private channel: WorkerChannel;\n private mixer: AudioMixer | null = null;\n private ducker: AudioDucker | null = null;\n private mixStream: TransformStream<MixRequest, MixResult> | null = null;\n\n // Connections to other workers\n private decoderPort: MessagePort | null = null;\n private encoderPort: MessagePort | null = null;\n // Track buffer map\n private trackBuffers = new Map<string, TrackBuffer>();\n private trackQueueWaiters = new Map<string, Array<() => void>>();\n private encoderStreamAttached = false;\n private readonly mixWindowUs: TimeUs = 40_000; // 40ms window\n private readonly maxQueuedSegments = 8;\n private mixing = false;\n\n constructor() {\n // Initialize WorkerChannel\n this.channel = new WorkerChannel(self as any, {\n name: 'AudioComposeWorker',\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 // Unified stream connect\n this.channel.registerHandler('connect' as any, this.handleConnect.bind(this));\n this.channel.registerHandler('add_track', this.handleAddTrack.bind(this));\n this.channel.registerHandler('remove_track', this.handleRemoveTrack.bind(this));\n this.channel.registerHandler('update_track', this.handleUpdateTrack.bind(this));\n this.channel.registerHandler('configure_ducking', this.handleConfigureDucking.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 /** Unified connect handler mapping for stream pipeline */\n private async handleConnect(payload: {\n direction: 'upstream' | 'downstream';\n port: MessagePort;\n streamType?: string;\n }): Promise<{ success: boolean }> {\n if (payload.direction === 'upstream') {\n this.decoderPort = payload.port;\n const decoderChannel = new WorkerChannel(this.decoderPort, {\n name: 'AudioCompose-Decoder',\n timeout: 30000,\n });\n\n decoderChannel.registerHandler('audio_track:add', this.handleAddTrack.bind(this));\n decoderChannel.registerHandler('audio_track:remove', this.handleRemoveTrack.bind(this));\n decoderChannel.registerHandler('audio_track:update', this.handleUpdateTrack.bind(this));\n\n decoderChannel.receiveStream(this.handleReceiveStream.bind(this));\n return { success: true };\n }\n\n if (payload.direction === 'downstream') {\n // if (payload.streamType === 'preview') {\n // this.previewPort = payload.port;\n // this.previewChannel?.dispose?.();\n // this.previewChannel = new WorkerChannel(this.previewPort, {\n // name: 'AudioCompose-Preview',\n // timeout: 30000,\n // });\n // return { success: true };\n // }\n\n this.encoderPort = payload.port;\n return { success: true };\n }\n\n return { success: true };\n }\n\n private async handleReceiveStream(\n stream: ReadableStream,\n metadata?: Record<string, any>\n ): Promise<void> {\n if (metadata?.streamType !== 'audio' || !this.mixStream || !this.mixer) {\n return;\n }\n\n const update: Partial<AudioComposeConfig> = {};\n const currentConfig = this.mixer.getConfig();\n\n if (typeof metadata?.sampleRate === 'number' && metadata.sampleRate > 0) {\n if (!currentConfig.sampleRate || currentConfig.sampleRate !== metadata.sampleRate) {\n update.sampleRate = metadata.sampleRate;\n }\n }\n\n if (typeof metadata?.numberOfChannels === 'number' && metadata.numberOfChannels > 0) {\n if (\n !currentConfig.numberOfChannels ||\n metadata.numberOfChannels > currentConfig.numberOfChannels\n ) {\n update.numberOfChannels = metadata.numberOfChannels;\n }\n }\n\n if (Object.keys(update).length > 0) {\n this.mixer.updateConfig(update);\n }\n\n const mixerConfig = this.mixer.getConfig();\n\n const streamMetadata = {\n ...metadata,\n streamType: 'audio',\n sampleRate: mixerConfig.sampleRate,\n numberOfChannels: mixerConfig.numberOfChannels,\n };\n\n await this.attachEncodeStream(streamMetadata);\n const trackId = (metadata as any)?.trackId ?? (metadata as any)?.clipId;\n if (!trackId) {\n console.warn('[AudioComposeWorker] Missing track identifier in audio stream metadata');\n await stream.cancel();\n return;\n }\n\n await this.bufferTrackStream(trackId, stream as ReadableStream<AudioData>, streamMetadata);\n this.scheduleMix();\n }\n\n /**\n * Configure audio composer\n * @param payload.config - Audio composition configuration\n * @param payload.initial - If true, initialize worker state; otherwise just update config\n */\n private async handleConfigure(payload: {\n config: AudioComposeConfig;\n initial?: boolean;\n }): Promise<{ success: boolean }> {\n const { config, initial = false } = payload;\n\n try {\n if (initial) {\n // Initial setup - set worker state to ready\n this.channel.state = WorkerState.Ready;\n\n // Create new mixer and ducker instances\n // Previous instances will be garbage collected\n\n this.mixer = new AudioMixer(config);\n this.ducker = new AudioDucker(config.sampleRate);\n\n // Create stream with ducking support\n this.mixStream = this.mixer.createMixStream(this.ducker);\n\n // Notify configuration complete\n this.channel.notify('configured', {\n sampleRate: config.sampleRate,\n numberOfChannels: config.numberOfChannels,\n });\n } else {\n // Update configuration only (e.g., backpressure settings)\n if (!this.mixer || !this.ducker) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Audio composer not initialized. Call configure with initial=true first',\n };\n }\n\n // AudioMixer doesn't support runtime config updates\n // Would need initial=true for changes\n }\n\n return { success: true };\n } catch (error: any) {\n throw {\n code: error.code || 'CONFIG_ERROR',\n message: error.message,\n };\n }\n }\n\n /**\n * Connect to decoder worker to receive audio streams\n */\n /**\n * Add an audio track\n */\n private handleAddTrack(payload: {\n clipId: string;\n trackId: string;\n config: AudioTrackConfig;\n type?: AudioTrack['type'];\n }): { success: boolean } {\n if (!this.mixer) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Mixer not configured',\n };\n }\n\n const config = this.cloneTrackConfig(payload.config);\n const track: AudioTrack = {\n id: payload.trackId,\n clipId: payload.clipId,\n type: payload.type ?? 'other',\n config,\n };\n\n this.mixer.addTrack(track);\n this.trackBuffers.set(payload.trackId, {\n clipId: payload.clipId,\n queue: [],\n ended: false,\n config,\n type: payload.type ?? 'other',\n });\n\n this.channel.notify('track_added', {\n trackId: track.id,\n trackType: track.type,\n });\n\n return { success: true };\n }\n\n /**\n * Remove an audio track\n */\n private handleRemoveTrack(payload: { clipId?: string; trackId: string }): { success: boolean } {\n if (!this.mixer) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Mixer not configured',\n };\n }\n\n this.mixer.removeTrack(payload.trackId);\n this.disposeTrackBuffer(payload.trackId);\n\n this.channel.notify('track_removed', {\n trackId: payload.trackId,\n });\n\n return { success: true };\n }\n\n /**\n * Update track configuration\n */\n private handleUpdateTrack(payload: {\n trackId: string;\n config: Partial<AudioTrackConfig> & { type?: AudioTrack['type'] };\n }): {\n success: boolean;\n } {\n if (!this.mixer) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Mixer not configured',\n };\n }\n\n this.mixer.updateTrack(payload.trackId, payload.config);\n const buffer = this.trackBuffers.get(payload.trackId);\n if (buffer) {\n if (payload.config.type) {\n buffer.type = payload.config.type;\n }\n this.applyTrackConfigPatch(buffer.config, payload.config);\n }\n\n this.channel.notify('track_updated', {\n trackId: payload.trackId,\n });\n\n return { success: true };\n }\n\n /**\n * Configure audio ducking\n */\n private handleConfigureDucking(config: DuckingConfig): { success: boolean } {\n if (!this.ducker) {\n throw {\n code: 'NOT_CONFIGURED',\n message: 'Ducker not configured',\n };\n }\n\n this.ducker.configure(config);\n\n this.channel.notify('ducking_configured', {\n enabled: config.enabled,\n });\n\n return { success: true };\n }\n\n /**\n * Get mixer statistics\n */\n private async handleGetStats(): Promise<{\n tracks?: any[];\n ducking?: any;\n state?: WorkerState;\n }> {\n if (!this.mixer) {\n return { state: this.channel.state };\n }\n\n return {\n tracks: this.mixer.tracks,\n ducking: this.ducker\n ? {\n configured: this.ducker !== null,\n }\n : null,\n state: this.channel.state,\n };\n }\n\n /**\n * Dispose worker and cleanup resources\n */\n private async handleDispose(): Promise<{ success: boolean }> {\n // Clean up references\n this.mixer = null;\n this.ducker = null;\n this.mixStream = null;\n\n // Close connections\n this.decoderPort?.close();\n this.decoderPort = null;\n this.encoderPort?.close();\n this.encoderPort = null;\n\n this.channel.state = WorkerState.Disposed;\n\n return { success: true };\n }\n\n private async attachEncodeStream(metadata: Record<string, any>): Promise<void> {\n if (!this.mixStream || !this.encoderPort || this.encoderStreamAttached || !this.mixer) {\n return;\n }\n\n const encoderChannel = new WorkerChannel(this.encoderPort, {\n name: 'AudioCompose-Encoder',\n timeout: 30000,\n });\n\n const mixerConfig = this.mixer?.getConfig();\n\n const streamMetadata = {\n ...metadata,\n streamType: 'audio',\n sampleRate: mixerConfig?.sampleRate ?? metadata?.sampleRate,\n numberOfChannels: mixerConfig?.numberOfChannels ?? metadata?.numberOfChannels,\n };\n\n const [encoderResultStream, previewResultStream] = this.mixStream.readable.tee();\n\n const createAudioDataStream = (\n source: ReadableStream<MixResult>\n ): ReadableStream<AudioData> => {\n return new ReadableStream<AudioData>({\n start: (controller) => {\n const reader = source.getReader();\n\n const pump = async (): Promise<void> => {\n const { done, value } = await reader.read();\n if (done) {\n reader.releaseLock();\n controller.close();\n return;\n }\n\n try {\n controller.enqueue(value.audioData);\n } catch (error) {\n controller.error(error);\n reader.releaseLock();\n return;\n }\n\n await pump();\n };\n\n pump().catch((error) => {\n reader.releaseLock();\n controller.error(error);\n });\n },\n });\n };\n\n const encoderStream = createAudioDataStream(encoderResultStream);\n const previewStream = createAudioDataStream(previewResultStream);\n\n await encoderChannel.sendStream(encoderStream, streamMetadata);\n\n this.channel.sendStream(previewStream, streamMetadata);\n\n this.encoderStreamAttached = true;\n await this.scheduleMix();\n }\n\n private async bufferTrackStream(\n trackId: string,\n stream: ReadableStream<AudioData>,\n metadata: Record<string, any>\n ): Promise<void> {\n const buffer = this.trackBuffers.get(trackId);\n if (!buffer) {\n await stream.cancel();\n return;\n }\n\n const reader = stream.getReader();\n const process = async (): Promise<void> => {\n while (true) {\n if (buffer.queue.length >= this.maxQueuedSegments) {\n await this.waitForQueueSpace(trackId);\n }\n\n const { done, value } = await reader.read();\n if (done) {\n buffer.ended = true;\n reader.releaseLock();\n return;\n }\n\n buffer.queue.push({\n audioData: value,\n timestampUs: value.timestamp ?? 0,\n durationUs:\n value.duration ??\n Math.round((value.numberOfFrames / (metadata.sampleRate ?? 48_000)) * 1_000_000),\n });\n\n // mix scheduling is triggered after queue updates via scheduleMix()\n this.scheduleMix();\n }\n };\n\n process().catch((error) => {\n buffer.ended = true;\n reader.releaseLock();\n console.error('[AudioComposeWorker] Track stream error:', error);\n });\n }\n\n private async scheduleMix(): Promise<void> {\n if (this.mixing || !this.mixStream || !this.encoderStreamAttached || !this.mixer) {\n return;\n }\n\n const window = this.computeNextWindow();\n if (!window) {\n return;\n }\n\n this.mixing = true;\n try {\n const request = this.buildMixRequest(window.timeUs, window.durationUs);\n if (!request) {\n return;\n }\n\n const writer = this.mixStream.writable.getWriter();\n try {\n await writer.write(request);\n } finally {\n writer.releaseLock();\n }\n } catch (error) {\n console.error('[AudioComposeWorker] Failed to enqueue mix request:', error);\n } finally {\n this.mixing = false;\n if (this.hasBufferedAudio()) {\n queueMicrotask(() => {\n void this.scheduleMix();\n });\n }\n }\n }\n\n private computeNextWindow(): { timeUs: TimeUs; durationUs: TimeUs } | null {\n let earliest: TimeUs | null = null;\n\n for (const buffer of this.trackBuffers.values()) {\n if (buffer.queue.length === 0) {\n continue;\n }\n const firstFrame = buffer.queue[0];\n if (!firstFrame) {\n continue;\n }\n const ts = firstFrame.timestampUs;\n if (earliest === null || ts < earliest) {\n earliest = ts;\n }\n }\n\n if (earliest === null) {\n return null;\n }\n\n return {\n timeUs: earliest,\n durationUs: this.mixWindowUs,\n };\n }\n\n private buildMixRequest(timeUs: TimeUs, _durationUs: TimeUs): MixRequest | null {\n if (!this.mixer) {\n return null;\n }\n\n const tracks: MixRequest['tracks'] = [];\n let resolvedDurationUs = this.mixWindowUs;\n\n for (const [trackId, buffer] of this.trackBuffers.entries()) {\n const segment = this.consumeSegment(trackId, buffer);\n if (!segment) {\n continue;\n }\n\n tracks.push({\n trackId,\n clipId: buffer.clipId,\n audioData: segment.audioData,\n config: segment.config,\n type: buffer.type,\n sampleRate: this.mixer.config.sampleRate,\n numberOfChannels: this.mixer.config.numberOfChannels,\n });\n\n resolvedDurationUs = Math.min(resolvedDurationUs, segment.durationUs ?? this.mixWindowUs);\n }\n\n if (tracks.length === 0) {\n return null;\n }\n\n return {\n tracks,\n timeUs,\n durationUs: resolvedDurationUs,\n };\n }\n\n private consumeSegment(\n trackId: string,\n buffer: TrackBuffer\n ): {\n audioData: AudioData;\n config: AudioTrackConfig;\n sampleRate: number;\n numberOfChannels: number;\n durationUs?: TimeUs;\n } | null {\n if (buffer.queue.length === 0) {\n return null;\n }\n\n const head = buffer.queue[0];\n if (!head) {\n return null;\n }\n\n const queueItem = buffer.queue.shift();\n if (!queueItem) {\n return null;\n }\n\n this.resolveQueueWaiter(trackId);\n\n return {\n audioData: queueItem.audioData,\n config: buffer.config,\n sampleRate: this.mixer!.config.sampleRate,\n numberOfChannels: this.mixer!.config.numberOfChannels,\n durationUs: queueItem.durationUs,\n };\n }\n\n private hasBufferedAudio(): boolean {\n for (const buffer of this.trackBuffers.values()) {\n if (buffer.queue.length > 0) {\n return true;\n }\n }\n return false;\n }\n\n private cloneTrackConfig(config: AudioTrackConfig): AudioTrackConfig {\n return {\n startTimeUs: config.startTimeUs,\n durationUs: config.durationUs,\n volume: config.volume,\n fadeIn: config.fadeIn ? { ...config.fadeIn } : undefined,\n fadeOut: config.fadeOut ? { ...config.fadeOut } : undefined,\n effects: config.effects\n ? config.effects.map((effect) => ({\n type: effect.type,\n params: effect.params ?? {},\n }))\n : undefined,\n duckingTag: config.duckingTag,\n };\n }\n\n private applyTrackConfigPatch(target: AudioTrackConfig, patch: Partial<AudioTrackConfig>): void {\n if (patch.fadeIn) {\n target.fadeIn = { ...patch.fadeIn };\n } else if (patch.fadeIn === null) {\n target.fadeIn = undefined;\n }\n\n if (patch.fadeOut) {\n target.fadeOut = { ...patch.fadeOut };\n } else if (patch.fadeOut === null) {\n target.fadeOut = undefined;\n }\n\n if (patch.effects) {\n target.effects = patch.effects.map((effect) => ({\n type: effect.type,\n params: effect.params ?? {},\n }));\n }\n\n if (typeof patch.volume === 'number') {\n target.volume = patch.volume;\n }\n\n if (patch.startTimeUs !== undefined) {\n target.startTimeUs = patch.startTimeUs;\n }\n\n if (patch.durationUs !== undefined) {\n target.durationUs = patch.durationUs;\n }\n\n if (patch.duckingTag !== undefined) {\n target.duckingTag = patch.duckingTag;\n }\n }\n\n private async waitForQueueSpace(trackId: string): Promise<void> {\n const existing = this.trackQueueWaiters.get(trackId);\n if (existing && existing.length === 0) {\n this.trackQueueWaiters.delete(trackId);\n }\n\n await new Promise<void>((resolve) => {\n const waiters = this.trackQueueWaiters.get(trackId);\n if (waiters) {\n waiters.push(resolve);\n } else {\n this.trackQueueWaiters.set(trackId, [resolve]);\n }\n });\n }\n\n private resolveQueueWaiter(trackId: string): void {\n const waiters = this.trackQueueWaiters.get(trackId);\n if (!waiters || waiters.length === 0) {\n return;\n }\n\n const resolve = waiters.shift();\n resolve?.();\n if (!waiters.length) {\n this.trackQueueWaiters.delete(trackId);\n }\n }\n\n private disposeTrackBuffer(trackId: string): void {\n const buffer = this.trackBuffers.get(trackId);\n if (!buffer) {\n return;\n }\n\n for (const item of buffer.queue) {\n try {\n item.audioData.close();\n } catch (error) {\n console.warn('[AudioComposeWorker] Failed to close AudioData on disposal', error);\n }\n }\n\n this.trackBuffers.delete(trackId);\n\n const waiters = this.trackQueueWaiters.get(trackId);\n if (waiters) {\n waiters.forEach((resolve) => resolve());\n this.trackQueueWaiters.delete(trackId);\n }\n }\n}\n\n// Initialize worker\nconst worker = new AudioComposeWorker();\n\n// Handle worker termination\nself.addEventListener('beforeunload', () => {\n worker['handleDispose']();\n});\n\nexport default null; // Required for TypeScript worker compilation\n"],"names":["channels"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { W as WorkerChannel, a as WorkerMessageType, b as WorkerState } from "../../WorkerChannel.DjBEVvEA.js";
1
+ import { W as WorkerChannel, a as WorkerMessageType, b as WorkerState } from "../../WorkerChannel.DQK8rAab.js";
2
2
  function measureTextWidth(ctx, text, fontSize, fontFamily, fontWeight = 400) {
3
3
  ctx.save();
4
4
  ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
@@ -2511,4 +2511,4 @@ export {
2511
2511
  VideoComposeWorker,
2512
2512
  videoCompose_worker as default
2513
2513
  };
2514
- //# sourceMappingURL=video-compose.worker.CQwmNfXT.js.map
2514
+ //# sourceMappingURL=video-compose.worker.CA2_Kpg-.js.map