웹 프론트엔드/동영상 Video

[번역] iOS를 위한 새로운 <video> 정책

아로리(arori) 2019. 9. 9. 15:53
반응형

원문: New <video> Policies for iOS

 
 

New

 

Since before your sun burned hot in space and before your race was born, Safari on iOS has required a user gesture to play media in a

webkit.org


우주에 당신의 태양이 불타기 전부터, 당신의 민족이 태어나기 전부터 (Since before your sun burned hot in space and before your race was born), iOS의 Safari는 <video> 혹은 <audio> 요소의 미디어를 재생하기 위해서는 사용자 제스처가 필요했습니다.

Safari가 iPhoneOS 3 에서 <video>를 처음 지원했을 때, 미디어 데이터는 사용자가 페이지와 인터렉션할 때만 로드 되었습니다. 그러나 미디어 재생에 대한 더 많은 제어권을 웹 개발자에게 돌려주겠다는 목표로, iOS8에서 이러한 제한을 완화했습니다. Safari는 preload="metadata" 속성을 인정하기 시작하여 <video><audio> 요소가 미디어의 크기, 재생 시간, 사용 가능한 트랙을 결정하기에 충분한 미디어 데이터를 로딩할 수 있도록 허용했습니다. iOS 10 Safari의 경우, 무음 <video>요소에 대한 유저 제스처 요구 사항이 완화되었습니다.

동기 부여 Motivation

요즘 사람들은 GIF를 정말 좋아한다는 것이 밝혀졌습니다. 그러나 GIF 포맷은 H.264와 같은 최신 비디오 코덱과 비교했을 때, 애니메이션 이미지를 인코딩하는 매우 비싼 방법으로 밝혀졌습니다. 우리는 GIF가 대역폭에서 최대 12배, 에너지 사용해서 2배까지 비쌀 수 있다는 것을 발견했습니다. 너무 많은 비용이 들기 때문에 가장 큰 GIF 제공 업체 중의 다수가 GIF에서 <video> 요소로 이동했습니다. 이러한 GIF의 대부분은 비디오 클립으로 삶을 시작해서, 애니메이션 GIF로 변환되었다가, 다시 비디오 클립으로 변환되었습니다. 때문에 여러분은 원처럼 빙글빙글 돈다고 말할 수도 있습니다.

그러나 이러한 움직임은 사용자의 배터리를 절약할 뿐 아니라, 웹사이트의 대역 폭 비용을 절약하지만, 사용성에 비용이 생깁니다. iOS9에서는 <video> 는 사용자의 제스처의 결과로만 재생을 시작합니다. 따라서 <img><video>로 바꾼 페이지는 애니메이션 컨텐츠를 표시하기 전에 사용자 제스처가 필요하고, iPhone에서는 <video>가 재생을 시작할 때 전체 화면으로 들어갑니다.

사용자 제스처 요구 사항에 대한 참고 사항: 예를 들어, 액션이 "사용자 동작의 결과로" 발생해야 한다고 말하는 것은 video.play()를 호출하는 JavaScript는 touchend, click, doubleclick, keydown이벤트의 핸들러로부터 직접 발생해야함을 의미합니다. 즉, button.addEventListner('click', () => { video.play(); })는 사용자 제스처 요구사항을 충족합니다. video.addEventListener('canplaythrought', () => { video.play(); } )는 그렇지 않습니다.

마찬가지로, 웹 개발자는 <video> 요소를 자신의 페이지를 표현하는 요소로서 통합하는(자연스럽게 녹아 들게 하기 위해) 상당히 놀라운 일을 하고 있습니다. 그리고 이 페이지는 사용자 제스처 요구 사항으로 인해 iOS에서 전혀 작동하지 않거나, 혹은 <video>요소가 애니메이션 배경 이미지를 전체 화면으로 재생하여 페이지의 표현을 완전히 가리게 합니다.

Webkit의 새로운 비디오 정책 WebKit’s New policies for video

iOS 10에서 시작하여, WebKit은 이러한 표현을 가능하게 하기 위해 인라인 및 자동 재생을 완화하려고 하지만, 여전히 사이트의 대역폭과 사용자의 배터리를 염두에 두고 있습니다.

기본적으로 WebKit에는 다음과 같은 정책이 있습니다.

  • <video autoplay> 요소는 다음과 같은 조건을 충족하는 요소에 대해 autoplay 속성을 인정합니다.
    • <video> 요소는 소스 미디어에 오디오 트랙이 없는 경우에 사용자 제스처 없이 autoplay를 허용합니다.
    • <video muted> 요소는 사용자 제스처 없이 자동 재생될 수 있습니다.
    • <video> 요소가 사용자의 제스처 없이 오디오 트랙을 얻거나, 음소거를 해제하면 재생이 일시 정지됩니다.
    • <video autoplay> 요소는 스크롤해서 뷰포트에 노출되고, CSS를 통해 보이고(visible 하고), DOM에 삽입 되어 있을 때와 같이 스크린에서 볼 수 있을 때만 재생을 시작합니다.
    • <video autoplay> 요소는 뷰포트 밖으로 스크롤 되는 등, 보이지 않는 경우에는 일시 중지됩니다.
  • <video> 요소는 다음과 같은 조건을 충족하는 요소에 대해 play() 메소드를 인정합니다.
    • <video> 요소는 소스 미디어에 오디오 트랙이 없거나 muted 속성이 true로 설정 된 경우 사용자 동작 없이 play()를 허용합니다.
    • <video> 요소는 사용자의 제스처 없이 오디오 트랙을 얻거나, 음소거를 해제하면 재생이 일시 정지됩니다.
    • <video> 요소는 화면에 표시되지 않거나, 뷰포트 외부에 있을 때 play() 를 허용하지 않습니다.
    • video.play()Promise를 반환하며, 이러한 조건 중 하나라도 충족되지 않으면 거부됩니다.
  • 아이폰에서 <video playsinline> 요소는 이제 인라인으로 재생할 수 있으며, 재생이 시작될 때 자동으로 전체화면 모드로 들어가지 않습니다.
    <video> 요소에 playsinline 속성이 없이 iPhone에서 재생하려면 전체 화면 모드가 계속 필요합니다.
    핀치 제스처로 전체 화면을 종료하면, <video> 요소는 playsinline 없이 인라인으로 계속 재생됩니다.

