WebGL Audio Output Device

I’m a developer working with another team that is responsible for generating 3D content in a web app. We use UnityLoader to pull this content in.

I’ve been reading through the WebGL roadmap and documentation. My question is:
Is it possible to change the audio output device that WebGL uses?

And if so, can the browser dictate this device through UnityLoader, or would the source code of the 3D content be responsible for selecting and using the desired output audio device?

From what I’m reading, it seems the capabilities don’t exist yet. I just want to be sure I’ve checked everywhere. Thanks in advance!

Chiming in to indicate that there are others struggling with this as well. It would be nice if there was (at minimum) a way to access the audio context that WebGL uses (assuming this is how it outputs sound?) on the web app.

Do you mean configuring the physical audio output device, like display speakers vs headphones vs separate speakers? If so, I don’t think there exists a web API for allowing web content to choose the speaker output mode. So the only way to choose the output audio device is to choose it manually from the OS task bar audio widget.

Or if I missed what you mean, I wonder if there is an existing audio site that does what you are looking for - then there should exist a web specification for doing that.

Exactly. You are correct in the sense that there’s not an API for it like there is for audio/video input (getUserMedia) but there is a way to choose the audio output device for a HTMLMediaElement via setSinkId (https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId), albeit with limited browser support.

We would like to be able to take advantage of this feature (on supported browsers) but we seemingly have no access to whatever is playing WebGL’s audio.

Thanks for posting the link. That setSinkId() applies to a different web audio API that is not good for games use cases. Unity and game engines in general use Web Audio API.

Now with searching found out that Web Audio API is discussing that same use case in this issue: Access to a different output device: AudioContext.setSinkId() · Issue #2400 · WebAudio/web-audio-api · GitHub . Added a comment there that this feature request has come up, hopefully Web Audio API people will be able to add that to the spec.

Thank you for the quick replies! It’s good to see that there is an ongoing conversation about this to improve the Web Audio API.

I’m aware of this current limitation, but it is still technically possible to use sinkId with the Web Audio API by attaching the audio context to an HTML audio element.

Please check this the answer on this SO question: How to select destination output device using Web Audio API - Stack Overflow

This same solution is also proposed in the Github issue you linked: Access to a different output device: AudioContext.setSinkId() · Issue #2400 · WebAudio/web-audio-api · GitHub

The reality is that there may be issues with this proposed workaround, but we don’t know (and are unable to try) because we have no access to the audio context that Unity is using.

Thanks for pointing that out. I have not been aware of that API to route Web Audio to an

Now looking further, it seems that Unity does not currently have a C# API that would allow one to select the audio output device? (a feature request has been discussed here at least: Selecting the audio output device ). That makes it hard to expose this feature to user.

You can access the AudioContext of Unity by editing the file C:\Program Files\Unity\Hub\Editor\2020.2.2f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\lib\Audio.js and then doing a project rebuild. On line ~14ish you’ll see code

WEBAudio.audioContext = new AudioContext();

You can try doing there something like

window.myGameAudioContext = WEBAudio.audioContext = new AudioContext();

after which when you do a project rebuild, you should see the Audio Context accessible via window.myGameAudioContext, if you’d like to manually try the code out.

I’ve recorded this feature request to the team to look at in the future.

1 Like

Awesome, this is promising. We are able to find and edit the Audio.js file locally as you suggested, but the problem is that we’re using Unity Cloud Build (UCB) to build our project out, which will not use the updated Audio.js file.

We’ve found in the UCB build logs that it seems to reference similar WebGLSupport files like so:

/Volumes/2019_4_0f1/PlaybackEngines/WebGLSupport/BuildTools/lib/modules/WebGLSupport_AccessibilityModule_Dynamic.bc

But we do not see the actual Audio.js file anywhere in the logs. We’re assuming we don’t because the line that’s referencing a lot of these WebGLSupport files gets truncated.

So essentially the question is: do you know of a way for us to edit the Audio.js file that is used by UCB when building out the project?

Sorry, unfortunately that will not be possible :frowning: You would have to do the build locally for such a change.

Btw, there were some comments added after my comment at Access to a different output device: AudioContext.setSinkId() · Issue #2400 · WebAudio/web-audio-api · GitHub that mention that the feature might not work in Chrome and/or other browsers.

Any chance would you be able to test it in JavaScript (e.g. in a standalone test app) and provide user feedback into that Web Audio API thread if it will even work for the use case in your application? E.g. for a skeleton to get started, you could use GitHub - juj/audio_test_suite: Test files for audio playback with different types of audio effects which demonstrates the same audio playback technique that Unity uses. A file such as audio_test_suite/8bit_detective/8bit_detective.html at master · juj/audio_test_suite · GitHub can be used as a basis.

You’d add the code from audio_test_suite/8bit_detective/8bit_detective.html at master · juj/audio_test_suite · GitHub right after this line audio_test_suite/8bit_detective/8bit_detective.html at 855015be472030696d14257f0d3ecd09158b1892 · juj/audio_test_suite · GitHub to do the routing that it is asking.

I can also do such a test, but I am uncertain whether my test will be representative of the use case you are trying to solve in your application, so it would be great to have your feedback on this.