I have been exploring some of the samples which are listed here: Google Chrome Labs - Audio Worklet. They have helped me get most of the way to implementing my own WASM based AudioWorklet. It soon came to my attention that Safari doesn't support Worklet.addModule()
? I can't find any alternative ways online that demonstrate how to implement a Audio Worklet without addModule
, can anyone help me understand if it is possible use an Audio Worklet in Safari without this method?

- 39
- 5
2 Answers
I found that in Chrome, you have to:
// wait for user interaction
const context = new AudioContext()
await context.audioWorklet.addModule('./worklet.js')
const worklet = new AudioWorkletNode(context, 'workletName')
worklet.connect(context.destination)
However in Safari, if I enable "Console > Media Logging" I can see this fails with
BaseAudioContext::willBeginPlayback returning false, not processing user gesture or capturing
This seems to be due to the await
between the user interaction and the new AudioWorkletNode
.
If I change the order in Safari to:
const context = new AudioContext()
await context.audioWorklet.addModule('./worklet.js')
// wait for user interaction
const worklet = new AudioWorkletNode(context, 'workletName')
worklet.connect(context.destination)
This works, but it now doesn't work in Chrome (!) which now gives the error:
The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page
Perhaps enable "Console > Media Logging" is Safari dev tools and see if this is the same issue you are getting?
To make it work in both Safari and Chrome, you can create the AudioContext on page load and then call resume after user interaction:
const context = new AudioContext()
await context.audioWorklet.addModule('./worklet.js')
// wait for user interaction
await context.resume();
const worklet = new AudioWorkletNode(context, 'workletName')
worklet.connect(context.destination)

- 2,572
- 4
- 27
- 50
-
Safari requires a user interaction for media to play. The interaction must be within a very short time of the audio playback being requested. The problem here is that the worklet js code is being loaded on-demand only after the user interaction happens, meaning that it's often too late. (This explains why it sometimes works, when the file is cached or the network is fast). – Joby Taffey Mar 05 '23 at 12:50
I'm not sure why it didn't work for you but the latest versions of Safari support the AudioWorklet
(with some bugs). It doesn't work on pages served over http. But it should work on pages served over https though. Maybe that was the issue.
If you want to support older browsers (that don't support the AudioWorklet
yet) you could try standardized-audio-context or jariseon/audioworklet-polyfill or GoogleChromeLabs/audioworklet-polyfill or audioworkletpolyfill.js from the javascriptmusic project.

- 7,025
- 15
- 21
-
Thanks for your help, I was looking in to your standardised-audio-context recently actually. I can see that Safari does work with AudioWorklets in principle but I cannot find how to load a audioworklet file without using .addModule (which isn't supported by safari). Are you aware of the process of adding a workout without using .addModule? I've tested my site with https to be sure, but it did not work. – James Greenaway Aug 09 '22 at 22:53
-
I know that it is possible, https://jackschaedler.github.io/karplus-stress-tester/ works fine in Safari, it uses https://ringbuf-js.netlify.app. However I find the code in this project so complex that I can't really understand how it works. I'd rather follow the GoogleChromeLabs example but I can't get it to work with Safari, nor find any documentation on how I could. – James Greenaway Aug 09 '22 at 22:56
-
Maybe I'm missing something but Jack's code is also using `addModule()`. https://github.com/jackschaedler/karplus-stress-tester/blob/11cd99fe98b54a4771e86876db78b73e0b4e009f/index.html#L148 – chrisguttandin Aug 11 '22 at 07:55