diff --git a/src/components/video-editor/timeline/components/waveform/WaveformGenerator.ts b/src/components/video-editor/timeline/components/waveform/WaveformGenerator.ts index 7ff7f26c..07d00419 100644 --- a/src/components/video-editor/timeline/components/waveform/WaveformGenerator.ts +++ b/src/components/video-editor/timeline/components/waveform/WaveformGenerator.ts @@ -8,29 +8,40 @@ export class WaveformGenerator { private worker: Worker; private peaksCache = new Map(); private pending = new Map>(); + private workerRequestSeq = 0; + private workerResolvers = new Map void>(); constructor() { this.audioContext = new (window.AudioContext || (window as typeof window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext)(); this.worker = new WorkerConstructor(); + this.worker.addEventListener( + "message", + (event: MessageEvent<{ requestId: number; peaks: Float32Array }>) => { + const { requestId, peaks } = event.data; + const resolve = this.workerResolvers.get(requestId); + if (!resolve) return; + this.workerResolvers.delete(requestId); + resolve(peaks); + }, + ); } private computePeaksWithWorker(channelData: Float32Array, samples: number): Promise { return new Promise((resolve, reject) => { - const onMessage = (event: MessageEvent) => { - this.worker.removeEventListener("message", onMessage); - this.worker.removeEventListener("error", onError); - resolve(event.data); - }; + const requestId = ++this.workerRequestSeq; const onError = (error: ErrorEvent) => { - this.worker.removeEventListener("message", onMessage); this.worker.removeEventListener("error", onError); + this.workerResolvers.delete(requestId); reject(error.error ?? new Error(error.message)); }; - - this.worker.addEventListener("message", onMessage); - this.worker.addEventListener("error", onError); + this.worker.addEventListener("error", onError, { once: true }); + this.workerResolvers.set(requestId, (peaks) => { + this.worker.removeEventListener("error", onError); + resolve(peaks); + }); this.worker.postMessage( { + requestId, channelData, samples, }, diff --git a/src/components/video-editor/timeline/components/waveform/waveform.worker.ts b/src/components/video-editor/timeline/components/waveform/waveform.worker.ts index c8a7f8c5..7b7a5184 100644 --- a/src/components/video-editor/timeline/components/waveform/waveform.worker.ts +++ b/src/components/video-editor/timeline/components/waveform/waveform.worker.ts @@ -1,11 +1,12 @@ self.onmessage = (e: MessageEvent) => { - const { channelData, samples } = e.data as { + const { requestId, channelData, samples } = e.data as { + requestId: number; channelData: Float32Array; samples: number; }; if (!channelData || samples <= 0) { - self.postMessage(new Float32Array(0)); + self.postMessage({ requestId, peaks: new Float32Array(0) }); return; } @@ -24,8 +25,8 @@ self.onmessage = (e: MessageEvent) => { result[i] = max; } - self.postMessage(result); + self.postMessage({ requestId, peaks: result }); } catch { - self.postMessage(new Float32Array(0)); + self.postMessage({ requestId, peaks: new Float32Array(0) }); } };