-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.bs
430 lines (347 loc) · 26.9 KB
/
index.bs
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
<pre class='metadata'>
Title: Audio Session
Shortname: audio-session
Level: None
Status: w3c/ED
Group: mediawg
Repository: w3c/audio-session
URL: https://w3c.github.io/audio-session/
TR: https://www.w3.org/TR/audio-session/
Editor: Youenn Fablet, Apple https://www.apple.com/, [email protected], w3cid 96458
Editor: Alastor Wu, Mozilla https://www.mozilla.org, [email protected], w3cid 92198
Abstract: This API defines an API surface for controlling how audio is rendered and interacts with other audio playing applications.
Markup Shorthands: css no, markdown yes
</pre>
<pre class=link-defaults>
spec:html; type:dfn; for:/; text:browsing context
</pre>
# Introduction # {#introduction}
People increasingly consume media (audio/video) through the Web,
which has become a primary channel for accessing this type of content.
However, media on the Web often lacks seamless integration with underlying platforms.
The Audio Session API addresses this gap by enhancing media handling
across platforms that support audio session management or similar audio focus features.
This API improves how web-based audio interacts with other apps,
allowing for better audio mixing or exclusive playback, depending on the context,
to provide a more consistent and integrated media experience across devices.
Additionally, some platforms automatically manage a site's audio session
based on media playback and the APIs used to play audio.
However, this behavior might not always align with user expectations.
This API allows developers to override the default behavior and gain more control over an audio session.
# Concepts # {#concepts}
A web page can do audio processing in various ways, combining different APIs like {{HTMLMediaElement}} or {{AudioContext}}.
This audio processing has a start and a stop, which aggregates all the different audio APIs being used.
An <dfn>audio session</dfn> represents this aggregated audio processing. It allows web pages to express the general nature
of the audio processing done by the web page.
An [=audio session=] can be of a particular [=audio session/type=], and be in a particular [=audio session/state=].
An [=audio session=] manages the audio for a set of individual sources (microphone recording) and sinks (audio rendering), named audio session <dfn data-lt="element" for="audio session">elements</dfn>.
An [=audio session=]'s [=audio session/element=] has a number of properties:
* A <dfn data-lt="default type" for="audio session">default type</dfn>, which is used to compute the [=audio session=] [=audio session/type=], in case of "{{AudioSessionType/auto}}".
* An <dfn>audible flag</dfn>, which is either `true` if the element is playing/recording audio, or `false` otherwise.
An audio session [=audio session/element=] is an <dfn>audible element</dfn> if its [=audible flag=] is `true`.
Additionaly, an audio session [=audio session/element=] has associated steps for dealing with various state changes. By default, each of these steps is empty list of steps:
* <dfn data-lt="element update steps" for="audio session">Element update steps</dfn>, which are run whenever the audio session state changes.
* <dfn data-lt="element suspend steps" for="audio session">Element suspend steps</dfn>, which are run when the audio session state moves from {{AudioSessionState/active}} to either {{AudioSessionState/interrupted}} or {{AudioSessionState/inactive}}.
* <dfn data-lt="element resume steps" for="audio session">Element resume steps</dfn>, which are run when audio session state moves from {{AudioSessionState/interrupted}} to {{AudioSessionState/active}}.
This specification is defining these steps, the [=default type=] and the [=audible flag=] for some [=audio session=]'s [=audio session/element|elements=] in section [[#integration]].
Specifications defining other [=audio session/element|elements=] need to define these steps and properties.
A [=top-level browsing context=] has a <dfn>selected audio session</dfn>. In case of a change to any [=audio session=], the user agent will update which [=audio session=] becomes the [=selected audio session=].
A [=top-level browsing context=] is said to have <dfn lt="audio focus" for="top-level browsing context">audio focus</dfn> if its [=selected audio session=] is not `null` and its state is {{AudioSessionState/active}}.
<div class=note>
User agents can decide whether to allow several [=top-level browsing context=] to have [=audio focus=], or to enforce that only a single [=top-level browsing context=] has [=audio focus=] at any given time.</div>
# The {{AudioSession}} interface # {#audiosession-interface}
{{AudioSession}} is the main interface for this API.
It is accessed through the {{Navigator}} interface (see [[#extensions-to-navigator]]).
<pre class="idl">
[Exposed=Window]
interface AudioSession : EventTarget {
attribute AudioSessionType type;
readonly attribute AudioSessionState state;
attribute EventHandler onstatechange;
};
</pre>
To create an {{AudioSession}} object in |realm|, run the following steps:
1. Let |audioSession| be a new {{AudioSession}} object in |realm|, initialized with the following internal slots:
1. <dfn for="AudioSession">\[[type]]</dfn> to store the audio session [=audio session/type=], initialized to {{AudioSessionType/auto}}.
1. <dfn for="AudioSession">\[[state]]</dfn> to store the audio session [=audio session/state=], initialized to {{AudioSessionState/inactive}}.
1. <dfn for="AudioSession">\[[elements]]</dfn> to store the audio session [=audio session/elements=], initialized to an empty list.
1. <dfn for="AudioSession">\[[interruptedElements]]</dfn> to store the audio session [=audio session/elements=] that where interrupted while being [=audible element|audible=], initialized to an empty list.
1. <dfn for="AudioSession">\[[appliedType]]</dfn> to store the [=audio session/type=] applied to the audio session, initialized to {{AudioSessionType/auto}}.
1. <dfn for="AudioSession">\[[isTypeBeingApplied]]</dfn> flag to store whether the [=audio session/type=] is being applied to the audio session, initialized to `false`.
1. Return |audioSession|.
Each {{AudioSession}} object is uniquely <dfn for="AudioSession">tied to</dfn> its underlying [=audio session=].
The {{AudioSession}} state attribute reflects its [=audio session=] [=audio session/state=].
On getting, it MUST return the {{AudioSession}} [=AudioSession/[[state]]=] value.
The {{AudioSession}} type attribute reflects its [=audio session=] [=audio session/type=], except for {{AudioSessionType/auto}}.
On getting, it MUST return the {{AudioSession}} [=AudioSession/[[type]]=] value.
On setting, it MUST run the following steps with |newValue| being the new value being set on |audioSession|:
1. If |audioSession|.[=AudioSession/[[type]]=] is equal to |newValue|, abort these steps.
1. Set |audioSession|.[=AudioSession/[[type]]=] to |newValue|.
1. [=Update the type=] of |audioSession|.
## Audio session types ## {#audio-session-types}
By convention, there are several different [=audio session=] <dfn data-lt="type" for="audio session">types</dfn> for different purposes.
In the API, these are represented by the {{AudioSessionType}} enum:
<dl>
<dt><dfn for="AudioSessionType" enum-value>playback</dfn></dt>
<dd>Playback audio, which is used for video or music playback, podcasts, etc. They should not mix with other playback audio. (Maybe) they should pause all other audio indefinitely.</dd>
<dt><dfn for="AudioSessionType" enum-value>transient</dfn></dt>
<dd>Transient audio, such as a notification ping. They usually should play on top of playback audio (and maybe also "duck" persistent audio).</dd>
<dt><dfn for="AudioSessionType" enum-value>transient-solo</dfn></dt>
<dd>Transient solo audio, such as driving directions. They should pause/mute all other audio and play exclusively. When a transient-solo audio ended, it should resume the paused/muted audio.</dd>
<dt><dfn for="AudioSessionType" enum-value>ambient</dfn></dt>
<dd>Ambient audio, which is mixable with other types of audio. This is useful in some special cases such as when the user wants to mix audios from multiple pages.</dd>
<dt><dfn for="AudioSessionType" enum-value>play-and-record</dfn></dt>
<dd>Play and record audio, which is used for recording audio. This is useful in cases microphone is being used or in video conferencing applications.</dd>
<dt><dfn for="AudioSessionType" enum-value>auto</dfn></dt>
<dd>Auto lets the user agent choose the best audio session type according the use of audio by the web page. This is the default type of {{AudioSession}}.</dd>
</dl>
<pre class="idl">
enum AudioSessionType {
"auto",
"playback",
"transient",
"transient-solo",
"ambient",
"play-and-record"
};
</pre>
An {{AudioSessionType}} is an <dfn>exclusive type</dfn> if it is {{AudioSessionType/playback}}, {{AudioSessionType/play-and-record}} or {{AudioSessionType/transient-solo}}.
## Audio session states ## {#audio-session-states}
An [=audio session=] can be in one of the following <dfn data-lt="state" for="audio session">state</dfn> , which are represented in the API by the {{AudioSessionState}} enum:
<dl>
<dt><dfn for="AudioSessionState" enum-value>active</dfn></dt>
<dd>the [=audio session=] is playing sound or recording microphone.</dd>
<dt><dfn for="AudioSessionState" enum-value>interrupted</dfn></dt>
<dd>the [=audio session=] is not playing sound nor recording microphone, but can resume when it will get uninterrupted.</dd>
<dt><dfn for="AudioSessionState" enum-value>inactive</dfn></dt>
<dd>the [=audio session=] is not playing sound nor recording microphone.</dd>
</dl>
<pre class="idl">
enum AudioSessionState {
"inactive",
"active",
"interrupted"
};
</pre>
The [=audio session=]'s state may change, which will automatically be reflected on its {{AudioSession}} object via the steps to [=notify the state's change=].
# Extensions to the `Navigator` interface # {#extensions-to-navigator}
Each {{Window}} has an <dfn>associated AudioSession</dfn>, which is an {{AudioSession}} object.
It represents the default audio session that is used by the user agent to automatically set up the audio session parameters.
The user agent will request or abandon audio focus when audio session [=audio session/elements=] start or finish playing.
Upon creation of the {{Window}} object, its [=associated AudioSession=] MUST be set to a newly created {{AudioSession}} object with the {{Window}} object's [=relevant realm=].
The [=associated AudioSession=] list of [=audio session/elements=] is updated dynamically as audio sources and sinks of the {{Window}} object are created or removed.
<pre class="idl">
[Exposed=Window]
partial interface Navigator {
// The default audio session that the user agent will use when media elements start/stop playing.
readonly attribute AudioSession audioSession;
};
</pre>
# Audio session algorithms # {#audio-session-algorithms}
## Update AudioSession's type ## {#audio-session-update-type-algorithm}
To <dfn>update the type</dfn> of |audioSession|, the user agent MUST run the following steps:
1. If |audioSession|.[=AudioSession/[[isTypeBeingApplied]]=] is `true`, abort these steps.
1. Set |audioSession|.[=AudioSession/[[isTypeBeingApplied]]=] to `true`.
1. [=Queue a task=] to run the following steps:
1. Set |audioSession|.[=AudioSession/[[isTypeBeingApplied]]=] to `false`.
1. If |audioSession|.[=AudioSession/[[type]]=] is the same as |audioSession|.[=AudioSession/[[appliedType]]=], abort these steps.
1. Set |audioSession|.[=AudioSession/[[appliedType]]=] to |audioSession|.[=AudioSession/[[type]]=].
1. [=Update all AudioSession states=] of |audioSession|'s [=top-level browsing context=] with |audioSession|.
1. For each |element| of |audioSession|.[=AudioSession/[[elements]]=], [=update an element|update=] |element|.
1. Let |newType| be the result of [=compute the audio session type|computing the type=] of |audioSession|.
1. [=In parallel=], set the [=audio session/type=] of |audioSession|'s [=audio session=] to |newType|.
## Update AudioSession's state ## {#audio-session-update-state-algorithm}
When an audio session [=audio session/element=] is starting or stopping, the user agent will run steps that <dfn>set the state</dfn> of an [=audio session=], via the [=inactivate=] and [=try activating=] algorithms.
Setting an [=audio session=]'s [=audio session/state=] to {{AudioSessionState/active}} has consequences, especially if the [=audio session=]'s [=audio session/type=] is an [=exclusive type=]:
* It can [=inactivate=] {{AudioSession}} objects of the [=top-level browsing context=], as defined in the algorithms below.
* It can pause the audio of another tab or another application.
Conversely, an [=audio session=] [=audio session/state=] can be modified outside of audio session [=audio session/element=] changes.
When the user agent observes such a modification, the user agent MUST [=queue a task=] to [=notify the state's change=] with |audioSession|, the {{AudioSession}} object [=tied to=] the modified [=audio session=] and with |newState| being the new [=audio session=] [=audio session/state=].
<div class=example>
An active `playback` audio session can be interrupted by an incoming phone call, or by another `playback` session that is going to start playing a new media content in another tab.
</div>
To <dfn>notify the state's change</dfn> with |audioSession| and |newState|, the user agent MUST run the following steps:
1. Let |isMutatingState| be `true` if |audioSession|.[=AudioSession/[[state]]=] is not |newState| and `false` otherwise.
1. Set |audioSession|.[=AudioSession/[[state]]=] to |newState|.
1. If |newState| is {{AudioSessionState/inactive}}, set |audioSession|.[=AudioSession/[[interruptedElements]]=] to an empty list.
1. For each |element| of |audioSession|.[=AudioSession/[[elements]]=], [=update an element|update=] |element|.
1. If |isMutatingState| is `false`, abort these steps.
1. [=Update all AudioSession states=] of |audioSession|'s [=top-level browsing context=] with |audioSession|.
1. Fire an event named statechange at |audioSession|.
To <dfn>inactivate</dfn> an {{AudioSession}} named |audioSession|, the user agent MUST run the following steps:
1. If |audioSession|.[=AudioSession/[[state]]=] is {{AudioSessionState/inactive}}, abort these steps.
1. Run the following steps [=in parallel=]:
1. [=Set the state=] of |audioSession|'s [=audio session=] to {{AudioSessionState/inactive}}.
1. [=Assert=]: |audioSession|'s [=audio session=]'s [=audio session/state=] is {{AudioSessionState/inactive}}.
1. [=Queue a task=] to [=notify the state's change=] with |audioSession| and with its [=audio session=]'s [=audio session/state=].
To <dfn>try activating</dfn> an {{AudioSession}} named |audioSession|, the user agent MUST run the following steps:
1. If |audioSession|.[=AudioSession/[[state]]=] is {{AudioSessionState/active}}, abort these steps.
1. Run the following steps [=in parallel=]:
1. [=Set the state=] of |audioSession|'s [=audio session=] to {{AudioSessionState/active}}. [=Set the state|Setting the state=] to {{AudioSessionState/active}} can fail, in which case the [=audio session=]'s [=audio session/state=] will either be {{AudioSessionState/inactive}} or {{AudioSessionState/interrupted}}.
1. [=Queue a task=] to [=notify the state's change=] with |audioSession| and with its [=audio session=]'s [=audio session/state=].
<div class=example>
Activating an [=audio session=] can fail for various reasons.
For instance, a web application may try to start playing some audio while a higher privilege application, like a phone call application, is already playing audio.
</div>
## Update the selected audio session ## {#audio-session-update-selected-audio-session-algorithm}
To <dfn>update the selected audio session</dfn> of a [=top-level browsing context=] named |context|, the user agent MUST run the following steps:
1. Let |activeAudioSessions| be the list of all the [=audio session|audio sessions=] [=tied to=] {{AudioSession}} objects of |context| and its children in a breadth-first order, that match both the following constraints:
1. Its [=audio session/state=] is {{AudioSessionState/active}}.
1. The result of [=compute the audio session type|computing the type=] of the {{AudioSession}} object is an [=exclusive type=].
1. If |activeAudioSessions| is empty, abort these steps.
1. If there is only one [=audio session=] in |activeAudioSessions|, set the [=selected audio session=] to this [=audio session=] and abort these steps.
1. [=Assert=]: for any {{AudioSession}} object [=tied to=] an [=audio session=] in |activeAudioSessions|'s named |audioSession|, |audioSession|.[=AudioSession/[[type]]=] is {{AudioSessionType/auto}}.
<div class=note>
It is expected that only one [=audio session=] with an explicit [=exclusive type=] can be active at any point in time.
If there are multiple active [=audio session|audio sessions=] in |activeAudioSessions|, their [=AudioSession/[[type]]=] can only be {{AudioSessionType/auto}}.
</div>
1. The user agent MAY apply specific heuristics to reorder |activeAudioSessions|.
1. Set the [=selected audio session=] to the first [=audio session=] in |activeAudioSessions|.
## Other algorithms ## {#audio-session-other-algorithms}
To <dfn>update all AudioSession states</dfn> of a [=top-level browsing context=] named |context| with |updatedAudioSession|, run the following steps:
1. [=Update the selected audio session=] of |context|.
1. Let |updatedType| be the result of [=compute the audio session type|computing the type=] of |updatedAudioSession|.
1. If |updatedType| is not an [=exclusive type=] or |updatedAudioSession|.[=AudioSession/[[state]]=] is not {{AudioSessionState/active}}, abort these steps.
1. Let |audioSessions| be the list of all the {{AudioSession}} objects of |context| and its children in a breadth-first order.
1. For each |audioSession| of |audioSessions| except for |updatedAudioSession|, run the following steps:
1. If |audioSession|.[=AudioSession/[[state]]=] is not {{AudioSessionState/active}}, abort these steps.
1. Let |type| be the result of [=compute the audio session type|computing the type=] of |audioSession|.
1. If |type| is not an [=exclusive type=], abort these steps.
1. If |type| and |updatedType| are both {{AudioSessionType/auto}}, abort these steps.
1. [=Inactivate=] |audioSession|.
To <dfn>compute the audio session type</dfn> of |audioSession|, the user agent MUST run the following steps:
1. If |audioSession|.[=AudioSession/[[type]]=] is not {{AudioSessionType/auto}}, return |audioSession|.[=AudioSession/[[type]]=].
1. If any |element| of |audioSession|.[=AudioSession/[[elements]]=] has a [=default type=] of {{AudioSessionType/play-and-record}} and its [=element state|state=] is {{AudioSessionState/active}}, return {{AudioSessionType/play-and-record}}.
1. If any |element| of |audioSession|.[=AudioSession/[[elements]]=] has a [=default type=] of {{AudioSessionType/playback}} and its [=element state|state=] is {{AudioSessionState/active}}, return {{AudioSessionType/playback}}.
1. If any |element| of |audioSession|.[=AudioSession/[[elements]]=] has a [=default type=] of {{AudioSessionType/transient-solo}} and its [=element state|state=] is {{AudioSessionState/active}}, return {{AudioSessionType/transient-solo}}.
1. If any |element| of |audioSession|.[=AudioSession/[[elements]]=] has a [=default type=] of {{AudioSessionType/transient}} and its [=element state|state=] is {{AudioSessionState/active}}, return {{AudioSessionType/transient}}.
1. Return {{AudioSessionType/ambient}}.
# Audio source and sink integration # {#integration}
This section describes [=audio session=] [=audio session/element=]'s steps and properties for {{AudioContext}}, {{HTMLMediaElement}} and microphone {{MediaStreamTrack}}.
An <dfn>element state</dfn> is:
* {{AudioSessionState/interrupted}} if it is in its {{AudioSession}}'s [=AudioSession/[[interruptedElements]]=].
* {{AudioSessionState/active}} if it is an [=audible element=].
* {{AudioSessionState/inactive}} otherwise.
To <dfn>update an element</dfn> named |element|, the user agent MUST run the following steps:
1. Let |audioSession| be |element|'s {{AudioSession}}.
1. Run |element|'s [=element update steps|update steps=].
1. If |element| is an [=audible element=] and |audioSession|.[=AudioSession/[[state]]=] is {{AudioSessionState/interrupted}}, run the following steps:
1. Add |element| to |audioSession|.[=AudioSession/[[interruptedElements]]=].
1. Run |element|'s [=element suspend steps|suspend steps=].
1. If |element| is in |audioSession|.[=AudioSession/[[interruptedElements]]=], and |audioSession|.[=AudioSession/[[state]]=] is {{AudioSessionState/active}}, run the following steps:
1. Remove |element| from |audioSession|.[=AudioSession/[[interruptedElements]]=].
1. Run |element|'s [=element resume steps|resume steps=].
When the [=audible flag=] of one of |audioSession|'s [=audio session/elements=] is changing, the user agent MUST run the following steps:
1. If the [=audible flag=] is changing to `true`, [=try activating=] |audioSession|.
1. Otherwise, if any |element| of |audioSession|.[=AudioSession/[[elements]]=] has a [=element state|state=] of {{AudioSessionState/interrupted}}, abort these steps.
1. Otherwise, [=inactivate=] |audioSession|.
## AudioContext ## {#audiocontext-sink}
An {{AudioContext}} is an [=audio session/element=] with the following properties:
* Its [=default type=] is {{AudioSessionType/ambient}}.
* Its [=audible flag=] is `true` if its state is {{AudioContextState/running}} and is sending non zero samples to its destination.
* Its [=element suspend steps|suspend steps=] are:
1. Let |audioContext| be the {{AudioContext}} object.
1. Queue a control message to suspend |audioContext|.
* Its [=element resume steps|resume steps=] are:
1. Let |audioContext| be the {{AudioContext}} object.
1. Queue a control message to unsuspend |audioContext|.
When an {{AudioContext}} is created, the user agent MUST run the following steps:
1. Let |audioContext| be the newly created {{AudioContext}}.
1. Let |audioSession| be the {{AudioSession}}'s object of the {{Window}} object in which is created |audioContext|.
1. Add |audioContext| to |audioSession|.[=AudioSession/[[elements]]=].
## HTMLMediaElement ## {#media-element-sink}
A {{HTMLMediaElement}} is an [=audio session/element=] with the following properties:
* Its [=default type=] is {{AudioSessionType/playback}}.
* Its [=audible flag=] is `true` if it is playing, its volume is not <code>0</code>, it is not muted and it has audio tracks.
* Its [=element suspend steps|suspend steps=] are:
1. Let |mediaElement| be the {{HTMLMediaElement}} object.
1. [=Queue a task=] to run the internal pause steps of |mediaElement|.
* Its [=element resume steps|resume steps=] are:
1. Let |mediaElement| be the {{HTMLMediaElement}} object.
1. [=Queue a task=] to run the internal play steps of |mediaElement|.
When an {{HTMLMediaElement}}'s [=node document=] is changing, the user agent MUST run the following steps:
1. Let |mediaElement| be the {{HTMLMediaElement}} whose [=node document=] is changing.
1. Let |previousWindow| be the {{Window}} object associated to |mediaElement|'s previous [=node document=], if any or `null` otherwise.
1. If |previousWindow| is not `null`, remove |mediaElement| from |previousWindow|'s [=associated AudioSession=].[=AudioSession/[[elements]]=].
1. Let |newWindow| be the {{Window}} object associated to |mediaElement|'s new [=node document=], if any or `null` otherwise.
1. If |newWindow| is not `null`, add |mediaElement| to |newWindow|'s [=associated AudioSession=].[=AudioSession/[[elements]]=].
## Microphone MediaStreamtrack ## {#microphone-track-source}
A microphone capture {{MediaStreamTrack}} is an [=audio session/element=] with the following properties:
* Its [=default type=] is {{AudioSessionType/play-and-record}}.
* Its [=audible flag=] is `true` if it is neither [=MediaStreamTrack/ended=] nor [=MediaStreamTrack/muted=].
* Its [=element update steps=] are:
1. Let |track| be the {{MediaStreamTrack}} object.
1. Let |audioSession| be |track|'s {{AudioSession}}.
1. If |audioSession|.[=AudioSession/[[type]]=] is not {{AudioSessionType/play-and-record}} or {{AudioSessionType/auto}}, [$MediaStreamTrack/track ended by the user agent|end$] |track|.
* Its [=element suspend steps|suspend steps=] are:
1. Let |track| be the {{MediaStreamTrack}} object.
1. [=Queue a task=] to [$MediaStreamTrack/set a track's muted state|set the muted state$] of |track| to `true`.
* Its [=element resume steps|resume steps=] are:
1. Let |track| be the {{MediaStreamTrack}} object.
1. [=Queue a task=] to [$MediaStreamTrack/set a track's muted state|set the muted state$] of |track| to `false`.
When a microphone capture {{MediaStreamTrack}} is created, the user agent MUST run the following steps:
1. Let |track| be the newly created {{MediaStreamTrack}}.
1. Let |audioSession| be the {{AudioSession}}'s object of the {{Window}} object in which is created |track|.
1. Add |track| to |audioSession|.[=AudioSession/[[elements]]=].
FIXME: We should be hooking to the audio track's sources stored in the Window's mediaDevices's mediaStreamTrackSources, instead of MediaStreamTrack.
This should handle the case of transferred's microphone tracks.
# Privacy considerations # {#privacy}
# Security considerations # {#security}
# Examples # {#examples}
## A site sets its audio session type proactively to "play-and-record" ## {#proactive-play-and-record-example}
```javascript
navigator.audioSession.type = 'play-and-record';
// From now on, volume might be set based on 'play-and-record'.
...
// Start playing remote media
remoteVideo.srcObject = remoteMediaStream;
remoteVideo.play();
// Start capturing
navigator.mediaDevices
.getUserMedia({ audio: true, video: true })
.then((stream) => {
localVideo.srcObject = stream;
});
```
## A site reacts upon interruption ## {#interrutpion-handling-example}
```javascript
navigator.audioSession.type = "play-and-record";
// From now on, volume might be set based on 'play-and-record'.
...
// Start playing remote media
remoteVideo.srcObject = remoteMediaStream;
remoteVideo.play();
// Start capturing
navigator.mediaDevices
.getUserMedia({ audio: true, video: true })
.then((stream) => {
localVideo.srcObject = stream;
});
navigator.audioSession.onstatechange = async () => {
if (navigator.audioSession.state === "interrupted") {
localVideo.pause();
remoteVideo.pause();
// Make it clear to the user that the call is interrupted.
showInterruptedBanner();
for (const track of localVideo.srcObject.getTracks()) {
track.enabled = false;
}
} else {
// Let user decide when to restart the call.
const shouldRestart = await showOptionalRestartBanner();
if (!shouldRestart) {
return;
}
for (const track of localVideo.srcObject.getTracks()) {
track.enabled = true;
}
localVideo.play();
remoteVideo.play();
}
};
```
# Acknowledgements # {#acknowledgements}
The Working Group acknowledges the following people for their invaluable contributions to this specification:
* Becca Hughes
* Mounir Lamouri
* Zhiqiang Zhang