From 22ccc35cc3451004650746e38fcbee725db994f5 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Fri, 7 Jul 2023 17:36:53 +1000 Subject: [PATCH 01/16] FF116 Audio Output Device API updates --- files/en-us/web/api/htmlmediaelement/index.md | 4 ++-- .../en-us/web/api/htmlmediaelement/setsinkid/index.md | 6 ++++-- files/en-us/web/api/htmlmediaelement/sinkid/index.md | 11 +++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/files/en-us/web/api/htmlmediaelement/index.md b/files/en-us/web/api/htmlmediaelement/index.md index ff2c820dc229d6c..222229fe87d9c6e 100644 --- a/files/en-us/web/api/htmlmediaelement/index.md +++ b/files/en-us/web/api/htmlmediaelement/index.md @@ -73,8 +73,8 @@ _This interface also inherits properties from its ancestors {{domxref("HTMLEleme - : Returns a {{domxref('TimeRanges')}} object that contains the time ranges that the user is able to seek to, if any. - {{domxref("HTMLMediaElement.seeking")}} {{ReadOnlyInline}} - : Returns a boolean that indicates whether the media is in the process of seeking to a new position. -- {{domxref("HTMLMediaElement.sinkId")}} {{ReadOnlyInline}} {{Experimental_Inline}} - - : Returns a string that is the unique ID of the audio device delivering output, or an empty string if it is using the user agent default. This ID should be one of the `MediaDeviceInfo.deviceid` values returned from {{domxref("MediaDevices.enumerateDevices()")}}, `id-multimedia`, or `id-communications`. +- {{domxref("HTMLMediaElement.sinkId")}} {{ReadOnlyInline}} + - : Returns a string that is the unique ID of the audio device delivering output, or an empty string if the user agent default audio device is being used. - {{domxref("HTMLMediaElement.src")}} - : A string that reflects the [`src`](/en-US/docs/Web/HTML/Element/video#src) HTML attribute, which contains the URL of a media resource to use. - {{domxref("HTMLMediaElement.srcObject")}} diff --git a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md index 681389256fdc91f..48576aaf0a03b32 100644 --- a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md @@ -8,8 +8,10 @@ browser-compat: api.HTMLMediaElement.setSinkId {{APIRef("HTML DOM")}} -The **`HTMLMediaElement.setSinkId()`** method sets the ID of the audio device to use for output and returns a [`Promise`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). +The **`HTMLMediaElement.setSinkId()`** method of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) sets the ID of the audio device to use for output and returns a [`Promise`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). + This only works when the application is authorized to use the specified device. +Permission to use a particular device may be blocked by ## Syntax @@ -40,7 +42,7 @@ A {{jsxref("Promise")}} that resolves to {{jsxref("undefined")}}. Access to the API is subject to the following constraints: - The method must be called in a [secure context](/en-US/docs/Web/Security/Secure_Contexts). -- Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/midi) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). +- Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). ## Examples diff --git a/files/en-us/web/api/htmlmediaelement/sinkid/index.md b/files/en-us/web/api/htmlmediaelement/sinkid/index.md index 2084236454bbed7..2a33d54689989e1 100644 --- a/files/en-us/web/api/htmlmediaelement/sinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/sinkid/index.md @@ -3,20 +3,19 @@ title: "HTMLMediaElement: sinkId property" short-title: sinkId slug: Web/API/HTMLMediaElement/sinkId page-type: web-api-instance-property -status: - - experimental browser-compat: api.HTMLMediaElement.sinkId --- -{{SeeCompatTable}}{{APIRef("HTML DOM")}} +{{APIRef("HTML DOM")}} + +The **`HTMLMediaElement.sinkId`** read-only property of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) returns a string that is the unique ID of the audio device delivering output. +If the user agent default device is being used, it returns an empty string. -The **`HTMLMediaElement.sinkId`** read-only property returns a string that is the unique ID of the audio device delivering output. -If it is using the user agent default, it returns an empty string. This ID should be one of the {{domxref("MediaDeviceInfo.deviceId")}} values returned from {{domxref("MediaDevices.enumerateDevices()")}}, `id-multimedia`, or `id-communications`. ## Value -A string. +A string indicating the current audio output device, or the empty string if the default user agent output device is being used. ## Security requirements From 43efef415398ec4a09245359c6c4fe22e1c96d3a Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 10 Jul 2023 17:30:59 +1000 Subject: [PATCH 02/16] selectAudioOutput - fix up errors --- .../mediadevices/selectaudiooutput/index.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index f2af56ded2f75d1..e058b78b6c5343a 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -10,7 +10,13 @@ browser-compat: api.MediaDevices.selectAudioOutput {{APIRef("WebRTC")}} {{SeeCompatTable}} -The {{domxref("MediaDevices")}} method **`selectAudioOutput()`** prompts the user to select a specific audio output device, for example a speaker or headset. +The {{domxref("MediaDevices.selectAudioOutput()")}} method of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) prompts the user to select an audio output device, such as a speaker or headset, and grants user-permission to use the selected device as an audio output sink. + +Following selection, if the device is available it can be enumerated using [`MediaDevices.enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices) and set as the audio output sink using [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId). + +The method can only be called in a [secure context](/en-US/docs/Web/Security/Secure_Contexts) with [transient user activation](/en-US/docs/Web/Security/User_activation), and will only offer audio output devices if allowed by the page [`Permission-Policy: speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection). +For more information see the [security requirements](#security_requirements). + On success, the returned {{jsxref("Promise")}} is resolved with a {{domxref("MediaDeviceInfo")}} describing the selected device. ## Syntax @@ -28,13 +34,15 @@ selectAudioOutput(options) - `deviceId` {{Optional_Inline}} - - : A string representing the id of the (only) device to display in the prompt (with default value: ""). + - : A string representing the id of a single device to display in the prompt. + If not set, all audio output devices for which permission is not explicitly denied will be displayed. + + The option is intended for applications that want to use persisted device ids. > **Note:** A user agent may choose to skip prompting the user if a specified non-null id was previously exposed to the user by `selectAudioOutput()` in an earlier session. > In this case the user agent may simply resolve with this device id, or a new id for the same device if it has changed. > - > This is intended for applications that want to use persisted device ids. - > The ids _must be passed_ through `selectAudioOutput()` successfully before they will work with {{domxref("HTMLMediaElement.setSinkId","setSinkId()")}}. + > Note that persisted ids _must be passed_ through `selectAudioOutput()` successfully before they will work with {{domxref("HTMLMediaElement.setSinkId","setSinkId()")}}. ### Return value @@ -58,8 +66,6 @@ Access to the API is subject to the following constraints: - [Transient user activation](/en-US/docs/Web/Security/User_activation) is required. The user has to interact with the page or a UI element for this feature to work. - Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/midi) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). -- The user must explicitly grant permission to use the audio output device through a user-agent specific mechanism, or have previously granted permission. - Note that if access is denied by a permission policy it cannot be granted by a user permission. The permission status can be queried using the [Permissions API](/en-US/docs/Web/API/Permissions_API) method [`navigator.permissions.query()`](/en-US/docs/Web/API/Permissions/query), passing a permission descriptor with the `speaker-selection` permission. From 35be586a0d099a56e9397172d58d32300bae72f8 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 10 Jul 2023 17:37:31 +1000 Subject: [PATCH 03/16] setSinkId, sinkId fixes --- .../en-us/web/api/htmlmediaelement/setsinkid/index.md | 11 ++++++++--- files/en-us/web/api/htmlmediaelement/sinkid/index.md | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md index 48576aaf0a03b32..a554b9b0346df59 100644 --- a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md @@ -10,8 +10,8 @@ browser-compat: api.HTMLMediaElement.setSinkId The **`HTMLMediaElement.setSinkId()`** method of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) sets the ID of the audio device to use for output and returns a [`Promise`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). -This only works when the application is authorized to use the specified device. -Permission to use a particular device may be blocked by +This only works when the application is permitted to use the specified device. +For more information see the [security requirements](#security_requirements) below. ## Syntax @@ -43,15 +43,20 @@ Access to the API is subject to the following constraints: - The method must be called in a [secure context](/en-US/docs/Web/Security/Secure_Contexts). - Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). +- User permission is required to access a non-default device. + This is granted by selecting the device associated with the ID in the prompt displayed by [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput). ## Examples +This example shows how to select an audio output device from the array returned by [`MediaDevices.enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices), and set it as the sink for audio. +Note that the result of `enumerateDevices()` only includes devices for which user permission is not required or has already been been granted. + ```js const devices = await navigator.mediaDevices.enumerateDevices(); const audioDevice = devices.find((device) => device.kind === "audiooutput"); const audio = document.createElement("audio"); await audio.setSinkId(audioDevice.deviceId); -console.log(`Audio is being played on ${audio.sinkId}`); +console.log(`Audio is being output on ${audio.sinkId}`); ``` ## Specifications diff --git a/files/en-us/web/api/htmlmediaelement/sinkid/index.md b/files/en-us/web/api/htmlmediaelement/sinkid/index.md index 2a33d54689989e1..836961a9674b10b 100644 --- a/files/en-us/web/api/htmlmediaelement/sinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/sinkid/index.md @@ -8,7 +8,7 @@ browser-compat: api.HTMLMediaElement.sinkId {{APIRef("HTML DOM")}} -The **`HTMLMediaElement.sinkId`** read-only property of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) returns a string that is the unique ID of the audio device delivering output. +The **`HTMLMediaElement.sinkId`** read-only property of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) returns a string that is the unique ID of the device to be used for playing audio output. If the user agent default device is being used, it returns an empty string. This ID should be one of the {{domxref("MediaDeviceInfo.deviceId")}} values returned from {{domxref("MediaDevices.enumerateDevices()")}}, `id-multimedia`, or `id-communications`. From 2faa468fb784238b4dfde2fa46f70d8227ff3e9f Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 10 Jul 2023 17:37:55 +1000 Subject: [PATCH 04/16] minor fix --- files/en-us/web/api/mediadevices/selectaudiooutput/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index e058b78b6c5343a..57dd09f62da0196 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -109,4 +109,6 @@ audiooutput: Realtek Digital Output (Realtek(R) Audio) id = 0wE6fURSZ20H0N2Nbxqg ## See also +- [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId) +- [`HTMLMediaElement.sinkId`](/en-US/docs/Web/API/HTMLMediaElement/sinkId) - [WebRTC](/en-US/docs/Web/API/WebRTC_API) - the introductory page to the API From 6f0055d90b554d67ceb492d92bc8562f84c4ce2c Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 10 Jul 2023 17:44:59 +1000 Subject: [PATCH 05/16] Tidy enumeratedDevices --- .../web/api/mediadevices/enumeratedevices/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/files/en-us/web/api/mediadevices/enumeratedevices/index.md b/files/en-us/web/api/mediadevices/enumeratedevices/index.md index 4aa1b8f312e16ac..5e508a708fac59e 100644 --- a/files/en-us/web/api/mediadevices/enumeratedevices/index.md +++ b/files/en-us/web/api/mediadevices/enumeratedevices/index.md @@ -11,8 +11,8 @@ browser-compat: api.MediaDevices.enumerateDevices The {{domxref("MediaDevices")}} method **`enumerateDevices()`** requests a list of the available media input and output devices, such as microphones, cameras, headsets, and so forth. The returned {{jsxref("Promise")}} is resolved with a {{domxref("MediaDeviceInfo")}} array describing the devices. -Access to particular devices is gated by the [Permissions API](/en-US/docs/Web/API/Permissions_API). -The list of returned devices will omit any devices for which the corresponding permission has not been granted, including: [`microphone`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/microphone), [`camera`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/camera), [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) (for output devices), and so on. +The list of returned list will omit any devices that are blocked by the document [Permission Policy](/en-US/docs/Web/HTTP/Headers/Permissions-Policy): [`microphone`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/microphone), [`camera`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/camera), [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) (for output devices), and so on. +Access to particular non-default devices is also gated by the [Permissions API](/en-US/docs/Web/API/Permissions_API), and the list will omit devices for which the user has not granted explicit permission. ## Syntax @@ -26,11 +26,11 @@ None. ### Return value -A {{ jsxref("Promise") }} that receives an array of {{domxref("MediaDeviceInfo")}} objects when the promise is fulfilled. Each object in the array describes one of the available media input and output devices. +A {{ jsxref("Promise") }} that receives an array of {{domxref("MediaDeviceInfo")}} objects when the promise is fulfilled. +Each object in the array describes one of the available media input and output devices. The order is significant — the default capture devices will be listed first. -Only device types for which permission has been granted are "available". -Also note that if a [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) [Permissions Policy](/en-US/docs/Web/HTTP/Permissions_Policy) is used to block use of audio outputs, they won't be available in the list. +Other than default devices, only devices for which permission has been granted are "available". If enumeration fails, the promise is rejected. From c86984b3a153ea2323c549243742142015e93544 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 10 Jul 2023 17:52:33 +1000 Subject: [PATCH 06/16] enumerateDevices - currently available to make it clear that this list can change --- files/en-us/web/api/mediadevices/enumeratedevices/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/en-us/web/api/mediadevices/enumeratedevices/index.md b/files/en-us/web/api/mediadevices/enumeratedevices/index.md index 5e508a708fac59e..bf78982dd8b68f9 100644 --- a/files/en-us/web/api/mediadevices/enumeratedevices/index.md +++ b/files/en-us/web/api/mediadevices/enumeratedevices/index.md @@ -8,10 +8,10 @@ browser-compat: api.MediaDevices.enumerateDevices {{APIRef("WebRTC")}} -The {{domxref("MediaDevices")}} method **`enumerateDevices()`** requests a list of the available media input and output devices, such as microphones, cameras, headsets, and so forth. +The {{domxref("MediaDevices")}} method **`enumerateDevices()`** requests a list of the currently available media input and output devices, such as microphones, cameras, headsets, and so forth. The returned {{jsxref("Promise")}} is resolved with a {{domxref("MediaDeviceInfo")}} array describing the devices. -The list of returned list will omit any devices that are blocked by the document [Permission Policy](/en-US/docs/Web/HTTP/Headers/Permissions-Policy): [`microphone`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/microphone), [`camera`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/camera), [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) (for output devices), and so on. +The returned list will omit any devices that are blocked by the document [Permission Policy](/en-US/docs/Web/HTTP/Headers/Permissions-Policy): [`microphone`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/microphone), [`camera`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/camera), [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) (for output devices), and so on. Access to particular non-default devices is also gated by the [Permissions API](/en-US/docs/Web/API/Permissions_API), and the list will omit devices for which the user has not granted explicit permission. ## Syntax From 291194ccef9e4d3e6e1550da54047efdfb9ac8fc Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 10 Jul 2023 18:58:32 +1000 Subject: [PATCH 07/16] Improve the overview --- .../web/api/audio_output_devices_api/index.md | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index 319cacc0f273d20..050a70dc1a357f0 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -8,19 +8,22 @@ browser-compat: - api.MediaDevices.selectAudioOutput - api.HTMLMediaElement.setSinkId - api.HTMLMediaElement.sinkId + - http.headers.Permissions-Policy.speaker-selection --- {{DefaultAPISidebar("Audio Output Devices API")}}{{securecontext_header}}{{SeeCompatTable}} -The **Audio Output Devices API** allows web applications to prompt users about what audio output device should be used for playback. +The **Audio Output Devices API** allows web applications to prompt users about what output device should be used for audio playback. ## Concepts and usage Operating systems commonly allow users to specify that audio should be played from speakers, a Bluetooth headset, or some other audio output device. -This API allows applications to provide this same functionality from within a web page, which may provide a better user experience. +This API allows applications to provide this same functionality from within a web page. -Setting a particular audio output device requires explicit user permission, as the user may be in a location where playing audio is not appropriate through some output devices. -For more information see [Security requirements](#security-requirements) below. +Even if allowed by a permission policy, access to a particular audio output device still requires explicit user permission, as the user may be in a location where playing audio is not appropriate through some output devices. + +The API provides the [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput) method that allows users to select their desired audio output from those that are allowed by the [`Permissions-Policy: speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) for the document. +The selected device then has user permission, allowing it to be enumerated with [`MediaDevices.enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices) and set as the audio output device using [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId). Audio devices may arbitrarily connect and disconnect. Applications that wish to react to this kind of change can listen to the [`devicechange` event](/en-US/docs/Web/API/MediaDevices/devicechange_event) and use [`enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices) to determine if `sinkId` is present in the returned devices. @@ -32,8 +35,14 @@ This might trigger, for example, pausing or unpausing playback. The Audio Output Devices API extends the following APIs, adding the listed features: +#### MediaDevices + - [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput) - : This method prompts the user to select a specific audio output device, for example a speaker or headset. + Selecting a device grants user permission to use that device and returns information about the device, including its ID. + +#### HTMLMediaElement + - [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId) - : This method sets the ID of the audio device to use for output, which will be used if permitted. - [`HTMLMediaElement.sinkId`](/en-US/docs/Web/API/HTMLMediaElement/sinkId) @@ -41,21 +50,58 @@ The Audio Output Devices API extends the following APIs, adding the listed featu ## Security requirements -Access to [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput) is subject to the following constraints: +Access to the API is subject to the following constraints: -- It may only be used in a [secure context](/en-US/docs/Web/Security/Secure_Contexts). -- Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/midi) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). -- [Transient user activation](/en-US/docs/Web/Security/User_activation) is required. - The user has to interact with the page or a UI element for this feature to work. -- The user must explicitly grant permission to use the audio output device through a user-agent specific mechanism, or have previously granted permission. - Note that if access is denied by a permission policy it cannot be granted by a user permission. +- All methods and properties may only be called in a [secure context](/en-US/docs/Web/Security/Secure_Contexts). -User permission to set the output device is also implicitly granted if the user has already granted permission to use a media input device in the same group, using [`MediaDevices.getUserMedia()`](/en-US/docs/Web/API/MediaDevices/getUserMedia). +- [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput) grants user permission for a selected device to be used as the audio output sink: -Other methods/properties also require a secure context and the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/midi) permission policy. + - Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). + - [Transient user activation](/en-US/docs/Web/Security/User_activation) is required. + The user has to interact with the page or a UI element for the method to be called. + +- [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId) sets a permitted ID as the audio output: + + - Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). + - User permission is required to set a non-default device ID. + - This can come from selection in the prompt launched by `MediaDevices.selectAudioOutput()` + - User permission to set the output device is also implicitly granted if the user has already granted permission to use a media input device in the same group with [`MediaDevices.getUserMedia()`](/en-US/docs/Web/API/MediaDevices/getUserMedia). The permission status can be queried using the [Permissions API](/en-US/docs/Web/API/Permissions_API) method [`navigator.permissions.query()`](/en-US/docs/Web/API/Permissions/query), passing a permission descriptor with the `speaker-selection` permission. +## Examples + +Here's an example of using `selectAudioOutput()`, within a function that is triggered by a button click, and then setting the selected device as the audio output. + +The code first checks if `selectAudioOutput()` is supported, and if it is, uses it to select an output and return a [device ID](/en-US/docs/Web/API/MediaDeviceInfo/deviceId). +We then play some some audio using the default output, and then call `setSinkId()` in order to switch to the selected output device. + +```js +document.querySelector("#myButton").addEventListener("click", () => { + if (!navigator.mediaDevices.selectAudioOutput) { + console.log("selectAudioOutput() not supported or not in secure context."); + return; + } + +// Display prompt to select device +const audioDevice = await navigator.mediaDevices.selectAudioOutput(); + +// Create an audio element and start playing audio on the default device +const audio = document.createElement("audio"); +audio.src = "https://example.com/audio.mp3"; +audio.play(); + +// Change the sink to the selected audio output device. +audio.setSinkId(audioDevice.deviceId); +}); +``` + +Note that the output details might look something like this: + +```bash +audiooutput: Realtek Digital Output (Realtek(R) Audio) id = 0wE6fURSZ20H0N2NbxqgowQJLWbwo+5ablCVVJwRM3k= +``` + ## Specifications {{Specifications}} From 08ce0df505d68474666efd13e9b5f0e347ca61c4 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Tue, 11 Jul 2023 10:16:24 +1000 Subject: [PATCH 08/16] Apply suggestions from code review --- files/en-us/web/api/audio_output_devices_api/index.md | 2 +- files/en-us/web/api/htmlmediaelement/setsinkid/index.md | 2 +- files/en-us/web/api/htmlmediaelement/sinkid/index.md | 2 +- files/en-us/web/api/mediadevices/selectaudiooutput/index.md | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index 050a70dc1a357f0..3bc6e191d70e13e 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -77,7 +77,7 @@ The code first checks if `selectAudioOutput()` is supported, and if it is, uses We then play some some audio using the default output, and then call `setSinkId()` in order to switch to the selected output device. ```js -document.querySelector("#myButton").addEventListener("click", () => { +document.querySelector("#myButton").addEventListener("click", async () => { if (!navigator.mediaDevices.selectAudioOutput) { console.log("selectAudioOutput() not supported or not in secure context."); return; diff --git a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md index a554b9b0346df59..1da8488fc16ebef 100644 --- a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md @@ -8,7 +8,7 @@ browser-compat: api.HTMLMediaElement.setSinkId {{APIRef("HTML DOM")}} -The **`HTMLMediaElement.setSinkId()`** method of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) sets the ID of the audio device to use for output and returns a [`Promise`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). +The **`HTMLMediaElement.setSinkId()`** method of the [Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) sets the ID of the audio device to use for output and returns a [`Promise`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). This only works when the application is permitted to use the specified device. For more information see the [security requirements](#security_requirements) below. diff --git a/files/en-us/web/api/htmlmediaelement/sinkid/index.md b/files/en-us/web/api/htmlmediaelement/sinkid/index.md index 836961a9674b10b..85984e7c992a2b0 100644 --- a/files/en-us/web/api/htmlmediaelement/sinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/sinkid/index.md @@ -8,7 +8,7 @@ browser-compat: api.HTMLMediaElement.sinkId {{APIRef("HTML DOM")}} -The **`HTMLMediaElement.sinkId`** read-only property of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) returns a string that is the unique ID of the device to be used for playing audio output. +The **`HTMLMediaElement.sinkId`** read-only property of the [Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) returns a string that is the unique ID of the device to be used for playing audio output. If the user agent default device is being used, it returns an empty string. This ID should be one of the {{domxref("MediaDeviceInfo.deviceId")}} values returned from {{domxref("MediaDevices.enumerateDevices()")}}, `id-multimedia`, or `id-communications`. diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index 57dd09f62da0196..229d5b18d278fad 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -34,13 +34,14 @@ selectAudioOutput(options) - `deviceId` {{Optional_Inline}} - - : A string representing the id of a single device to display in the prompt. - If not set, all audio output devices for which permission is not explicitly denied will be displayed. + - : A string representing the id of a single previously exposed/permitted device. + If not set, a prompt with all available audio output devices will be displayed. The option is intended for applications that want to use persisted device ids. > **Note:** A user agent may choose to skip prompting the user if a specified non-null id was previously exposed to the user by `selectAudioOutput()` in an earlier session. > In this case the user agent may simply resolve with this device id, or a new id for the same device if it has changed. + > If permission for the specified device was previously granted but has since been revoked, the user-agent might display all allowed devices, highlighting the one with the specified ID. > > Note that persisted ids _must be passed_ through `selectAudioOutput()` successfully before they will work with {{domxref("HTMLMediaElement.setSinkId","setSinkId()")}}. From 1de7de87b95d70fe52929c610ad55e0cddcc0286 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Tue, 11 Jul 2023 10:19:43 +1000 Subject: [PATCH 09/16] Update index.md --- files/en-us/web/api/audio_output_devices_api/index.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index 3bc6e191d70e13e..60a6c09af541049 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -96,10 +96,11 @@ audio.setSinkId(audioDevice.deviceId); }); ``` -Note that the output details might look something like this: +Note that if you log the output details, they might look something like this: -```bash -audiooutput: Realtek Digital Output (Realtek(R) Audio) id = 0wE6fURSZ20H0N2NbxqgowQJLWbwo+5ablCVVJwRM3k= +```js +console.log(`${audioDevice.kind}: ${audioDevice.label} id = ${audioDevice.deviceId}`); +// audiooutput: Realtek Digital Output (Realtek(R) Audio) id = 0wE6fURSZ20H0N2NbxqgowQJLWbwo+5ablCVVJwRM3k= ``` ## Specifications From 81e5a03584c8e4afd4d07413c803665a42d8a2c1 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Tue, 11 Jul 2023 10:26:56 +1000 Subject: [PATCH 10/16] Run prettier --- .../web/api/audio_output_devices_api/index.md | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index 60a6c09af541049..569d24608bd12c7 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -74,7 +74,7 @@ The permission status can be queried using the [Permissions API](/en-US/docs/Web Here's an example of using `selectAudioOutput()`, within a function that is triggered by a button click, and then setting the selected device as the audio output. The code first checks if `selectAudioOutput()` is supported, and if it is, uses it to select an output and return a [device ID](/en-US/docs/Web/API/MediaDeviceInfo/deviceId). -We then play some some audio using the default output, and then call `setSinkId()` in order to switch to the selected output device. +We then play some some audio using the default output, and then call `setSinkId()` in order to switch to the selected output device. ```js document.querySelector("#myButton").addEventListener("click", async () => { @@ -83,23 +83,25 @@ document.querySelector("#myButton").addEventListener("click", async () => { return; } -// Display prompt to select device -const audioDevice = await navigator.mediaDevices.selectAudioOutput(); + // Display prompt to select device + const audioDevice = await navigator.mediaDevices.selectAudioOutput(); -// Create an audio element and start playing audio on the default device -const audio = document.createElement("audio"); -audio.src = "https://example.com/audio.mp3"; -audio.play(); + // Create an audio element and start playing audio on the default device + const audio = document.createElement("audio"); + audio.src = "https://example.com/audio.mp3"; + audio.play(); -// Change the sink to the selected audio output device. -audio.setSinkId(audioDevice.deviceId); + // Change the sink to the selected audio output device. + audio.setSinkId(audioDevice.deviceId); }); ``` Note that if you log the output details, they might look something like this: ```js -console.log(`${audioDevice.kind}: ${audioDevice.label} id = ${audioDevice.deviceId}`); +console.log( + `${audioDevice.kind}: ${audioDevice.label} id = ${audioDevice.deviceId}` +); // audiooutput: Realtek Digital Output (Realtek(R) Audio) id = 0wE6fURSZ20H0N2NbxqgowQJLWbwo+5ablCVVJwRM3k= ``` From f9eae219870f12cf41a3c27b5638c2430031239a Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 17 Jul 2023 13:58:09 +1000 Subject: [PATCH 11/16] Apply suggestions from code review Co-authored-by: wbamberg --- files/en-us/web/api/audio_output_devices_api/index.md | 4 ++-- files/en-us/web/api/htmlmediaelement/setsinkid/index.md | 2 +- files/en-us/web/api/mediadevices/enumeratedevices/index.md | 4 ++-- files/en-us/web/api/mediadevices/selectaudiooutput/index.md | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index 569d24608bd12c7..3c330f0758d71ab 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -20,9 +20,9 @@ The **Audio Output Devices API** allows web applications to prompt users about w Operating systems commonly allow users to specify that audio should be played from speakers, a Bluetooth headset, or some other audio output device. This API allows applications to provide this same functionality from within a web page. -Even if allowed by a permission policy, access to a particular audio output device still requires explicit user permission, as the user may be in a location where playing audio is not appropriate through some output devices. +Even if allowed by a permission policy, access to a particular audio output device still requires explicit user permission, as the user may be in a location where playing audio through some output devices is not appropriate. -The API provides the [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput) method that allows users to select their desired audio output from those that are allowed by the [`Permissions-Policy: speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) for the document. +The API provides the [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput) method that allows users to select their desired audio output from those that are allowed by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) directive of the [`Permissions-Policy`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy) HTTP header for the document. The selected device then has user permission, allowing it to be enumerated with [`MediaDevices.enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices) and set as the audio output device using [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId). Audio devices may arbitrarily connect and disconnect. diff --git a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md index 1da8488fc16ebef..f3e15bf0d3a0482 100644 --- a/files/en-us/web/api/htmlmediaelement/setsinkid/index.md +++ b/files/en-us/web/api/htmlmediaelement/setsinkid/index.md @@ -44,7 +44,7 @@ Access to the API is subject to the following constraints: - The method must be called in a [secure context](/en-US/docs/Web/Security/Secure_Contexts). - Access may be gated by the [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) HTTP [Permission Policy](/en-US/docs/Web/HTTP/Permissions_Policy). - User permission is required to access a non-default device. - This is granted by selecting the device associated with the ID in the prompt displayed by [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput). + The user grants permission by selecting the device associated with the ID in the prompt displayed by [`MediaDevices.selectAudioOutput()`](/en-US/docs/Web/API/MediaDevices/selectAudioOutput). ## Examples diff --git a/files/en-us/web/api/mediadevices/enumeratedevices/index.md b/files/en-us/web/api/mediadevices/enumeratedevices/index.md index bf78982dd8b68f9..fa9afb9be082669 100644 --- a/files/en-us/web/api/mediadevices/enumeratedevices/index.md +++ b/files/en-us/web/api/mediadevices/enumeratedevices/index.md @@ -9,7 +9,7 @@ browser-compat: api.MediaDevices.enumerateDevices {{APIRef("WebRTC")}} The {{domxref("MediaDevices")}} method **`enumerateDevices()`** requests a list of the currently available media input and output devices, such as microphones, cameras, headsets, and so forth. -The returned {{jsxref("Promise")}} is resolved with a {{domxref("MediaDeviceInfo")}} array describing the devices. +The returned {{jsxref("Promise")}} is resolved with an array of {{domxref("MediaDeviceInfo")}} objects describing the devices. The returned list will omit any devices that are blocked by the document [Permission Policy](/en-US/docs/Web/HTTP/Headers/Permissions-Policy): [`microphone`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/microphone), [`camera`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/camera), [`speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection) (for output devices), and so on. Access to particular non-default devices is also gated by the [Permissions API](/en-US/docs/Web/API/Permissions_API), and the list will omit devices for which the user has not granted explicit permission. @@ -26,7 +26,7 @@ None. ### Return value -A {{ jsxref("Promise") }} that receives an array of {{domxref("MediaDeviceInfo")}} objects when the promise is fulfilled. +A {{ jsxref("Promise") }} that is fulfilled with an array of {{domxref("MediaDeviceInfo")}} objects. Each object in the array describes one of the available media input and output devices. The order is significant — the default capture devices will be listed first. diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index 229d5b18d278fad..147181b655d2bc1 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -10,7 +10,7 @@ browser-compat: api.MediaDevices.selectAudioOutput {{APIRef("WebRTC")}} {{SeeCompatTable}} -The {{domxref("MediaDevices.selectAudioOutput()")}} method of the [Web Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) prompts the user to select an audio output device, such as a speaker or headset, and grants user-permission to use the selected device as an audio output sink. +The {{domxref("MediaDevices.selectAudioOutput()")}} method of the [Audio Output Devices API](/en-US/docs/Web/API/Audio_Output_Devices_API) prompts the user to select an audio output device, such as a speaker or headset. If the user selects a device, the method grants user permission to use the selected device as an audio output sink. Following selection, if the device is available it can be enumerated using [`MediaDevices.enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices) and set as the audio output sink using [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId). @@ -34,7 +34,7 @@ selectAudioOutput(options) - `deviceId` {{Optional_Inline}} - - : A string representing the id of a single previously exposed/permitted device. + - : A string representing the ID of a single previously exposed/permitted device. If not set, a prompt with all available audio output devices will be displayed. The option is intended for applications that want to use persisted device ids. From bc4044b07d674eb4845afdc0d8b077e025573bec Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 17 Jul 2023 14:00:33 +1000 Subject: [PATCH 12/16] Fulfills not receives for promise --- files/en-us/web/api/mediadevices/selectaudiooutput/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index 147181b655d2bc1..8ab415b517e9fcc 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -47,8 +47,7 @@ selectAudioOutput(options) ### Return value -A {{ jsxref("Promise") }} that receives a {{domxref("MediaDeviceInfo")}} object when the promise is fulfilled. -The object describes the user-selected audio output device. +A {{ jsxref("Promise") }} that is fulfilled with a {{domxref("MediaDeviceInfo")}} object that describes the audio output device selected by the user. ### Exceptions From 350eb9d8d764dd9a04bcba25431865e29f3afd6e Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 17 Jul 2023 14:10:35 +1000 Subject: [PATCH 13/16] Spec urls fixup --- files/en-us/web/api/audio_output_devices_api/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index 3c330f0758d71ab..e58506937c70bbe 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -9,6 +9,7 @@ browser-compat: - api.HTMLMediaElement.setSinkId - api.HTMLMediaElement.sinkId - http.headers.Permissions-Policy.speaker-selection +spec-urls: https://w3c.github.io/mediacapture-output/#dom-mediadevices-selectaudiooutput --- {{DefaultAPISidebar("Audio Output Devices API")}}{{securecontext_header}}{{SeeCompatTable}} From 648380a73b54b8e2cb5419c5d06b4630fb99ca6b Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 17 Jul 2023 14:21:54 +1000 Subject: [PATCH 14/16] Remove early note of security considerations --- files/en-us/web/api/mediadevices/selectaudiooutput/index.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index 8ab415b517e9fcc..7aa02f1f03ff934 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -14,9 +14,6 @@ The {{domxref("MediaDevices.selectAudioOutput()")}} method of the [Audio Output Following selection, if the device is available it can be enumerated using [`MediaDevices.enumerateDevices()`](/en-US/docs/Web/API/MediaDevices/enumerateDevices) and set as the audio output sink using [`HTMLMediaElement.setSinkId()`](/en-US/docs/Web/API/HTMLMediaElement/setSinkId). -The method can only be called in a [secure context](/en-US/docs/Web/Security/Secure_Contexts) with [transient user activation](/en-US/docs/Web/Security/User_activation), and will only offer audio output devices if allowed by the page [`Permission-Policy: speaker-selection`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection). -For more information see the [security requirements](#security_requirements). - On success, the returned {{jsxref("Promise")}} is resolved with a {{domxref("MediaDeviceInfo")}} describing the selected device. ## Syntax From f0f0d71b97302b761667d6cc148d11204923eec3 Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Mon, 17 Jul 2023 14:50:25 +1000 Subject: [PATCH 15/16] Better explain persisting IDs --- files/en-us/web/api/mediadevices/selectaudiooutput/index.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md index 7aa02f1f03ff934..c4af7eeba3e2680 100644 --- a/files/en-us/web/api/mediadevices/selectaudiooutput/index.md +++ b/files/en-us/web/api/mediadevices/selectaudiooutput/index.md @@ -34,13 +34,12 @@ selectAudioOutput(options) - : A string representing the ID of a single previously exposed/permitted device. If not set, a prompt with all available audio output devices will be displayed. - The option is intended for applications that want to use persisted device ids. + The option is intended for applications that want to store a device id so that the same device can be used by default in future sessions. + Note that the method may return a new ID for the same device, and that persisted ids _must be passed_ through `selectAudioOutput()` successfully before they will work with {{domxref("HTMLMediaElement.setSinkId","setSinkId()")}}. > **Note:** A user agent may choose to skip prompting the user if a specified non-null id was previously exposed to the user by `selectAudioOutput()` in an earlier session. > In this case the user agent may simply resolve with this device id, or a new id for the same device if it has changed. > If permission for the specified device was previously granted but has since been revoked, the user-agent might display all allowed devices, highlighting the one with the specified ID. - > - > Note that persisted ids _must be passed_ through `selectAudioOutput()` successfully before they will work with {{domxref("HTMLMediaElement.setSinkId","setSinkId()")}}. ### Return value From 2dc034591cf521a3f7c01bedec17c03bcddedafa Mon Sep 17 00:00:00 2001 From: Hamish Willee Date: Fri, 21 Jul 2023 09:21:42 +1000 Subject: [PATCH 16/16] Prettier --- files/en-us/web/api/audio_output_devices_api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/en-us/web/api/audio_output_devices_api/index.md b/files/en-us/web/api/audio_output_devices_api/index.md index e58506937c70bbe..bd2a6f78b73db4e 100644 --- a/files/en-us/web/api/audio_output_devices_api/index.md +++ b/files/en-us/web/api/audio_output_devices_api/index.md @@ -101,7 +101,7 @@ Note that if you log the output details, they might look something like this: ```js console.log( - `${audioDevice.kind}: ${audioDevice.label} id = ${audioDevice.deviceId}` + `${audioDevice.kind}: ${audioDevice.label} id = ${audioDevice.deviceId}`, ); // audiooutput: Realtek Digital Output (Realtek(R) Audio) id = 0wE6fURSZ20H0N2NbxqgowQJLWbwo+5ablCVVJwRM3k= ```