peaks.js icon indicating copy to clipboard operation
peaks.js copied to clipboard

Browser generated waveform loading previous waveform on differents peaks instances in chrome

Open WisePlatypus opened this issue 4 years ago • 3 comments

When generating waveform with an audioContext for the second time on a different instance of peaks. (destroying the previous and init another one). The waveform shown is the same as the previous one. On next call n audio will be loaded with n-1 waveform and timeline.

This bug only works in chrome.

(I only tested this by downloading audio file manually as a blob)

Minimal bug replication: https://repl.it/@daWisePlatypus/browserWaveformPeaksJs#script.js

I'm reporting this because I think it is not the intended behaviour. If you have downloaded your file as a blob you can easily work around by extracting manually the audioBuffer and provide it in peaks init as such:

blob.arrayBuffer().then(arrayBuffer=> {

      let audioContext = new AudioContext();      

      audioContext.decodeAudioData(arrayBuffer, (audioBuffer) => {
      
      peaksInstance = Peaks.init(
      {
             webAudio:
            {
                  audioBuffer: audioBuffer,
            },
            ...otherPeaksOptions
       });
      audioContext.close();
});

WisePlatypus avatar Jan 11 '21 09:01 WisePlatypus

Thanks for reporting this, and for including the code to reproduce the issue. This will help me investigate what's going on.

chrisn avatar Jan 11 '21 17:01 chrisn

We may need to fix Peaks.init(), but the way I suggest you implement this is to call peaksInstance.setSource() to change the audio URL instead of destroying and re-creating the Peaks instance:

peaksInstance.setSource({
  mediaUrl: yourMp3Url,
  webAudio: { audioContext: audioContext }
},
(err) => {
  if (err) console.error(err);
});

Peaks.init() checks currentSrc to detect whether the media element has been initialised, see WaveformBuilder._buildWaveformDataUsingWebAudio and https://github.com/bbc/peaks.js/issues/112#issuecomment-356131073.

The difference between Chrome and Firefox is that Firefox sets the media element's currentSrc to an empty string after you change src, whereas Chrome does not, and this leads to Peaks.init() getting confused.

There's a related HTML spec issue here: https://github.com/whatwg/html/issues/3988. FWIW, my reading of the spec is that Chrome's behaviour is per-spec, and I wouldn't expect currentSrc to change to an empty string on setting src - although arguably the Firefox behaviour could be preferable.

chrisn avatar Jan 12 '21 11:01 chrisn

Thanks!

I need to have different peaks instance. The init will be called a second time anyway. My work around works, so I'll just decode my audioBuffer before for now.

WisePlatypus avatar Jan 15 '21 11:01 WisePlatypus