forked from w3c/mediacapture-output
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
220 lines (198 loc) · 17.7 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<!DOCTYPE html>
<!--
To publish this document, see instructions in README
-->
<html lang="en-us">
<head>
<meta charset=utf-8>
<link href="style.css" rel="stylesheet">
<title>Audio Output Devices API</title>
<script class="remove"
src="https://www.w3.org/Tools/respec/respec-w3c-common"
type="text/javascript"> // <!-- keep this comment --> // </script>
<script class="remove" src="script.js" type="text/javascript"> //
<!-- keep this comment --> // </script>
</head>
<body>
<section id="abstract">
<p>This document defines a set of JavaScript APIs that let a Web application manage how audio is rendered on the user audio output devices.</p>
</section>
<section id="sotd">
<p>This document is not complete. It is subject to major changes and,
while early experimentations are encouraged, it is therefore not
intended for implementation.</p>
</section>
<section class="informative" id="intro">
<h2>Introduction</h2>
<p>This proposal allows JavaScript to direct the audio output of a media element to authorized devices other than the system or user agent default. This can be helpful in a variety of real-time communication scenarios as well as general media applications. For example, an application can use this API to programmatically direct output to a device such as a Bluetooth headset or speakerphone.
</p>
</section>
<section id="htmlmediaelement-extensions">
<h2><a href="#idl-def-HTMLMediaElement" class="idlType"><code>HTMLMediaElement</code></a> Extensions</h2>
<p>This section specifies additions to the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#htmlmediaelement"><code>HTMLMediaElement</code></a> [[!HTML5]] when the Audio Output Devices API is supported.</p>
<dl title='partial interface HTMLMediaElement' class='idl'>
<dt>readonly attribute DOMString sinkId</dt>
<dd>
The unique ID of the audio device through which output is being delivered, or empty string if it is using the user agent default. This ID should be one of the <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-MediaDeviceInfo-deviceId"><code>MediaDeviceInfo.deviceId</code></a> values returned from <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-MediaDevices-enumerateDevices-void-MediaDeviceInfoCallback-resultCallback"><code>MediaDevices.enumerateDevices()</code></a> [[!GETUSERMEDIA]], or one of the predefined IDs listed below.
</dd>
<dt>Promise<void> setSinkId ()</dt>
<dd>
Sets the ID of the audio device through which audio output should be rendered if the application is <a href="#privacy-considerations">authorized</a> to play out of a given device.
<dl class='parameters'>
<dt>DOMString sinkId</dt>
<dd>
The id corresponding to the audio output device.
</dd>
</dl>
</dd>
</dl>
<p>When this method is invoked, the user agent must run the following steps:</p>
<ol class="method-algorithm">
<li><p>If <code>sinkId</code> and the <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>sinkId</code></a> attribute are the same object, return a resolved promise.</p></li>
<li><p>If the <code>sinkId</code> does not match any audio output device identified by <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#dom-mediadevices-enumeratedevices"><code>enumerateDevices()</code></a>, return a promise rejected with a new <a href="http://www.w3.org/TR/html5/infrastructure.html#domexception"><code>DOMException</code></a> whose name is <a href="http://www.w3.org/TR/html5/infrastructure.html#notfounderror"><code>NotFoundError</code></a>.</p></li>
<li><p>If application is not authorized to play audio through the device identified by the given sinkId, return a promise rejected with a new <a href="http://www.w3.org/TR/html5/infrastructure.html#domexception"><code>DOMException</code></a> whose name is <a href="http://www.w3.org/TR/html5/infrastructure.html#securityerror"><code>SecurityError</code></a>.</p></li>
<li><p>Let <var>promise</var> be a new promise.</p></li>
<li><p>Run the following steps asynchronously:</p>
<ol>
<li><p>Associate the audio output device represented by <code>sinkId</code> with this object for playout.</p></li>
<li><p>If the preceding step failed, return a rejected promise.</p></li>
<li><p>If the media element's <a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused"><code>paused</code></a> attribute is false, stop playing this object's audio out of the device represented by the <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>sinkId</code></a> attribute.</p></li>
<li><p>Set the <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>sinkId</code></a> attribute to <code>sinkId</code>.</p></li>
<li><p>If the media element's <a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused"><code>paused</code></a> attribute is false, start playing this object's audio out of the device represented by <code>sinkId</code>.</p></li>
<li><p>Resolve <var>promise</var>.</p></li>
</ol>
</li>
<li><p>Return <var>promise</var>.</p></li>
</ol>
<section id="algorithms">
<h3>Algorithms</h3>
<section id="algorithms-sink-unavailable">
<h4>Sink no longer available</h4>
<p>The audio device associated with <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>HTMLMediaElement.sinkId</code></a> may become unavailable, for example if it is unplugged.</p>
<p>When the audio device identified by the <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>sinkId</code></a> attribute is no longer available, the user agent must take no action. For example, if the media element's <a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused"><code>paused</code></a> attribute is false when the device identified by the sinkId is no longer available, then playback will continue as normal. Of course, audio will not be rendered because the device to which the media element is attached is unavailable.</p>
<p>
<em>The following paragraph is non-normative.</em>
</p>
<p class="informative">If the application wishes to react to the device change, the application can listen to the <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#event-mediadevices-devicechange"><code>devicechange</code></a> event and query <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#dom-mediadevices-enumeratedevices"><code>enumerateDevices()</code></a> for the list of updated devices. If the <a href="#widl-HTMLMediaElement-sinkId"><code>HTMLMediaElement.sinkId</code></a> is no longer present in the list of <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-MediaDeviceInfo-deviceId"><code>MediaDeviceInfo.deviceId</code></a>s returned, the device is no longer available and the application can choose to react accordingly.</p>
</section>
<section id="algorithms-new-sink-available">
<h4>New sink available</h4>
<p>New audio devices may become available to the user agent, or an audio device (identified by <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>HTMLMediaElement.sinkId</code></a>) that had previously become <a href="#algorithms-sink-unavailable">unavailable</a> may become available again, for example, if it is unplugged and later plugged back in.</a></p>
<p>In this scenario, the user agent must run the following steps:</p>
<ol class="method-algorithm">
<li><p>Let <var>sinkId</var> be the identifier for the newly available device.</p></li>
<li><p>For each <a href="#widl-HTMLMediaElement-sinkId" class="idlType"><code>sinkId</code></a> whose value is equal to <var>sinkId</var>:</p>
<ol>
<li><p>If the media element's <a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused"><code>paused</code></a> attribute is false, start rendering this object's audio out of the device represented by the <a href="#widl-HTMLMediaElement-sinkId"><code>sinkId</code></a> attribute.</p></li>
</ol>
</li>
</ol>
<p>
<em>The following paragraph is non-normative.</em>
</p>
<p class="informative">If the application wishes to react to the device change, the application can listen to the <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#event-mediadevices-devicechange"><code>devicechange</code></a> event and query <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#dom-mediadevices-enumeratedevices"><code>enumerateDevices()</code></a> for the list of updated devices.</p>
</section>
</section>
</section>
<section id="webaudio-extensions">
<h2><a href="http://webaudio.github.io/web-audio-api/">Web Audio API</a> Extensions</h2>
<p>This is a work in progress. The following section discusses the options for additions to and modifications of the <a href="http://webaudio.github.io/web-audio-api/">Web Audio API</a> [[!WEBAUDIO]] when the Audio Output Devices API is supported.</p>
<section>
<h3>Implementation Options</h3>
<p>There are many ways that this functionality could be extended to Web Audio. This section lists several different options and is open for discussion.</p>
<p>See also <a href="https://github.com/WebAudio/web-audio-api/issues/445"/>this issue</a> in the Web Audio issue tracker regarding the handling of output devices by Web Audio.</a>
<section>
<h4>Constructor argument</h4>
<p>Option 1: <code>AudioContext</code> constructor argument</p>
<ul>
<li>The sink ID is passed as an argument to the <a href="http://webaudio.github.io/web-audio-api/#the-audiocontext-interface"><code>AudioContext</code></a> constructor, e.g. <br><br><code>new AudioContext({ sinkId: requestedSinkId });</code><br><br> By requiring the sink ID to be set at construction time, this simplifies the implementation, since the output sample rate is fixed.</li>
<li>Limitation: this implies the graph must be recreated if the output device changes.</li>
<li>Limitation: can’t play audio out of multiple devices at once (assuming application is written with a standard single <a href="http://webaudio.github.io/web-audio-api/#the-audiocontext-interface"><code>AudioContext</code></a>).
</li>
</ul>
</section>
<section>
<h4 id="webaudio-option1"><code>setSinkId()</code></h4>
<p>Option 2a: <code>AudioContext.setSinkId()</code></p>
<ul>
<li>Same as <a href="#widl-HTMLMediaElement-setSinkId-Promise-void--DOMString-sinkId"><code>HTMLMediaElement.setSinkId()</code></a>, but added to <a href="http://webaudio.github.io/web-audio-api/#the-audiocontext-interface"><code>AudioContext</code></a> as well.</li>
<li>Limitation: can’t play audio out of multiple devices at once (assuming application is written with a standard single <a href="http://webaudio.github.io/web-audio-api/#the-audiocontext-interface"><code>AudioContext</code></a>).</li>
</ul>
<p>Option 2b: <code>AudioDestinationNode.setSinkId()</code></p>
<ul>
<li>Same as 2a, but on <a href="http://webaudio.github.io/web-audio-api/#the-audiodestinationnode-interface"><code>AudioDestinationNode</code></a> instead.</li>
</ul>
</section>
<section>
<h4>addSinkId()/removeSinkId()</h4>
<p>Option 3a: <code>AudioContext.addSinkId()</code>/<code>removeSinkId()</code></p>
<ul>
<li>Benefit over <a href="#webaudio-option1">setSinkId</a>: Audio can be piped through multiple devices.</li>
</ul>
<p>Option 3b: <code>AudioDestinationNode.addSinkId()</code>/<code>removeSinkId()</code></p>
<ul>
<li>Same as 3a but on <a href="http://webaudio.github.io/web-audio-api/#the-audiodestinationnode-interface"><code>AudioDestinationNode</code></a> instead.</li>
</ul>
</section>
<section>
<h4>No change to spec</h4>
<ul>
<li>Use <a href="http://webaudio.github.io/web-audio-api/#widl-AudioContext-createMediaStreamDestination-MediaStreamAudioDestinationNode"><code>createMediaStreamDestination()</code></a> and attach to <a href="http://www.w3.org/TR/html5/embedded-content-0.html#htmlmediaelement"><code>HTMLMediaElements</code></a> via <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-HTMLMediaElement-srcObject"></code>srcObject</code></a>, and use <a href="#widl-HTMLMediaElement-setSinkId-Promise-void--DOMString-sinkId"><code>HTMLMediaElement.setSinkId()</code></a> exclusively.</li>
</ul>
</section>
</section>
</section>
<section id="predefined-ids">
<h2>Predefined Device IDs</h2>
<p>User agents must also support the following predefined pseudo-identifiers
which reference an abstract device. For example, if the application wants to
route audio to a headset, but doesn't care exactly which headset, it can
use the predefined id for the system communications device.
<section>
<h3>MediaDeviceId Enum</h3>
<dl class="idl" title="enum MediaDeviceId">
<dt>id-multimedia</dt>
<dd>Indicates the system multimedia playout device.
This is the default, i.e., equivalent to not setting the sink id,
or setting it to "".
</dd>
<dt>id-communications</dt>
<dd>Indicates the system audio communications device, if one exists,
typically a headset of some sort. [NOTE: what should happen if the
system does not support this concept, but does know about headsets?]
</dd>
</dl>
</section>
</section>
<section id="privacy-considerations">
<h2>Privacy Considerations</h2>
<section id="privacy-consent">
<h3>Consent</h3>
<p>This document extends the Web platform with the ability to direct audio output to non-default devices, when authorization is given. Authorization is necessary because playing audio out of a non-default device may be unexpected behavior to the user, and may cause a nuisance. For example, suppose a user is in a library or other quiet public place where she is using a laptop with system audio directed to a USB headset. Her expectation is that the laptop’s audio is private and she will not disturb others. If any Web application can direct audio output through arbitrary output devices, a mischievous website may play loud audio out of the laptop’s external speakers without the user’s consent.</p>
<p>To prevent these kinds of nuisance scenarios, the user agent must acquire the user’s consent to access non-default audio output devices. This would prevent the library example outlined earlier, because the application would not be authorized to play out audio from the system speakers.</p>
<p>The default audio output device is always authorized.</p>
</section>
<section id="privacy-obtaining-consent">
<h3>Obtaining Consent</h3>
<p>The user agent may explicitly obtain user consent to play audio out of
non-default output devices; the details of this process are left to the implementation.
For example, one approach could be to add an explicit user prompt of the form
"example.com wants to access all your sound output devices".</p>
<p>However, implementations must support implicit consent via the <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-MediaDevices-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback"><code>getUserMedia()</code></a> permission prompt; when an audio input device is authorized and opened via <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-MediaDevices-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback"><code>getUserMedia()</code></a>, this also authorizes access to any associated audio output devices (i.e., those with the same <a href="http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html#widl-MediaDeviceInfo-groupId"><code>MediaDeviceInfo.groupId</code></a>). This conviently handles the common case of wanting to route both input and output audio through a headset or speakerphone device.</p>
</section>
</section>
<section id="conformance">
<p>This specification defines conformance criteria that apply to a
single product: the <dfn>user agent</dfn> that implements the interfaces
that it contains.</p>
<p>Conformance requirements phrased as algorithms or specific steps may
be implemented in any manner, so long as the end result is equivalent.
(In particular, the algorithms defined in this specification are
intended to be easy to follow, and not intended to be performant.)</p>
<p>Implementations that use ECMAScript to implement the APIs defined in
this specification must implement them in a manner consistent with the
ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]], as
this specification uses that specification and terminology.</p>
</section>
</body>
</html>