Skip to content

Player: the audio output can be chosen (Firefox's own device chooser) - #580

Merged
Nawid3333 merged 5 commits into
mainfrom
player/audio-output
Oct 24, 2026
Merged

Nawid3333 merged 5 commits into
mainfrom
player/audio-output

Conversation

@Nawid3333

Copy link
Copy Markdown
Owner

The sound can now play on another device than the system's default, headphones for example. The audio button's list gets an Audio output part with three rows: Default output, the device chosen, and Choose an output…, which opens Firefox's own device chooser.

How it routes the sound

  • All of the player's sound runs through Web Audio, and Firefox has no AudioContext.setSinkId.
  • For a chosen device, the graph's end goes into a MediaStreamAudioDestinationNode, and a hidden <audio> plays that stream on the device (setSinkId).
  • The graph moves over only once that element plays, so the sound never plays on both outputs or on neither.
  • For the default output nothing changes: anyone who never chooses gets exactly the old path.

Measured in Firefox 158 first (extension pages; the harness answers the chooser with media.navigator.permission.disabled):

Question Result
selectAudioOutput, element setSinkId yes
AudioContext.setSinkId no
In a page's iframe without allow="speaker-selection" refused (NotAllowedError, permissions policy); content.js now gives the player's iframe the token
selectAudioOutput without a click, even with a known deviceId InvalidStateError: requires transient user activation
The saved device in the next video's player (a new document) NotFoundError

So each new video starts on the default output and says so

  • The status line shows "The sound plays on the default output: click here to play it on Headphones."
  • One click opens the chooser with that device already picked, or with nothing picked if the device is gone.
  • A device unplugged while it plays (devicechange) sends the sound back to the default output, with the same notice.
  • Choosing from the list clears the notice.
  • The status line gained an optional click handler for this. Messages without one behave as before.

Not established

  • Whether Firefox's real prompt can be remembered, so the chooser no longer appears.
  • The latency the detour adds, which affects A/V sync.
  • Whether more than 2 channels get through the detour. The detour follows the video's channel count either way.

glm-5.3-flash as helper and checker

  • It drafted the unit tests and the menu part. I checked both and adapted them.
  • Its two reviews found 6 real bugs, each now with a test that is red without its fix:
    • the kept choice was read once, so "Default output" was undone by the next video;
    • a route overtaken by a newer action could report a false failure or touch a closed context;
    • choose() could save a choice the user had already abandoned;
    • the channel count did not follow the video;
    • a click for a device that is gone did nothing;
    • a notice went stale after a choice from the list.
  • One finding was wrong and left out: new Audio() does not set autoplay.
  • Its design check confirmed that no Firefox API avoids the click per new document. Only a player document that lasts across episodes would, which would be a much bigger change.

Tests

  • AudioOutputDevice.test.mjs (20).
  • statusLevels.test.mjs: a clickable message; both tests are red on the old StatusManager.
  • audio-output.e2e.mjs in a page's iframe: choose a device, the next video's notice and its click, back to the default. It passed in Firefox 158 and skips on a machine without audio output (CI's runners may have none).
  • Lint, typecheck and unit tests (3158) green locally.
  • 7 strings in 16 locales (gemma4:cloud, checked; six "choose it again" phrasings fixed by hand).

🤖 Generated with Claude Code

Nawid3333 and others added 5 commits October 24, 2026 12:24
The audio button's list gets an "Audio output" part: Default output, the device chosen, and
"Choose an output..." (Firefox's selectAudioOutput). All of the player's sound runs through
Web Audio and Firefox has no AudioContext.setSinkId, so for a chosen device the graph's end
moves to a MediaStreamAudioDestinationNode that a hidden <audio> plays on the device
(setSinkId); the default output is unchanged.

Measured on Firefox 158: the chooser needs a click, also for a known device, and a device is
usable only in the page it was chosen in. So the choice is kept, and each new video starts on
the default output and says so: one click on the notice opens the chooser with that device
picked. An unplugged device goes back to the default output with the same notice. The
player's iframe gets allow="speaker-selection" (Firefox refuses both calls without it).

- AudioOutputDevice.mjs, its tests drafted by glm-5.3-flash and checked; glm's two reviews
  found six real bugs (a frozen kept choice, overtaken routes, an abandoned choice saved, the
  channel count, a gone preselected device, a stale notice), each with a test red without it.
- StatusManager: a message may have a click of its own (it shows as clickable).
- 7 strings in 16 locales (gemma4:cloud, checked; six "choose it again" fixed by hand).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	chrome/_locales/de/messages.json
#	chrome/_locales/en/messages.json
#	chrome/_locales/es/messages.json
#	chrome/_locales/fr/messages.json
#	chrome/_locales/id/messages.json
#	chrome/_locales/it/messages.json
#	chrome/_locales/ja/messages.json
#	chrome/_locales/ko/messages.json
#	chrome/_locales/ms/messages.json
#	chrome/_locales/nl/messages.json
#	chrome/_locales/pl/messages.json
#	chrome/_locales/pt_BR/messages.json
#	chrome/_locales/ru/messages.json
#	chrome/_locales/tr/messages.json
#	chrome/_locales/zh_CN/messages.json
#	chrome/_locales/zh_TW/messages.json
#	combined-locales.json
… and counts track rows only

The audio list has an "Audio output" part under its tracks now (AudioOutputDevice), and its
button shows wherever this Firefox can choose an output, also with one track; the test
expected it hidden there (CI's Linux and Firefox Beta playback shards).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nawid3333
Nawid3333 merged commit d4c5a07 into main Oct 24, 2026
34 checks passed
@Nawid3333
Nawid3333 deleted the player/audio-output branch October 24, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant