1. 소개
대부분의 사용자 에이전트는 자동 재생 미디어를 차단하는 자체 메커니즘을 가지고 있으며, 이러한 메커니즘은 구현별로 다릅니다. 웹 개발자들은 자동 재생 미디어가 허용되는지 감지할 수 있는 방법이 필요하며, 이를 통해 대체 콘텐츠를 선택하거나 미디어가 자동 재생되지 않을 때 사용자 경험을 개선하는 등의 작업을 수행할 수 있습니다. 예를 들어, 사용자 에이전트가 소리 나는 자동 재생만 차단한다면 웹 개발자는 소리나는 미디어를 소리 없는 미디어로 교체하여 미디어가 계속 재생되도록 할 수 있습니다. 차단된 미디어가 사용자에게 정지된 이미지처럼 보이는 대신, 소리 없는 미디어를 사용함으로써 경험을 개선할 수 있습니다. 사용자 에이전트가 어떤 자동 재생 미디어도 허용하지 않는다면, 웹 개발자는 미디어 리소스와 관련 작업의 로딩을 중단하여 사용자의 대역폭과 CPU 사용량을 절약할 수 있습니다.현재 이 명세는 HTMLMediaElement
(video
및
audio)
그리고 Web Audio API만 다룹니다. 이 명세는
Web Speech API 및 애니메이션
image
(GIF 애니메이션)은 다루지 않습니다.
2. 자동 재생 감지 API
자동 재생 감지는Navigator
객체를 통해 수행할 수 있습니다.
결과는 미디어 타입과 동일한 타입을 가진 미디어가, 쿼리된 Navigator
객체와 연결된 Window
객체에 포함된 document
에 존재하는 미디어가 자동 재생을 허용하는지 알 수 있게 하거나, 특정 요소가 자동 재생을
허용하는지 확인할 수 있게 해줍니다.
2.1. 자동 재생 정책 열거형
enum {AutoplayPolicy "allowed" ,"allowed-muted" ,"disallowed" };
| 열거형 값 | 설명 |
|---|---|
"allowed"
| 미디어가 자동 재생을 허용합니다. |
"allowed-muted"
|
소리 없는 미디어
가 자동 재생을 허용합니다.
참고: 현재 이 속성은 주어진 미디어 타입이나 요소가
HTMLMediaElement
또는 그 확장(예: HTMLVideoElement
또는
HTMLAudioElement)
타입일 때만 반환됩니다.
소리 없는 미디어 요소
는 다음 조건 중 하나를 갖는 HTMLMediaElement
입니다:
|
"disallowed"
| 어떠한 미디어도 자동 재생을 허용하지 않습니다. |
disallowed)이라면
사용자가 페이지나 미디어에서 지원되는 제스처를 수행한 후에 정책이 allowed
또는 allowed-muted
로 변경될 수 있습니다.
2.2. 자동 재생 감지 메서드
enum {AutoplayPolicyMediaType "mediaelement" ,"audiocontext" }; [Exposed =Window ]partial interface Navigator {AutoplayPolicy (getAutoplayPolicy AutoplayPolicyMediaType );type AutoplayPolicy (getAutoplayPolicy HTMLMediaElement );element AutoplayPolicy (getAutoplayPolicy AudioContext ); };context
| 열거형 값 | 설명 |
|---|---|
mediaelement
|
HTMLMediaElement
및 그 확장(예: HTMLVideoElement
와 HTMLAudioElement)
의 상태 쿼리에 사용됨.
|
audiocontext
|
AudioContext
상태 쿼리에 사용됨.
|
2.2.1. 미디어 타입으로 쿼리
getAutoplayPolicy(type)
메서드는 대략적 상태를 반환합니다.
즉, 쿼리된 Navigator
객체와 연결된 Window
객체에 포함된 document
에 존재하는 미디어 요소 또는 오디오 컨텍스트가 자동 재생을 허용하는지 여부의 상태입니다.
여기서 대략적이라는 의미는 반환된 결과가 주어진 미디어 타입과 같은 모든 요소마다 항상 정확하지는 않다는 것입니다.
disallowed
인 경우에도 자동 재생될 수 있습니다.
이럴 때는 정확한 결과를 얻기 위해 특정 요소로도 쿼리하는 것이 권장됩니다.
예를 들어, 처음에는 미디어 타입으로 쿼리한 결과와 객체로 쿼리한 결과가 모두 disallowed
일 수 있습니다.
사용자가 미디어 요소를 클릭하면 그 미디어 요소로 쿼리한 결과는 allowed
로 바뀌지만 미디어 타입으로 쿼리하거나 아직 클릭하지 않은 다른 미디어 요소로 쿼리한 결과는
disallowed
를 계속 반환합니다.
getAutoplayPolicy(type)
메서드를 호출할 때, 사용자 에이전트는 다음 단계를 수행해야 합니다:
-
type이mediaelement이면HTMLMediaElement및 그 확장(예:HTMLVideoElement와HTMLAudioElement)이 쿼리된Navigator객체와 연결된Window객체의document에 존재하는 현재 상태를 반환합니다. -
type이audiocontext이면AudioContext이 쿼리된Navigator객체와 연결된Window객체의document에 존재하는 현재 상태를 반환합니다.
- 반환값이
allowed - 주어진 타입에 해당하는 모든 미디어가 자동 재생을 허용합니다.
- 반환값이
allowed-muted -
주어진 타입에 해당하는 모든 소리 없는 미디어가 자동 재생을 허용합니다.
참고: 현재 이 속성은 주어진 미디어 타입이
mediaelement일 때만 반환됩니다. 소리 없는 미디어란소리 없는 미디어 요소를 의미합니다. - 반환값이
disallowed - 주어진 타입에 해당하는 모든 미디어는 자동 재생이 허용되지 않습니다.
Navigator
객체로 쿼리한 결과와, 자식 문서에 연결된 Navigator
객체로 쿼리한 결과가 다를 수 있습니다.
foo.com의 최상위 문서 A에서 allowed
을 반환하고,
그 안에 bar.com의 다른 문서 B가 포함된 iframe이 있다고 가정합니다.
사용자 에이전트는 자식 문서 B도 상위 문서 A에서 상속된 결과와 동일하게 반환하거나,
문서 B에서 disallowed
등 다른 결과를 반환할 수 있습니다.
전자는 복잡성을 낮추고 자동 재생 차단 동작을 더 일관적으로 만듭니다. 후자는 더 세밀한 자동 재생 제어를 제공합니다.
2.2.2. 요소로 쿼리
getAutoplayPolicy(element)
및 getAutoplayPolicy(context)
메서드는 주어진 요소가 자동 재생을 허용하는지에 대한 현재 상태를 반환합니다.
- 반환값이
allowed - 이 요소는 현재 실행 컨텍스트 내에서 자동 재생이 허용됩니다.
- 반환값이
allowed-muted -
이 요소는 소리가 나지 않을 때만 자동 재생이 허용됩니다.
참고: 현재 이 속성은 주어진 요소가
HTMLMediaElement또는 그 확장(예:HTMLVideoElement또는HTMLAudioElement) 타입일 때만 반환됩니다. 소리 없는 미디어란소리 없는 미디어 요소를 의미합니다.또한, 작성자가 소리 없는 미디어 요소가 재생을 시작한 직후에 이를 소리나게 만든다면, 사용자 에이전트는 해당 미디어 요소를 즉시 일시 정지할 것을 권장합니다 왜냐하면 더 이상 소리 없는 상태가 아니기 때문입니다.
- 반환값이
disallowed -
이 요소는 자동 재생이 허용되지 않습니다.
참고:
HTMLMediaElement에 대해 작성자가play()를 호출하면play()에서 반환된 promise가NotAllowedError예외로 거부됩니다.AudioContext인 경우,AudioContextState가suspended상태로 유지된다는 의미입니다.
미디어 타입으로 쿼리한 결과와 요소로 쿼리한 결과가 다르다면, 작성자는 요소로 쿼리한 결과를 정확한 결과로 간주해야 합니다. 예시 2는 가능한 시나리오를 보여줍니다.
HTMLMediaElement
(또는 그 확장, 예: HTMLVideoElement
와 HTMLAudioElement)
또는
AudioContext
가 아니라면, 이 메서드들은 TypeError
를 throw 합니다.
3. 예시
if ( navigator. getAutoplayPolicy( "mediaelement" ) === "allowed" ) { // 새 미디어 요소를 생성하고 재생합니다. } else if ( navigator. getAutoplayPolicy( "mediaelement" ) === "allowed-muted" ) { // 새 미디어 요소를 생성하고 음소거 상태로 재생합니다. } else { // 자동 재생이 허용되지 않으므로, 대신 포스터를 표시합니다. }
AudioContext
를 시작할 수 있는지 판단합니다.
if ( navigator. getAutoplayPolicy( "audiocontext" ) === "allowed" ) { let ac= new AudioContext(); ac. onstatechange= function () { if ( ac. state=== "running" ) { // 오디오 앱을 시작하세요. } } } else { // 오디오 컨텍스트가 시작되지 않으므로 사용자에게 오디오 앱 시작을 유도하는 UI를 표시합니다. // 핸들러에서 ac.resume()을 호출하여 오디오를 시작할 수 있고, 'onstatechange'로 오디오 스택이 준비된 시점을 알 수 있습니다. }
function handlePlaySucceeded() { // 컨트롤 UI를 재생중 상태로 업데이트합니다. } function handlePlayFailed() { // 사용자가 비디오를 명시적으로 시작할 수 있게 버튼을 표시하고, // 이미지를 포스터로 보여 비디오 대신 대체합니다. } let video= document. getElementById( "video" ); switch ( navigator. getAutoplayPolicy( video)) { case "allowed" : video. src= "video.webm" ; video. play(). then( handlePlaySucceeded, handlePlayFailed); break ; case "allowed-muted" : video. src= "video.webm" ; video. muted= true ; video. play(). then( handlePlaySucceeded, handlePlayFailed); break ; default : // 자동 재생이 허용되지 않으므로 리소스를 다운로드할 필요가 없습니다. handlePlayFailed(); break ; }
AudioContext
를 시작할 수 있는지 판단합니다.
let ac= new AudioContext(); if ( navigator. getAutoplayPolicy( ac) === "allowed" ) { ac. onstatechange= function () { if ( ac. state=== "running" ) { // 오디오 앱을 시작하세요. } } } else { // 사용자에게 오디오 앱 시작을 요청하는 UI를 표시합니다. // 핸들러에서 ac.resume()을 호출하여 오디오를 시작할 수 있고, // 'onstatechange'로 오디오 스택이 준비된 시점을 알 수 있습니다. }
4. 보안 및 개인정보 보호 고려 사항
Self-Review Questionnaire: Security and Privacy § questions를 기준으로 합니다.본 명세에서 제공하는 API는 보안 및 개인정보 측면에서 매우 영향이 낮습니다. 사용자를 식별하는 데 이용될 수 있는 민감한 정보를 노출하지 않습니다. 센서나 사용자의 장치를 제어할 수 있는 능력을 노출하지 않습니다. 하나의 origin에 대해 브라우징 세션 전반에 걸쳐 지속되는 새로운 상태를 도입하지 않습니다. origin이 기본 플랫폼에 데이터를 전송할 수 있도록 허용하지 않습니다. 새로운 스크립트 실행 또는 로딩 메커니즘을 도입하거나 활성화하지 않습니다. origin이 사용자 에이전트의 기본 UI 위에 그릴 수 있도록 허용하지 않습니다. origin이 사용자가 프라이빗 브라우징 모드인지 비프라이빗 브라우징 모드인지 감지할 수 있도록 허용하지 않습니다.
5. 감사의 글
이 명세는 W3C 미디어 작업 그룹의 협업 결과물입니다.에디터들은 본 명세서에 기여한 Alastor Wu, Becca Hughes, Christoph Guttandin, Chris Needham, Chris Pearce, Dale Curtis, Eric Carlson, François Daoust, Frank Liberato, Gary Katsevman, Jean-Yves Avenard, Jer Noble, Mattias Buelens, Mounir Lamouri, Paul Adenot, Tom Jenkinson에게 감사드립니다.