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

Failed to set the 'currentTime' property on 'HTMLMediaElement' error when using MediaElement backend

Open matyasforian opened this issue 4 years ago • 3 comments

Wavesurfer.js version(s):

3.3.3

Browser and operating system version(s):

latest Chrome (v83), Windows 10

Use behaviour needed to reproduce the issue:

This is the code:

playerRef.current = WaveSurfer.create({
    barWidth: 3,
    cursorWidth: 1,
    container: '#waveform',
    // see https://github.com/katspaugh/wavesurfer.js#can-the-audio-start-playing-before-the-waveform-is-drawn
    backend: 'MediaElement',
    height: 60,
    progressColor: '#2D5BFF',
     responsive: true,
     waveColor: '#EFEFEF',
     cursorColor: 'transparent',
});

// Called when a song is buffered and ready to play
playerRef.current.on('ready', function () {
     playerRef.current!.play();
     setLoading(false);
});

Try to load an .mp3 while one is playing, but the waveform is not loaded yet, it will result in the exception. This is the stack trace:

TypeError: Failed to set the 'currentTime' property on 'HTMLMediaElement': The provided double value is non-finite.

WaveSurfer/src/mediaelement.js:275
  272 |  */
  273 | seekTo(start) {
  274 |     if (start != null) {
> 275 |         this.media.currentTime = start;
      | ^  
  276 |     }
  277 |     this.clearPlayEnd();
  278 | }
WaveSurfer.seekTo
WaveSurfer/src/wavesurfer.js:906
  903 | // avoid small scrolls while paused seeking
  904 | const oldScrollParent = this.params.scrollParent;
  905 | this.params.scrollParent = false;
> 906 | this.backend.seekTo(progress * this.getDuration());
      | ^  
  907 | this.drawer.progress(progress);
  908 | 
  909 | if (!paused) {
WaveSurfer.stop
WaveSurfer/src/wavesurfer.js:923
 920 |  */
  921 | stop() {
  922 |     this.pause();
> 923 |     this.seekTo(0);
      | ^  
  924 |     this.drawer.progress(0);
  925 | }

After some debugging the issue is in mediaelement.js's getDuration() method:

getDuration() {
        if (this.explicitDuration) {
            return this.explicitDuration;
        }
        let duration = (this.buffer || this.media).duration;
        if (duration >= Infinity) {
            // streaming audio
            duration = this.media.seekable.end(0); // <- This returns Infinity!!
        }
        return duration;
    }

matyasforian avatar Jun 07 '20 22:06 matyasforian

A workaround is to call pause() before loading a new mp3.

matyasforian avatar Jun 08 '20 06:06 matyasforian

the solution is to edit the function like this:

if (start != null && !isNaN(start)) { this.media.currentTime = start; }

NareshBisht avatar Oct 10 '21 06:10 NareshBisht

[workaround] Loading Wavesurfer on loadedmetadata event of video might fix the issue.

RanjeetEppa18 avatar Mar 23 '22 06:03 RanjeetEppa18