iOS의 WebKit 프레임워크 클라이언트의 경우, API를 통해 이러한 정책을 계속 제어할 수 있으며, 기존 API를 사용하여 이러한 정책을 제어하는 클라이언트는 변경되지 않습니다. 자동 재생 정책을 보다 세밀하게 제어하려면 새로운 WKWebViewConfiguration 속성mediaTypesRequiringUserActionForPlayback을 참고하세요. iOS 10의 Safari는 WebKit의 기본 정책을 사용합니다.

<playsinline 속성에 대한 참고 사항: 이 속성은 HTML 명세에 최근에 추가되었으며, WebKit은 기존의 webkit-playsinline 속성의 prefix를 제거하여 이 새로운 속성을 채택했습니다. 이 레거시 속성은 iPhoneOS 4.0부터 지원되었으며, 업데이트된 prefix를 제거한 정책에 따라 webkit-playsinline을 접두사(prefix) 없이 사용할 수 있어서 기쁩니다. 불행히도 이 변경사항이 iOS 10 Developer Seed 2에 적용되지 않았습니다. 만약 iOS Developmetn Seed 2에서 새로운 정책을 경험하고 싶다면, 접두사를 넣은 속성이 작동할 것입니다. 하지만 우리는 향후 Seed에서 지원할 때, 접두사를 제거한 속성으로 변경할 것을 권장합니다.

예제 Examples

그럼 괜찮은 웹 개발자는 이러한 새로운 정책을 어떻게 활용할 수 있을까요? 어떤 개발자가 많은 GIF를 가진 블로그 포스트나 기사가 있는데 <video> 요소로 사용하기를 원한다고 가정해봅시다. 다음은 간단한 GIF 대체의 예제입니다:

<video autoplay loop muted playsinline>
  <source src="image.mp4">
  <source src="image.webm" onerror="fallback(parentNode)">
  <img src="image.gif">
</video>
function fallback(video)
{
  var img = video.querySelector('img');
  if (img)
    video.parentNode.replaceChild(img, video);
}

iOS 10 에서 <video>의 소스(source)가 지원되지 않는 경우, GIF에 대한 멋진 폴백(fallback)을 제공하여 GIF를 직접 사용하여 똑같은 유저 경험을 제공합니다. 사실 이 코드는 당신에게 그 멋진 GIF를 보여주는데 사용된 것입니다.

만약 인라인 재생(playback)이 허용되면서, 전체 화면 플레이가 필요한 경우와 같이 페이지 디자인에서 다른 동작이 필요한 경우, 두가지를 구별하기 위해 미디어 쿼리에 -webkit-video-playable-inline을 사용합니다.

<div id="either-gif-or-video">
  <video src="image.mp4" autoplay loop muted playsinline></video>
  <img src="image.gif">
</div>
#either-gif-or-video video { display: none; }
@media (-webkit-video-playable-inline) {
    #either-gif-or-video img { display: none; }
    #either-gif-or-video video { display: initial; }
}

이러한 새로운 정책은 <video>를 전체 화면 모드로 전환하지 않고, <video> 재생을 <canvas>에 페인팅하는 것과 같이 <video> 요소를 보다 고급으로 사용할 수 있는 것이 이제 가능하다는 것을 의미합니다.

var video;
var canvas;

function startPlayback()
{
  if (!video) {
    video = document.createElement('video');
    video.src = 'image.mp4';
    video.loop = true;
    video.addEventListener('playing', paintVideo);
  }
  video.play();
}

function paintVideo()
{
  if (!canvas) {
    canvas = document.createElement('canvas');
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    document.body.appendChild(canvas);
  }
  canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
  if (!video.paused)
    requestAnimationFrame(paintVideo);
}
<button onclick="startPlayback()">Start Playback</button>

동일한 기술을 사용해서 WebGL 컨텍스트로 렌더링할 수 있습니다. 이 예제에서는 <video> 요소가 DOM에 없어 볼 수 없으므로(not visible), click과 같은 사용자 제스처가 필요합니다.

이러한 새로운 정책으로 인해 사용자에게 대역폭이나 배터리에 부담을 주지 않으면서 현대적이고 매력적인 웹사이트를 디자인할 때 비디오가 매우 유용한 도구가 될 것이라고 생각합니다. 자세한 내용은, 작성자(@jernoble)나, 애플 웹 기술 에반젤리스트 Jonathan Davis(@jonathandavis), 혹은 WebKit 팀(@WebKit)에게 문의해주세요.


이럴수가... 포스트 타이틀에 video태그가 들어있어서 그런가 링크가 깨진다

반응형