From fbb1baea7a73f3fbe8b3595bcf4a8d3d0367fb04 Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Wed, 8 Nov 2023 08:04:37 +0100 Subject: [PATCH] Fix: allow loading an empty URL string with peaks (#3326) * Fix: allow loading an empty URL string with peaks * Fix tests --- cypress/e2e/options.cy.js | 3 +-- src/plugins/minimap.ts | 4 ++-- src/wavesurfer.ts | 39 ++++++++++++--------------------------- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/cypress/e2e/options.cy.js b/cypress/e2e/options.cy.js index f1e9e84c8..a4f736b67 100644 --- a/cypress/e2e/options.cy.js +++ b/cypress/e2e/options.cy.js @@ -544,9 +544,8 @@ describe('WaveSurfer options tests', () => { duration: 12.5, }) - expect(wavesurfer.getDuration().toFixed(2)).to.equal('12.50') - wrapReady(wavesurfer, 'redraw').then(() => { + expect(wavesurfer.getDuration().toFixed(2)).to.equal('12.50') cy.get(id).matchImageSnapshot('pre-decoded-no-audio') done() }) diff --git a/src/plugins/minimap.ts b/src/plugins/minimap.ts index bc799b741..003cc8e23 100644 --- a/src/plugins/minimap.ts +++ b/src/plugins/minimap.ts @@ -91,9 +91,9 @@ class MinimapPlugin extends BasePlugin { this.initTimerEvents() this.initPlugins() - // Load audio if URL is passed or an external media with an src - const url = this.options.url || this.getSrc() - if (url) { + // Load audio if URL or an external media with an src is passed, + // of render w/o audio if pre-decoded peaks and duration are provided + const url = this.options.url || this.getSrc() || '' + if (url || (this.options.peaks && this.options.duration)) { this.load(url, this.options.peaks, this.options.duration) - } else if (this.options.peaks && this.options.duration) { - // If pre-decoded peaks and duration are provided, render a waveform w/o loading audio - this.loadPredecoded() } } @@ -329,21 +327,6 @@ class WaveSurfer extends Player { return this.plugins } - private async loadPredecoded() { - if (this.options.peaks && this.options.duration) { - this.decodedData = Decoder.createBuffer(this.options.peaks, this.options.duration) - await Promise.resolve() // wait for event listeners to subscribe - this.renderDecoded() - } - } - - private async renderDecoded() { - if (this.decodedData) { - this.emit('decode', this.getDuration()) - this.renderer.render(this.decodedData) - } - } - private async loadAudio(url: string, blob?: Blob, channelData?: WaveSurferOptions['peaks'], duration?: number) { this.emit('load', url) @@ -362,22 +345,24 @@ class WaveSurfer extends Player { // Wait for the audio duration // It should be a promise to allow event listeners to subscribe to the ready and decode events - duration = + const audioDuration = (await Promise.resolve(duration || this.getDuration())) || (await new Promise((resolve) => { this.onceMediaEvent('loadedmetadata', () => resolve(this.getDuration())) - })) || - (await Promise.resolve(0)) + })) // Decode the audio data or use user-provided peaks if (channelData) { - this.decodedData = Decoder.createBuffer(channelData, duration) + this.decodedData = Decoder.createBuffer(channelData, audioDuration || 0) } else if (blob) { const arrayBuffer = await blob.arrayBuffer() this.decodedData = await Decoder.decode(arrayBuffer, this.options.sampleRate) } - this.renderDecoded() + if (this.decodedData) { + this.emit('decode', this.getDuration()) + this.renderer.render(this.decodedData) + } this.emit('ready', this.getDuration()) } @@ -464,7 +449,7 @@ class WaveSurfer extends Player { this.setTime(this.getCurrentTime() + seconds) } - /** Empty the waveform by loading a tiny silent audio */ + /** Empty the waveform */ public empty() { this.load('', [[0]], 0.001) }