fix: Web safari audio context reuse#1972
Conversation
|
Thank you for your contribution! |
|
@Szymon-Gesicki Actually I wanted to reproduce your error. I tested online via https://bluefireteam.github.io/audioplayers/ which still has a build without your fix and also tested locally. I could not reproduce your issue: The audio played multiple times in "release" mode, even after 10 times.
|
|
Hi, thanks for testing, let me clarify:
The third print("play 3") call produces no audio on Safari, on chrome everything works perfect.
I initially only tested on macOS 15.7.3, Safari 18.6. I tested on iOS today and unfortunately the problem still occurs there. I will work on a fix for that. I'm also preparing a separate fix for a volume setting issue on Safari. When I do that, I will also test macOS 26.
https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/AudioContext:
I don't have anything black on white confirming the same limit on macOS Safari specifically. |
|
I think your other problem is not releated to Safari, it didn't work on Chrome either: |
# Description If playing multiple sources one after one in the same player, the sources sometimes would not play in `release` mode. ```dart final player = AudioPlayer(); String audioUrl1 = "https://cdn.pixabay.com/audio/2021/08/04/audio_12b0c7443c.mp3"; print("play 1"); await player.play(UrlSource(audioUrl1)); await Future.delayed(const Duration(seconds: 3)); await player.stop(); print("play 2"); await player.play(UrlSource(audioUrl1)); await Future.delayed(const Duration(seconds: 3)); await player.stop(); print("play 3"); await player.play(UrlSource(audioUrl1)); await Future.delayed(const Duration(seconds: 3)); await player.stop(); ``` The `pausedAt` property is now reset, when calling `release` which allows playing the next source at 0.
Description
Fix audio playback on Safari (web) by reusing a single
AudioContextper player instance and explicitly resuming it before playback.Closes #1759
Existing behavior:
recreateNode()created a newweb.AudioContext()on every call and stored it only as a local variable. This caused three problems:suspendedstate and requires an explicitresume()within a user gesture — this call was missing entirely, so audio never played.recreateNode()returned, making it impossible to resume or close later.Chrome auto-resumes AudioContexts, which is why the issue only manifested on Safari.
Changes:
AudioContextandMediaElementAudioSourceNodeas class-level fields onWrappedPlayer.AudioContextacrossrecreateNode()calls (_audioContext ??= web.AudioContext()).audioContext.resume()instart()when the context is suspended (required by Safari)._sourceNodeinrelease()for proper cleanup without closing the shared context.AudioContextindispose()to prevent resource leaks.All changes are in a single file:
packages/audioplayers_web/lib/wrapped_player.dart.Checklist
fix:,feat:,refactor:,docs:,chore:,test:,ci:etc).///, where necessary.Breaking Change
Related Issues