├── _config.yml ├── w3c.json ├── LICENSE.md ├── CODE_OF_CONDUCT.md ├── README.md ├── CONTRIBUTING.md ├── .github └── workflows │ └── auto-publish.yml ├── explainer.md └── index.bs /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": "wg/media" 3 | , "contacts": ["tidoust", "marcoscaceres", "chrisn"] 4 | , "repo-type": "rec-track" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors under the 2 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Audio Session API 2 | 3 | > [!NOTE] 4 | > Work moved to the [w3c/audio-session](https://github.com/w3c/audio-session) repository. 5 | > This repository is kept for historical purpose (it had been incorrectly created as a fork). 6 | 7 | This is the repository for the [Audio Session API](https://w3c.github.io/audio-session/), developed by the [Media Working Group](https://www.w3.org/media-wg/). 8 | 9 | See the [explainer](explainer.md). 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions to this repository are intended to become part of 4 | Recommendation-track documents governed by the 5 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy-20200915/) and 6 | [Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). 7 | To contribute, you must either participate in the relevant W3C Working Group or 8 | make a non-member patent licensing commitment. 9 | 10 | If you are not the sole contributor to a contribution (pull request), please 11 | identify all contributors in the pull request's body or in subsequent comments. 12 | 13 | To add a contributor (other than yourself, that's automatic), mark them one per 14 | line as follows: 15 | 16 | ``` 17 | +@github_username 18 | ``` 19 | 20 | If you added a contributor by mistake, you can remove them in a comment with: 21 | 22 | ``` 23 | -@github_username 24 | ``` 25 | 26 | If you are making a pull request on behalf of someone else but you had no part 27 | in designing the feature, you can remove yourself with the above syntax. 28 | -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | # Workflow based on the main w3c/spec-prod action example: 2 | # https://github.com/w3c/spec-prod/#basic-usage 3 | 4 | name: Build, Validate, Deploy and Publish 5 | 6 | on: 7 | # Worflow runs on pull requests where it makes sure that the spec can still be 8 | # generated, that markup is valid and that there are no broken links, as 9 | # well as on pushes to the default branch where it also deploys the generated 10 | # spec to the gh-pages branch and publishes the result to /TR. 11 | # The "workflow_dispatch" hook allows admins to also trigger the workflow 12 | # manually from GitHub's UI. 13 | pull_request: {} 14 | push: 15 | branches: [main] 16 | workflow_dispatch: 17 | 18 | jobs: 19 | main: 20 | runs-on: ubuntu-latest 21 | steps: 22 | # See doc at https://github.com/actions/checkout#checkout-v2 23 | - name: Checkout repository 24 | uses: actions/checkout@v2 25 | 26 | # See doc at https://github.com/w3c/spec-prod/#spec-prod 27 | # The action only deploys the generated spec to the gh-pages branch when 28 | # the workflow was triggered by a push to the default branch. 29 | - name: Build and validate index.html, push to gh-pages branch if needed 30 | uses: w3c/spec-prod@v2 31 | with: 32 | GH_PAGES_BRANCH: gh-pages 33 | -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | # Audio Session API Explainer 2 | 3 | ## Objectives 4 | People consume a lot of media (audio/video) and the Web is one of the primary means of consuming this type of content. 5 | However, media on the web does not integrate well with the platform. 6 | The Audio Session API helps to close the gap with platforms that have audio session/audio focus such as Android and iOS. 7 | This API will help by improving the audio-mixing of websites with native apps, so they can play on top of each other, or play exclusively. 8 | 9 | Additionally, on some platforms the user agent will automatically manage the audio session for the site based on whether media elements are playing or not and which APIs are used for playing audio. 10 | In some cases this may not match user expectations so this API will provide overrides for the authors. 11 | 12 | ### Goals 13 | 14 | * **A site should be able to define how audio streams will interact with the platform.** 15 | This is where it can be annoying where two tabs play audio at the same time. 16 | However, in some cases it may be appropriate to play the two audio streams on top of each other (e.g. a transient ping). 17 | * **A site should be able to manage its own audio session and focus.** 18 | If a site wishes to manage its own audio focus (when to restart playing once uninterrupted for instance) then the user agent should not automatically manage it. 19 | This would be used on a site where the default user agent audio focus logic is not appropriate (a media site where we switch tracks) or supported (e.g. WebAudio, WebRTC sites). 20 | * **A site should be able to determine its own audio session state.** 21 | A site should be notified if its audio session state changes. 22 | This is so sites that are manually managing focus can be aware of their current state. 23 | * **To provide an experience on par with native apps.** 24 | Native apps have audio session APIs on some platforms so we should provide a similar level of experience for websites. 25 | 26 | ### Non-goals 27 | 28 | * We should aim to improve the audio interaction between the site and the platform. Audio interaction within the site should be up to the site in the first version of this document. For instance, a web site cannot manipulate more than one audio session and cannot group audio producers in different audio sesssions. 29 | 30 | ## API Design 31 | 32 | By convention, there are several `audio session types` for different purposes: 33 | 34 | * Playback (`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. 35 | * Transient (`transient`) audio, such as a notification ping. They usually should play on top of playback audio (and maybe also "duck" persistent audio). 36 | * Transient solo (`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. 37 | * Ambient (`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. 38 | * Play and record (`play-and-record`) audio, which is used for recording audio. This is useful in cases microphone is being used or in video conferencing applications. 39 | * Auto (`auto`) lets the User Agent choose the best audio session type according the use of audio by the web page. This is the type of the default AudioSession. 40 | 41 | The AudioSession is the main interface for this API. It can have the following states: 42 | 43 | * active: the AudioSession is playing sound. 44 | * interrupted: the AudioSession is not playing sound, but can resume when it will get uninterrupted. 45 | * inactive: the AudioSession is not playing sound. 46 | 47 | The page has a default audio session which is used by the user agent to automatically set up the audio session parameters. 48 | The UA will request and abandon audio focus when media elements start/finish playing on the page. 49 | This default audio session is represented as an `AudioSession` object that is exposed as `navigator.audioSession`. 50 | 51 | ```javascript 52 | enum AudioSessionState { 53 | "inactive", 54 | "active", 55 | "interrupted" 56 | }; 57 | 58 | enum AudioSessionType { 59 | "auto", 60 | "playback", 61 | "transient", 62 | "transient-solo", 63 | "ambient", 64 | "play-and-record" 65 | }; 66 | 67 | [Exposed=Window] 68 | partial interface Navigator { 69 | // The default audio session that the user agent will use when media elements start/stop playing. 70 | readonly attribute AudioSession audioSession; 71 | }; 72 | 73 | [Exposed=Window] 74 | interface AudioSession : EventTarget { 75 | attribute AudioSessionType type; 76 | 77 | readonly attribute AudioSessionState state; 78 | attribute EventHandler onstatechange; 79 | }; 80 | ``` 81 | 82 | ## Sample Code 83 | 84 | #### A site sets its audio session type proactively to "play-and-record" 85 | 86 | ```javascript 87 | navigator.audioSession.type = 'play-and-record'; 88 | // From now on, volume might be set based on 'play-and-record'. 89 | ... 90 | // Start playing remote media 91 | remoteVideo.srcObject = remoteMediaStream; 92 | remoteVideo.play(); 93 | // Start capturing 94 | navigator.mediaDevices.getUserMedia({ audio:true, video:true }).then(stream => { 95 | localVideo.srcObject = stream; 96 | }); 97 | ``` 98 | 99 | #### A site reacts upon interruption 100 | 101 | ```javascript 102 | navigator.audioSession.type = 'play-and-record'; 103 | // From now on, volume might be set based on 'play-and-record'. 104 | ... 105 | // Start playing remote media 106 | remoteVideo.srcObject = remoteMediaStream; 107 | remoteVideo.play(); 108 | // Start capturing 109 | navigator.mediaDevices.getUserMedia({ audio:true, video:true }).then(stream => { 110 | localVideo.srcObject = stream; 111 | }); 112 | 113 | let isInterrupted = false; 114 | navigator.audioSession.onstatechange = () => { 115 | if (navigator.audioSession.state === 'interrupted') { 116 | isInterrupted = true; 117 | localVideo.pause(); 118 | remoteVideo.pause(); 119 | // Make it clear to the user that the call is interrupted. 120 | showInterruptedBanner(); 121 | localVideo.srcObject.getTracks().forEach(track => track.enabled = false); 122 | return; 123 | } 124 | if (isInterrupted) { 125 | isInterrupted = false; 126 | // Let user decide when to restart the call. 127 | showOptionalRestartBanner().then((result) => { 128 | if (!result) 129 | return; 130 | localVideo.srcObject.getTracks().forEach(track => track.enabled = true); 131 | localVideo.play(); 132 | remoteVideo.play(); 133 | }); 134 | } 135 | } 136 | ``` 137 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |
2 | Title: Audio Session 3 | Shortname: audio-session 4 | Level: None 5 | Status: w3c/ED 6 | Group: mediawg 7 | Repository: w3c/audio-session 8 | URL: https://w3c.github.io/audio-session/ 9 | Editor: Youenn Fablet, Apple https://www.apple.com/, youenn@apple.com, w3cid 96458 10 | Editor: Alastor Wu, Mozilla https://www.mozilla.org, alwu@mozilla.com, w3cid 92198 11 | Abstract: This API defines an API surface for controlling how audio is rendered and interacts with other audio playing applications 12 | Markup Shorthands: css no, markdown yes 13 |14 | 15 | # Introduction # {#introduction} 16 | 17 | People consume a lot of media (audio/video) and the Web is one of the primary means of consuming this type of content. 18 | However, media on the web does not integrate well with the platform. 19 | The Audio Session API helps to close the gap with platforms that have audio session/audio focus such as Android and iOS. 20 | This API will help by improving the audio-mixing of websites with native apps, so they can play on top of each other, or play exclusively. 21 | 22 | Additionally, on some platforms the user agent will automatically manage the audio session for the site 23 | based on whether media elements are playing or not and which APIs are used for playing audio. 24 | In some cases this may not match user expectations, this API provides overrides to authors. 25 | 26 | # The {{AudioSession}} interface # {#audiosession-interface} 27 | 28 | An audio session represents the playback of auditory media. 29 | An audio session can be of particular [=audio session/type=] and in a given [=audio session/state=]. 30 | 31 | The {{AudioSession}} is the main interface for this API, which is accessed through the {{Navigator}} interface (see [[#extensions-to-navigator]]). 32 | 33 |
34 | [Exposed=Window]
35 | interface AudioSession : EventTarget {
36 | attribute AudioSessionType type;
37 |
38 | readonly attribute AudioSessionState state;
39 | attribute EventHandler onstatechange;
40 | };
41 |
42 |
43 | ## Audio session states ## {#audio-session-types}
44 |
45 | By convention, there are several different [=audio session=] types for different purposes.
46 | In the API, these are represented by the {{AudioSessionType}} enum:
47 |
48 |
64 | enum AudioSessionType {
65 | "auto",
66 | "playback",
67 | "transient",
68 | "transient-solo",
69 | "ambient",
70 | "play-and-record"
71 | };
72 |
73 |
74 | ## Audio session states ## {#audio-session-states}
75 |
76 | An [=audio session=] can be in one of following state , which are represented in the API by the {{AudioSessionState}} enum:
77 |
78 |
92 | enum AudioSessionState {
93 | "inactive",
94 | "active",
95 | "interrupted"
96 | };
97 |
98 |
99 | # Extensions to the `Navigator` interface # {#extensions-to-navigator}
100 |
101 |
102 | [Exposed=Window]
103 | partial interface Navigator {
104 | // The default audio session that the user agent will use when media elements start/stop playing.
105 | readonly attribute AudioSession audioSession;
106 | };
107 |
108 |
109 | # Privacy considerations # {#privacy}
110 |
111 | # Security considerations # {#security}
112 |
113 | # Examples # {#examples}
114 |
115 | ## A site sets its audio session type proactively to "play-and-record" ## {#proactive-play-and-record-example}
116 |
117 | ```javascript
118 | navigator.audioSession.type = 'play-and-record';
119 | // From now on, volume might be set based on 'play-and-record'.
120 | ...
121 | // Start playing remote media
122 | remoteVideo.srcObject = remoteMediaStream;
123 | remoteVideo.play();
124 | // Start capturing
125 | navigator.mediaDevices
126 | .getUserMedia({ audio: true, video: true })
127 | .then((stream) => {
128 | localVideo.srcObject = stream;
129 | });
130 | ```
131 |
132 | ## A site reacts upon interruption ## {#interrutpion-handling-example}
133 |
134 | ```javascript
135 | navigator.audioSession.type = "play-and-record";
136 | // From now on, volume might be set based on 'play-and-record'.
137 | ...
138 | // Start playing remote media
139 | remoteVideo.srcObject = remoteMediaStream;
140 | remoteVideo.play();
141 | // Start capturing
142 | navigator.mediaDevices
143 | .getUserMedia({ audio: true, video: true })
144 | .then((stream) => {
145 | localVideo.srcObject = stream;
146 | });
147 |
148 | navigator.audioSession.onstatechange = async () => {
149 | if (navigator.audioSession.state === "interrupted") {
150 | localVideo.pause();
151 | remoteVideo.pause();
152 | // Make it clear to the user that the call is interrupted.
153 | showInterruptedBanner();
154 | for (const track of localVideo.srcObject.getTracks()) {
155 | track.enabled = false;
156 | }
157 | } else {
158 | // Let user decide when to restart the call.
159 | const shouldRestart = await showOptionalRestartBanner();
160 | if (!shouldRestart) {
161 | return;
162 | }
163 | for (const track of localVideo.srcObject.getTracks()) {
164 | track.enabled = true;
165 | }
166 | localVideo.play();
167 | remoteVideo.play();
168 | }
169 | };
170 | ```
171 |
172 | # Acknowledgements # {#acknowledgements}
173 |
174 | The Working Group acknowledges the following people for their invaluable contributions to this specification:
175 |
176 | * Becca Hughes
177 | * Mounir Lamouri
178 | * Zhiqiang Zhang
179 |
--------------------------------------------------------------------------------