1.11 (plus the one on the website)
Safari 11
The sample on https://wavesurfer-js.org/
On the main website example, if you click play/pause quickly multiple times, the seek bar will get 'stuck'.

(By this point, the song is playing and is already nearing it's end, while the seek position is still at the beginning)
As far as my tests go, this bug seems to not be present on Chrome (61)
It happens for me also on a simple play/pause action on Safari 11.0.
I also stop receiving callbacks.
On chrome it works great.
In my project it happens every time I pause the player. In your examples it happens only if you pause and play rapidly, I can't tell why.
I use wavesurfer on React.
At first I used react-wavesurfer. When I noticed the bug I opened a new issue.
Then I replaced it with wavesurfer.js and tailored in into my react project but the bug keeps happening.
Tried it with v1.4.0 and v2.0.0-beta02.
@pinhassi @Secretmapper Do you get any error messages? Can you maybe check if there are uncaught exceptions (you should see them if you have the dev tools open when the error appears)
@mspae Unfortunately it doesn't log anything.
If it helps, everything else still work - I can play/pause, seek, etc. and the music updates, but the 'seek bar' itself doesn't move.
anyone found any solution on this?
This happened to me as well after I bound the load file function with the on('ready'){ws.play()}function.
Before this, I was loading the track on page load and binding the play function on click button, and Safari was not giving any problem.
But make a user download 15mb of an audio file, no matter if they hit the play button or not is terrible /:
For me, the wavesurfer example in the homepage using Safari @11.0.1 works perfectly.
Is the new beta fixing this? I am loading wavesurfer through the CDN link (v 1.4.0).
afaik once you press pause, this piece of code in wavesurfer.js stops getting called in Safari (where it is called in Firefox):
this.backend.on('audioprocess', time => {
this.drawer.progress(this.backend.getPlayedPercents());
this.fireEvent('audioprocess', time);
});
This appears to be due to something in WebAudio backend. My guess is that there is some sort of race condition that only happens in Safari, which is preventing the audioprocess event handler from getting attached. This is likely a result of destroying and then creating the buffer source on every pause/play, but I can't prove this. Someone more familiar with the WebAudio API and this project will need to look into that, as I'm in over my head.
A simple workaround would be to force the MediaElement backend, via:
wavesurfer.init({
container: document.querySelector('#wave'),
backend: 'MediaElement'
});
Although I'm guessing that forcing MediaElement has its own drawbacks. It seems to work for my use case.
I was also having an issue where the audio wasn't playing on my iPhone along with the exact situation outlined by @Secretmapper and so I switched the backend to MediaElement and everything is working smoothly now.
I have something similar to this too, whereby audioprocess stops firing after i pause a track. It will happen from the first time i pause. Once I resume audioprocess is dead. I'm using Safari 11.0.3
Is a fix incoming does anyone know?
i'm still getting this posted something additional #1367
the quick fix is to use backend: 'MediaElement'
@mfairchild365 Do u know what the possible drawbacks are?
btw, when i tried by adding backend: 'MediaElement' and tried on safari Version 11.1 (13605.1.33.1.4)
this.waveSurfer = WaveSurfer.create({
container: '#wave',
backend: 'MediaElement',
});
I got this error:
TypeError: undefined is not an object (evaluating 't.querySelector')
value - mediaelement.js:98
value - wavesurfer.js:1122
wavesurfer.js:1109
wavesurfer.js:1305
// mediaelement.js
load(url, container, peaks, preload) {
const media = document.createElement(this.mediaType);
media.controls = this.params.mediaControls;
media.autoplay = this.params.autoplay || false;
media.preload = preload == null ? 'auto' : preload;
media.src = url;
media.style.width = '100%';
**const prevMedia = container.querySelector(this.mediaType);** // line 98
if (prevMedia) {
container.removeChild(prevMedia);
}
container.appendChild(media);
this._load(media, peaks);
}
EDIT: on chrome as well
EDIT: add file name
@katspaugh This issue still exists and is present on Safari 11 and iOS. In certain implementations MediaElement is not a possible solution. Can you please investigate or work on a fix for this issue? It is a huge problem on my current project.
Can you please investigate or work on a fix for this issue? It is a huge problem on my current project.
We're all volunteers here, it's opensource. What do you expect to happen? You'll have to dig into the code and help us all out.
@thijstriemstra you鈥檙e totally right and I apologize. This project is simply a bit out my scope of expertise as I generally come from a mobile development background. I鈥檝e tried looking through the code but haven鈥檛 been able to track down the issue or get a workaround. I鈥檓 just looking for any of the maintainers to perhaps take another look as it would be wonderful if this got solved. I鈥檓 willing to help in whatever way I can.
I am able to reproduce this issue and also, unfortunately, can comment on possible side effects of using the MediaBackend as a workaround.
In my testing a bug which is marked closed (#709) is still present in version 2.0.5 for Firefox 61. Thus, I've determined the following:
As a result I'm forced to use the following browser-sniffing to determine which backend to use:
// Only use MediaElement backend for Safari
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent || '') ||
/iPad|iPhone|iPod/i.test(navigator.userAgent || '');
const wavesurferArgs = {
container: document.getElementById('wavesurferContainerInternal'),
plugins
};
if (isSafari) {
wavesurferArgs.backend = 'MediaElement';
}
_wavesurfer = window.WaveSurfer.create(wavesurferArgs);
The iPad/iPhone portion of the user agent sniffing is there so that Firefox and Chrome on iOS are treated as Safari and not Firefox/Chrome (since they are under the hood re-skinned versions of Safari).
On a more general note, it seems clear from @katspaugh's comments in #709 that MediaElement is not the preferred backend, so it probably makes sense to limit it regardless to only the browsers or scenarios where you know it is absolutely required. IMO, Safari behaves better with it than without, and all other browsers are likely the reverse.
The above solution from @DrLongGhost works great for me with one minor exception.
Like many others, I am pre-rendering the peaks without actually loading the MP3 file, using code like this:
_wavesurfer.backend.peaks = peaks;
_wavesurfer.drawBuffer();
Once the user clicks Play, I then load the audio using the load() method and start playback using a callback that executes once the file is loaded:
// callback that is called when the load() finishes
_wavesurfer.on('ready', () => {
_wavesurfer.play();
});
// load MP3 file
_wavesurfer.load(audioURL,peaks);
This works great in Chrome Windows, and it got my audio to actually play in iOS Safari. However, on iOS (both Safari and Chrome), once you click "play" the waveform will briefly disappear and then reappear.
If anyone knows a way to fix this visual glitch, I'm all ears. If not, I imagine I can live with it.
Most helpful comment
This appears to be due to something in
WebAudiobackend. My guess is that there is some sort of race condition that only happens in Safari, which is preventing theaudioprocessevent handler from getting attached. This is likely a result of destroying and then creating the buffer source on every pause/play, but I can't prove this. Someone more familiar with theWebAudioAPI and this project will need to look into that, as I'm in over my head.A simple workaround would be to force the
MediaElementbackend, via:Although I'm guessing that forcing
MediaElementhas its own drawbacks. It seems to work for my use case.