1. はじめに
人々は、ますます Web を通じてメディア(オーディオ/ビデオ)を消費するようになっており、 Web はこの種のコンテンツにアクセスするための主要なチャネルになっています。 しかし、Web 上のメディアは、多くの場合、基盤となるプラットフォームとのシームレスな統合を欠いています。 Audio Session API は、オーディオセッション管理または類似のオーディオフォーカス機能をサポートする プラットフォーム全体でメディア処理を強化することにより、この隔たりに対処します。 この API は、Web ベースのオーディオが他のアプリとどのように相互作用するかを改善し、 コンテキストに応じて、より良いオーディオミキシングまたは排他的な再生を可能にし、 デバイス全体でより一貫した統合メディア体験を提供します。
さらに、一部のプラットフォームは、メディア再生およびオーディオ再生に使用される API に基づいて、 サイトのオーディオセッションを自動的に管理します。 しかし、この振る舞いは、常にユーザーの期待に沿うとは限りません。 この API により、開発者はデフォルトの振る舞いを上書きし、オーディオセッションをより細かく制御できます。
2. 概念
Web ページは、HTMLMediaElement
や AudioContext
などのさまざまな API を組み合わせて、さまざまな方法でオーディオ処理を行うことができます。
このオーディオ処理には開始と停止があり、使用されているすべての異なるオーディオ API を集約します。
オーディオセッションは、
この集約されたオーディオ処理を表します。これは、Web ページが行うオーディオ処理の一般的な性質を
Web ページが表明できるようにします。
オーディオセッションは、特定の 型を持ち、 特定の 状態にあることができます。 オーディオセッションは、個々の ソース(マイク録音)およびシンク(オーディオレンダリング)の集合に対するオーディオを管理し、それらは オーディオセッションの 要素と呼ばれます。
オーディオセッションの要素には、 いくつかのプロパティがあります。
-
デフォルト型。これは、"
auto" の場合に、 オーディオセッションの型を 計算するために使用されます。 -
可聴フラグ。 これは、要素がオーディオを再生/録音している場合は
true、 そうでない場合はfalseです。
オーディオセッション要素は、その可聴フラグが true の場合、
可聴要素です。
さらに、オーディオセッション要素には、さまざまな状態変化を処理するための関連する手順があります。 デフォルトでは、これらの各手順は空の手順リストです。
-
要素更新手順。 これは、オーディオセッション状態が変化するたびに実行されます。
-
要素一時停止手順。 これは、オーディオセッション状態が
activeからinterruptedまたはinactiveのいずれかへ移行したときに実行されます。 -
要素再開手順。 これは、オーディオセッション状態が
interruptedからactiveへ移行したときに実行されます。
この仕様は、これらの手順、デフォルト型、および可聴フラグを、オーディオセッションの一部の要素について、§ 6 オーディオソースおよびシンクの統合で定義しています。 他の要素を定義する仕様は、これらの手順とプロパティを定義する必要があります。
トップレベル閲覧コンテキストは、
選択されたオーディオセッションを持ちます。
任意のオーディオセッションに
変更があった場合、ユーザーエージェントはどのオーディオセッションが選択されたオーディオセッションになるかを更新します。
トップレベル閲覧コンテキストは、その選択されたオーディオセッションが
null でなく、かつその状態が active
である場合、オーディオフォーカスを持つといいます。
3. AudioSession
インターフェイス
AudioSession
は、この API の主要なインターフェイスです。
これは Navigator
インターフェイスを通じてアクセスされます(§ 4 Navigator インターフェイスへの拡張を参照)。
[Exposed =Window ]interface :AudioSession EventTarget {attribute AudioSessionType ;type readonly attribute AudioSessionState ;state attribute EventHandler ; };onstatechange
realm に AudioSession
オブジェクトを作成するには、次の手順を実行します。
-
audioSession を、realm における新しい
AudioSessionオブジェクトとし、次の内部スロットで初期化します。 -
audioSession を返します。
各 AudioSession
オブジェクトは、その基盤となるオーディオセッションに一意に結び付けられます。
AudioSession
の state 属性は、そのオーディオ
セッションの状態を反映します。
取得時には、AudioSession
の [[state]]
値を返さなければなりません。
AudioSession
の type 属性は、auto
を除き、そのオーディオ
セッションの型を反映します。
取得時には、AudioSession
の [[type]]
値を返さなければなりません。
設定時には、audioSession に設定される新しい値を newValue として、 次の手順を実行しなければなりません。
-
audioSession.[[type]] が newValue と等しい場合、これらの手順を中止します。
-
audioSession.[[type]] を newValue に設定します。
-
audioSession の型を更新します。
3.1. オーディオセッション型
慣例として、さまざまな目的に応じて、いくつかの異なるオーディオセッションの型があります。
API では、これらは AudioSessionType
enum によって表されます。
playback- 再生オーディオ。これは動画や音楽再生、ポッドキャストなどに使用されます。 他の再生オーディオとミックスされるべきではありません。(おそらく)他のすべてのオーディオを無期限に一時停止すべきです。
transient- 通知音などの一時的なオーディオ。通常、再生オーディオの上に重ねて再生されるべきです(また、 永続的なオーディオを「ダック」することもあります)。
transient-solo- 運転案内などの一時的なソロオーディオ。他のすべてのオーディオを一時停止/ミュートし、 排他的に再生すべきです。一時的なソロオーディオが終了したときは、一時停止/ミュートされたオーディオを再開すべきです。
ambient- アンビエントオーディオ。これは他の種類のオーディオとミックス可能です。 ユーザーが複数のページからのオーディオをミックスしたい場合など、一部の特殊なケースで有用です。
play-and-record- 再生および録音オーディオ。これはオーディオ録音に使用されます。 マイクが使用されている場合やビデオ会議アプリケーションで有用です。
auto- Auto は、Web ページによるオーディオの使用に応じて、ユーザーエージェントが最適なオーディオセッション型を選択できるようにします。
これは
AudioSessionのデフォルト型です。
enum {AudioSessionType "auto" ,"playback" ,"transient" ,"transient-solo" ,"ambient" ,"play-and-record" };
AudioSessionType
は、それが playback、
play-and-record
または transient-solo
である場合、排他的型です。
3.2. オーディオセッション状態
オーディオセッションは、
次のいずれかの状態にあることができ、これらは API では AudioSessionState
enum によって表されます。
active- オーディオセッションは、 音を再生しているか、マイクを録音しています。
interrupted- オーディオセッションは、 音を再生しておらず、マイクも録音していませんが、中断が解除されれば再開できます。
inactive- オーディオセッションは、 音を再生しておらず、マイクも録音していません。
enum {AudioSessionState "inactive" ,"active" ,"interrupted" };
オーディオセッションの状態は
変化する可能性があり、その変化は状態の変化を通知する手順を通じて、対応する AudioSession
オブジェクトに自動的に反映されます。
4. Navigator インターフェイスへの拡張
各 Window
は、関連付けられた
AudioSessionを持ち、これは AudioSession
オブジェクトです。
これは、オーディオセッションパラメーターを自動的に設定するためにユーザーエージェントが使用するデフォルトの
オーディオセッションを表します。
ユーザーエージェントは、オーディオセッション要素が再生を開始または終了したときに、
オーディオフォーカスを要求または放棄します。
Window
オブジェクトの作成時に、その関連付けられた AudioSessionは、AudioSession
オブジェクトとして新たに作成され、Window
オブジェクトの関連するレルムで設定されなければなりません。
関連付けられた
AudioSession の要素のリストは、Window
オブジェクトのオーディオソースおよびシンクが作成または削除されるにつれて動的に更新されます。
[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
5. オーディオセッションアルゴリズム
5.1. AudioSession の type を更新する
audioSession の型を更新するには、 ユーザーエージェントは次の手順を実行しなければなりません。
-
audioSession.[[isTypeBeingApplied]] が
trueの場合、 これらの手順を中止します。 -
audioSession.[[isTypeBeingApplied]] を
trueに設定します。 -
次の手順を実行するタスクをキューに入れます。
-
audioSession.[[isTypeBeingApplied]] を
falseに設定します。 -
audioSession.[[type]] が audioSession.[[appliedType]] と同じである場合、これらの手順を中止します。
-
audioSession.[[appliedType]] を audioSession.[[type]] に設定します。
-
audioSession により、audioSession のトップレベル閲覧コンテキストのすべての AudioSession 状態を更新します。
-
audioSession.[[elements]] の各 element について、element を更新します。
-
newType を、audioSession の型を計算する結果とします。
-
並列に、audioSession のオーディオセッションの型を newType に設定します。
-
5.2. AudioSession の state を更新する
オーディオセッション要素が開始または停止しているとき、ユーザーエージェントは、
非アクティブ化するおよびアクティブ化を試みるアルゴリズムを通じて、オーディオセッションの
状態を設定する手順を実行します。
オーディオセッションの状態を active
に設定することには、特にオーディオセッションの型が排他的型である場合、結果が伴います。
-
以下のアルゴリズムで定義されるように、トップレベル閲覧コンテキストの
AudioSessionオブジェクトを非アクティブ化できます。 -
別のタブまたは別のアプリケーションのオーディオを一時停止できます。
逆に、オーディオセッションの
状態は、
オーディオセッション要素の変更とは別に変更されることがあります。
ユーザーエージェントがそのような変更を観測したとき、ユーザーエージェントは、変更されたオーディオセッションに
結び付けられた
AudioSession
オブジェクトである audioSession と、新しいオーディオセッション状態である newState を用いて、状態の変化を通知するためのタスクをキューに入れなければなりません。
playback オーディオセッションは、着信電話、または別のタブで新しいメディアコンテンツの再生を開始しようとしている
別の playback セッションによって中断されることがあります。
audioSession および newState を用いて状態の 変化を通知するには、ユーザーエージェントは次の手順を実行しなければなりません。
-
isMutatingState を、audioSession.[[state]] が newState でない場合は
true、そうでない場合はfalseとします。 -
audioSession.[[state]] を newState に設定します。
-
newState が
inactiveの場合、 audioSession.[[interruptedElements]] を空リストに設定します。 -
audioSession.[[elements]] の各 element について、element を更新します。
-
isMutatingState が
falseの場合、これらの手順を中止します。 -
audioSession により、audioSession のトップレベル閲覧コンテキストのすべての AudioSession 状態を更新します。
-
audioSession に対して statechange という名前のイベントを発火します。
audioSession という名前の AudioSession
を非アクティブ化するには、ユーザーエージェントは次の手順を実行しなければなりません。
-
次の手順を並列に実行します。
-
audioSession のオーディオセッションの状態を設定し、
inactiveにします。 -
アサート: audioSession のオーディオセッションの状態は
inactiveです。 -
audioSession と、そのオーディオセッションの状態を用いて、状態の 変化を通知するためのタスクをキューに入れます。
-
audioSession という名前の
AudioSession
のアクティブ化を試みるには、ユーザーエージェントは次の手順を実行しなければなりません。
-
次の手順を並列に実行します。
-
audioSession のオーディオセッションの状態を設定し、
activeにします。 状態を設定することは、activeに対して失敗する可能性があり、その場合、オーディオセッションの状態はinactiveまたはinterruptedのいずれかになります。 -
audioSession と、そのオーディオセッションの状態を用いて、状態の 変化を通知するためのタスクをキューに入れます。
-
5.3. 選択されたオーディオセッションを更新する
context という名前のトップレベル閲覧コンテキストの選択された オーディオセッションを更新するには、 ユーザーエージェントは次の手順を実行しなければなりません。
-
activeAudioSessions を、context およびその子の
AudioSessionオブジェクトに結び付けられたすべてのオーディオセッションのうち、幅優先順で、次の 両方の制約に一致するもののリストとします。-
AudioSessionオブジェクトの型を計算する結果が排他的型です。
-
activeAudioSessions が空の場合、これらの手順を中止します。
-
activeAudioSessions 内にオーディオ セッションが 1 つだけある場合、選択されたオーディオセッションを このオーディオセッションに設定し、 これらの手順を中止します。
-
アサート: activeAudioSessions 内のオーディオ セッションに結び付けられた任意の
AudioSessionオブジェクトで、audioSession という名前のものについて、 audioSession.[[type]] はautoです。明示的な排他的型を持つオーディオセッションは、任意の時点で 1 つだけ アクティブになれることが期待されます。 activeAudioSessions 内に複数のアクティブなオーディオセッションがある場合、それらの [[type]] はautoのみになり得ます。 -
ユーザーエージェントは、activeAudioSessions を並べ替えるために特定のヒューリスティックを適用してもよいです。
-
選択されたオーディオセッションを、 activeAudioSessions 内の最初のオーディオセッションに設定します。
5.4. その他のアルゴリズム
context という名前のトップレベル閲覧コンテキストのすべての AudioSession 状態を更新するには、 updatedAudioSession を用いて、次の手順を実行します。
-
context の選択されたオーディオセッションを更新します。
-
updatedType を、updatedAudioSession の型を 計算する結果とします。
-
updatedType が排他的型でない場合、または updatedAudioSession.[[state]] が
activeでない場合、 これらの手順を中止します。 -
audioSessions を、context およびその子のすべての
AudioSessionオブジェクトの幅優先順のリストとします。 -
updatedAudioSession を除く audioSessions の各 audioSession について、 次の手順を実行します。
audioSession のオーディオ セッション型を計算するには、ユーザーエージェントは次の手順を実行しなければなりません。
-
audioSession.[[type]] が
autoでない場合、 audioSession.[[type]] を返します。 -
audioSession.[[elements]] のいずれかの element が
play-and-recordのデフォルト型を持ち、その状態がactiveである場合、play-and-recordを返します。 -
audioSession.[[elements]] のいずれかの element が
playbackのデフォルト型を持ち、その状態がactiveである場合、playbackを返します。 -
audioSession.[[elements]] のいずれかの element が
transient-soloのデフォルト型を持ち、その状態がactiveである場合、transient-soloを返します。 -
audioSession.[[elements]] のいずれかの element が
transientのデフォルト型を持ち、その状態がactiveである場合、transientを返します。 -
ambientを返します。
6. オーディオソースおよびシンクの統合
この節では、AudioContext、
HTMLMediaElement
およびマイクの MediaStreamTrack
について、オーディオ
セッション要素の手順とプロパティを説明します。
要素状態は次のとおりです。
-
それが自身の
AudioSessionの [[interruptedElements]] 内にある場合、interrupted。 -
それ以外の場合、
inactive。
element という名前の要素を更新するには、 ユーザーエージェントは次の手順を実行しなければなりません。
-
audioSession を element の
AudioSessionとします。 -
element の更新手順を実行します。
-
element が可聴要素であり、かつ audioSession.[[state]] が
interruptedである場合、 次の手順を実行します。-
element を audioSession.[[interruptedElements]] に追加します。
-
element の一時停止手順を実行します。
-
-
element が audioSession.[[interruptedElements]] 内にあり、かつ audioSession.[[state]] が
activeである場合、 次の手順を実行します。-
element を audioSession.[[interruptedElements]] から削除します。
-
element の再開手順を実行します。
-
audioSession の要素の 1 つの可聴フラグが 変化しているとき、ユーザーエージェントは次の手順を実行しなければなりません。
-
可聴フラグが
trueに変化している場合、audioSession のアクティブ化を試みます。 -
そうでなく、audioSession.[[elements]] のいずれかの element が
interruptedの状態を持つ場合、 これらの手順を中止します。 -
そうでなければ、audioSession を非アクティブ化します。
6.1. AudioContext
AudioContext
は、次のプロパティを持つ要素です。
-
その一時停止手順は次のとおりです。
-
audioContext を
AudioContextオブジェクトとします。 -
audioContext を一時停止するための制御メッセージをキューに入れます。
-
-
その再開手順は次のとおりです。
-
audioContext を
AudioContextオブジェクトとします。 -
audioContext の一時停止を解除するための制御メッセージをキューに入れます。
-
AudioContext
が作成されたとき、ユーザーエージェントは次の手順を実行しなければなりません。
-
audioContext を、新しく作成された
AudioContextとします。 -
audioSession を、audioContext が作成される
WindowオブジェクトのAudioSessionオブジェクトとします。 -
audioContext を audioSession.[[elements]] に追加します。
6.2. HTMLMediaElement
HTMLMediaElement
は、次のプロパティを持つ要素です。
-
その可聴フラグは、 再生中であり、その音量が
0ではなく、ミュートされておらず、かつ オーディオトラックを持つ場合、trueです。 -
その一時停止手順は次のとおりです。
-
mediaElement を
HTMLMediaElementオブジェクトとします。 -
mediaElement の内部一時停止手順を実行するためにタスクをキューに入れます。
-
-
その再開手順は次のとおりです。
-
mediaElement を
HTMLMediaElementオブジェクトとします。 -
mediaElement の内部再生手順を実行するためにタスクをキューに入れます。
-
HTMLMediaElement
の
ノード文書が変更されるとき、ユーザーエージェントは次の手順を実行しなければなりません。
-
mediaElement を、そのノード文書が変更される
HTMLMediaElementとします。 -
previousWindow を、存在する場合は mediaElement の以前のノード文書に関連付けられた
Windowオブジェクトとし、そうでなければnullとします。 -
previousWindow が
nullでない場合、mediaElement を previousWindow の関連付けられた AudioSession.[[elements]] から削除します。 -
newWindow を、存在する場合は mediaElement の新しいノード文書に関連付けられた
Windowオブジェクトとし、そうでなければnullとします。 -
newWindow が
nullでない場合、mediaElement を newWindow の関連付けられた AudioSession.[[elements]] に追加します。
6.3. マイク MediaStreamTrack
マイクキャプチャ MediaStreamTrack
は、次のプロパティを持つ要素です。
-
そのデフォルト型は
play-and-recordです。 -
その要素更新手順は次のとおりです。
-
track を
MediaStreamTrackオブジェクトとします。 -
audioSession を track の
AudioSessionとします。 -
audioSession.[[type]] が
play-and-recordまたはautoでない場合、track をendします。
-
-
その一時停止手順は次のとおりです。
-
track を
MediaStreamTrackオブジェクトとします。 -
track のミュート状態を設定することにより
trueにするためのタスクをキューに入れます。
-
-
その再開手順は次のとおりです。
-
track を
MediaStreamTrackオブジェクトとします。 -
track のミュート状態を設定することにより
falseにするためのタスクをキューに入れます。
-
マイクキャプチャ MediaStreamTrack
が作成されたとき、ユーザーエージェントは次の手順を実行しなければなりません。
-
track を、新しく作成された
MediaStreamTrackとします。 -
audioSession を、track が作成される
WindowオブジェクトのAudioSessionオブジェクトとします。 -
track を audioSession.[[elements]] に追加します。
FIXME: MediaStreamTrack ではなく、Window の mediaDevices の mediaStreamTrackSources に格納されたオーディオトラックのソースにフックするべきです。 これは、転送されたマイクトラックの場合を扱うべきです。
7. プライバシーに関する考慮事項
8. セキュリティに関する考慮事項
9. 例
9.1. サイトがオーディオセッション型を先回りして "play-and-record" に設定する
navigator. audioSession. type= 'play-and-record' ; // これ以降、音量は 'play-and-record' に基づいて設定される可能性があります。 ... // リモートメディアの再生を開始する remoteVideo. srcObject= remoteMediaStream; remoteVideo. play(); // キャプチャを開始する navigator. mediaDevices. getUserMedia({ audio: true , video: true }) . then(( stream) => { localVideo. srcObject= stream; });
9.2. サイトが中断に反応する
navigator. audioSession. type= "play-and-record" ; // これ以降、音量は 'play-and-record' に基づいて設定される可能性があります。 ... // リモートメディアの再生を開始する remoteVideo. srcObject= remoteMediaStream; remoteVideo. play(); // キャプチャを開始する 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(); // 通話が中断されていることをユーザーに明確に示す。 showInterruptedBanner(); for ( const trackof localVideo. srcObject. getTracks()) { track. enabled= false ; } } else { // 通話をいつ再開するかはユーザーに決めさせる。 const shouldRestart= await showOptionalRestartBanner(); if ( ! shouldRestart) { return ; } for ( const trackof localVideo. srcObject. getTracks()) { track. enabled= true ; } localVideo. play(); remoteVideo. play(); } };
10. 謝辞
ワーキンググループは、この仕様への貴重な貢献について、次の方々に謝意を表します。
-
Becca Hughes
-
Mounir Lamouri
-
Zhiqiang Zhang