1. 소개
사람들은 점점 더 Web을 통해 미디어(오디오/비디오)를 소비하고 있으며, Web은 이러한 종류의 콘텐츠에 접근하기 위한 주요 채널이 되었습니다. 그러나 Web상의 미디어는 많은 경우 기반 플랫폼과의 매끄러운 통합이 부족합니다. Audio Session API는 오디오 세션 관리 또는 유사한 오디오 포커스 기능을 지원하는 플랫폼 전반에서 미디어 처리를 강화함으로써 이 간극을 해결합니다. 이 API는 Web 기반 오디오가 다른 앱과 어떻게 상호작용하는지를 개선하고, 컨텍스트에 따라 더 나은 오디오 믹싱 또는 배타적 재생을 가능하게 하며, 디바이스 전반에서 더 일관되고 통합된 미디어 경험을 제공합니다.
또한 일부 플랫폼은 미디어 재생 및 오디오 재생에 사용되는 API를 기반으로 사이트의 오디오 세션을 자동으로 관리합니다. 그러나 이 동작이 항상 사용자 기대와 일치하는 것은 아닐 수 있습니다. 이 API를 통해 개발자는 기본 동작을 덮어쓰고 오디오 세션을 더 세밀하게 제어할 수 있습니다.
2. 개념
Web 페이지는 HTMLMediaElement
나 AudioContext
같은 여러 API를 조합하여 다양한 방식으로 오디오 처리를 수행할 수 있습니다.
이 오디오 처리에는 시작과 중지가 있으며, 사용 중인 모든 서로 다른 오디오 API를 집약합니다.
오디오 세션은
이 집약된 오디오 처리를 나타냅니다. 이는 Web 페이지가 수행하는 오디오 처리의 일반적인 성질을
Web 페이지가 표현할 수 있게 합니다.
오디오 세션은 특정 유형일 수 있으며, 특정 상태에 있을 수 있습니다. 오디오 세션은 개별 소스(마이크 녹음) 및 싱크(오디오 렌더링)의 집합에 대한 오디오를 관리하며, 이들은 오디오 세션 요소라고 불립니다.
-
가청 플래그. 이는 요소가 오디오를 재생/녹음하고 있는 경우
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은 Window
객체의 관련 realm으로 새로 생성된 AudioSession
객체로 설정되어야 합니다.
관련
AudioSession의 요소 목록은 Window
객체의 오디오 소스와 싱크가 생성되거나 제거됨에 따라 동적으로 갱신됩니다.
[Exposed =Window ]partial interface Navigator { // 미디어 요소가 재생을 시작/중지할 때 사용자 에이전트가 사용할 기본 오디오 세션.readonly attribute AudioSession ; };audioSession
5. 오디오 세션 알고리즘
5.1. AudioSession의 type 갱신
audioSession의 type을 갱신하려면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:
-
audioSession.[[isTypeBeingApplied]]가
true이면, 이 단계를 중단한다. -
audioSession.[[isTypeBeingApplied]]를
true로 설정한다. -
다음 단계를 실행하도록 task를 큐에 넣는다:
-
audioSession.[[isTypeBeingApplied]]를
false로 설정한다. -
audioSession.[[type]]이 audioSession.[[appliedType]]와 같으면, 이 단계를 중단한다.
-
audioSession.[[appliedType]]를 audioSession.[[type]]으로 설정한다.
-
audioSession와 함께, audioSession의 최상위 브라우징 컨텍스트의 모든 AudioSession 상태를 갱신한다.
-
audioSession.[[elements]]의 각 element에 대해, element를 갱신한다.
-
newType을 audioSession의 type 계산 결과로 둔다.
-
5.2. AudioSession의 state 갱신
오디오 세션 요소가
시작하거나 중지할 때, 사용자 에이전트는
비활성화 및 활성화 시도 알고리즘을 통해
오디오 세션의
state를 설정하는 단계를 실행한다.
오디오 세션의 state를 active로
설정하면 결과가 발생하며, 특히 오디오 세션의 type이 배타적 유형인 경우 그러하다:
-
아래 알고리즘에 정의된 대로, 최상위 브라우징 컨텍스트의
AudioSession객체를 비활성화할 수 있다. -
다른 탭이나 다른 애플리케이션의 오디오를 일시정지할 수 있다.
반대로, 오디오 세션
state는
오디오 세션 요소 변경
외부에서 수정될 수 있다.
사용자 에이전트가 그러한 수정을 관찰하면, 사용자 에이전트는 반드시 audioSession,
수정된 오디오 세션에
결부된
AudioSession
객체, 그리고 newState를 새 오디오 세션 state로 하여 state의 변화를 알리기 위한 task를 큐에 넣어야 한다.
audioSession 및 newState와 함께 state의 변화를 알리려면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:
-
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이라는
AudioSession을
활성화 시도하려면,
사용자 에이전트는 반드시 다음 단계를 실행해야 한다:
-
다음 단계를 병렬로 실행한다:
-
audioSession의 오디오 세션의 state를 설정하여
active로 한다. state를 설정하여active로 하는 것은 실패할 수 있으며, 이 경우 오디오 세션의 state는inactive또는interrupted중 하나가 된다. -
audioSession 및 그 오디오 세션의 state와 함께 state의 변화를 알리기 위한 task를 큐에 넣는다.
-
5.3. 선택된 오디오 세션 갱신
context라는 이름의 최상위 브라우징 컨텍스트의 선택된 오디오 세션을 갱신하려면, 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:
-
activeAudioSessions를 context 및 그 자식들의
AudioSession객체에 결부된 모든 오디오 세션 중 너비 우선 순서로 된 목록으로 하며, 다음 두 제약 조건을 모두 만족하는 것들로 한다:-
AudioSession객체의 type 계산 결과가 배타적 유형이다.
-
activeAudioSessions가 비어 있으면, 이 단계를 중단한다.
-
activeAudioSessions에 오디오 세션이 하나만 있으면, 선택된 오디오 세션을 이 오디오 세션으로 설정하고 이 단계를 중단한다.
-
단언: activeAudioSessions의 오디오 세션에 결부된 임의의
AudioSession객체 중 audioSession이라는 이름의 객체에 대해, audioSession.[[type]]은auto이다. -
사용자 에이전트는 activeAudioSessions의 순서를 재배열하기 위해 특정 휴리스틱을 적용할 수 있다.
-
선택된 오디오 세션을 activeAudioSessions의 첫 번째 오디오 세션으로 설정한다.
5.4. 기타 알고리즘
updatedAudioSession와 함께 context라는 이름의 최상위 브라우징 컨텍스트의 모든 AudioSession 상태를 갱신하려면, 다음 단계를 실행한다:
-
context의 선택된 오디오 세션을 갱신한다.
-
updatedType을 updatedAudioSession의 type 계산 결과로 둔다.
-
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의 요소 중 하나의 가청 플래그가 변경될 때, 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:
-
그렇지 않고, 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의 내부 일시정지 절차를 실행하도록 task를 큐에 넣는다.
-
-
그 재개 절차는 다음과 같다:
-
mediaElement를
HTMLMediaElement객체로 둔다. -
mediaElement의 내부 재생 절차를 실행하도록 task를 큐에 넣는다.
-
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을 종료한다.
-
-
그 일시정지 절차는 다음과 같다:
-
track을
MediaStreamTrack객체로 둔다. -
track의 muted 상태를 설정하여
true로 하도록 task를 큐에 넣는다.
-
-
그 재개 절차는 다음과 같다:
-
track을
MediaStreamTrack객체로 둔다. -
track의 muted 상태를 설정하여
false로 하도록 task를 큐에 넣는다.
-
마이크 캡처 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