모바일 웹 동영상 재생

François Beaufort
François Beaufort

웹에서 최상의 모바일 미디어 환경을 만들려면 어떻게 해야 할까요? 참 쉽죠? 모두 사용자가 웹상의 미디어에 부여하는 중요성과 사용자 참여도에 따라 달라집니다. 있습니다. 사용자 방문의 이유가 동영상이라면 사용자 경험이 몰입도와 몰입을 가져야 합니다.

모바일 웹 동영상 재생

이 도움말에서는 미디어를 점진적으로 개선하는 방법에 대해 설명합니다. 몰입도를 높일 수 있습니다. 바로 간단한 모바일 플레이어 환경을 빌드하는 이유는 컨트롤, 전체 화면, 백그라운드 재생을 지원합니다. 지금 샘플을 사용해 보고 다음에서 코드를 확인할 수 있습니다

맞춤 컨트롤

<ph type="x-smartling-placeholder">
</ph> HTML 레이아웃 <ph type="x-smartling-placeholder">
</ph> 그림 1.HTML 레이아웃

보시다시피 미디어 플레이어에 사용할 HTML 레이아웃은 매우 간단합니다. <div> 루트 요소에 <video> 미디어 요소와 동영상 컨트롤 전용의 하위 요소 <div>

재생/일시중지 버튼, 전체 화면 등 나중에 다룰 동영상 컨트롤 뒤로 및 앞으로 버튼, 현재 시간의 일부 요소 탐색 시간 및 시간 추적

<div id="videoContainer">
  <video id="video" src="file.mp4"></video>
  <div id="videoControls"></div>
</div>

동영상 메타데이터 읽기

먼저, 동영상 메타데이터가 로드될 때까지 기다렸다가 동영상을 설정합니다. 현재 시간과 진행률 표시줄을 초기화할 수 있습니다. Note that the secondsToTimeCode() 함수는 제가 작성한 커스텀 유틸리티 함수입니다. 초를 'hh:mm:ss'의 문자열로 변환합니다. 더 나은 형식 적합한 모델입니다.

<div id="videoContainer">
  <video id="video" src="file.mp4"></video>
  <div id="videoControls">
    <strong>
      <div id="videoCurrentTime"></div>
      <div id="videoDuration"></div>
      <div id="videoProgressBar"></div>
    </strong>
  </div>
</div>
video.addEventListener('loadedmetadata', function () {
  videoDuration.textContent = secondsToTimeCode(video.duration);
  videoCurrentTime.textContent = secondsToTimeCode(video.currentTime);
  videoProgressBar.style.transform = `scaleX(${
    video.currentTime / video.duration
  })`;
});
드림 <ph type="x-smartling-placeholder">
</ph> 동영상 메타데이터만
그림 2. 동영상 메타데이터를 표시하는 미디어 플레이어
를 통해 개인정보처리방침을 정의할 수 있습니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.

동영상 재생/일시중지

동영상 메타데이터가 로드되었으므로 사용자가 동영상을 볼 수 있도록 허용하는 첫 번째 버튼을 다음에 따라 video.play()video.pause()로 동영상 재생 및 일시중지 있습니다.

<div id="videoContainer">
  <video id="video" src="file.mp4"></video>
  <div id="videoControls">
    <strong><button id="playPauseButton"></button></strong>
    <div id="videoCurrentTime"></div>
    <div id="videoDuration"></div>
    <div id="videoProgressBar"></div>
  </div>
</div>
playPauseButton.addEventListener('click', function (event) {
  event.stopPropagation();
  if (video.paused) {
    video.play();
  } else {
    video.pause();
  }
});
드림

click 이벤트 리스너에서 동영상 컨트롤을 조정하는 대신 playpause 동영상 이벤트. 컨트롤 이벤트를 기반으로 만들면 나중에 Media Session API에 대해 알아보도록 할 수 있으며, 브라우저가 재생에 개입하는 경우 컨트롤을 동기화 상태로 유지합니다. 동영상 재생이 시작되면 버튼 상태를 '일시중지'로 변경 동영상 컨트롤을 숨길 수 있습니다. 동영상이 일시중지되면 버튼 상태를 '재생'으로 변경하면 됩니다. 동영상 컨트롤을 표시합니다.

video.addEventListener('play', function () {
  playPauseButton.classList.add('playing');
});

video.addEventListener('pause', function () {
  playPauseButton.classList.remove('playing');
});

동영상 currentTime 속성에 표시된 시간이 timeupdate 동영상 이벤트에 대한 이벤트입니다. 맞춤 컨트롤이 표시됩니다.

video.addEventListener('timeupdate', function () {
  if (videoControls.classList.contains('visible')) {
    videoCurrentTime.textContent = secondsToTimeCode(video.currentTime);
    videoProgressBar.style.transform = `scaleX(${
      video.currentTime / video.duration
    })`;
  }
});

동영상이 끝나면 버튼 상태를 '재생'으로 변경하고 동영상을 설정합니다. currentTime를 다시 0으로 설정하고 동영상 컨트롤을 표시합니다. 참고로 사용자가 일부 동영상을 사용 설정한 경우 다른 동영상이 자동으로 로드되도록 '자동재생' 기능을 사용하면 기능을 사용할 수 있습니다.

video.addEventListener('ended', function () {
  playPauseButton.classList.remove('playing');
  video.currentTime = 0;
});

앞뒤로 탐색

계속 진행하여 '뒤로 탐색'을 추가해 보겠습니다. '앞으로 탐색' 버튼을 사용하여 사용자가 쉽게 일부 콘텐츠를 건너뛸 수 있습니다

<div id="videoContainer">
  <video id="video" src="file.mp4"></video>
  <div id="videoControls">
    <button id="playPauseButton"></button>
    <strong
      ><button id="seekForwardButton"></button>
      <button id="seekBackwardButton"></button
    ></strong>
    <div id="videoCurrentTime"></div>
    <div id="videoDuration"></div>
    <div id="videoProgressBar"></div>
  </div>
</div>
var skipTime = 10; // Time to skip in seconds

seekForwardButton.addEventListener('click', function (event) {
  event.stopPropagation();
  video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
});

seekBackwardButton.addEventListener('click', function (event) {
  event.stopPropagation();
  video.currentTime = Math.max(video.currentTime - skipTime, 0);
});

이전과 마찬가지로 click 이벤트 리스너에서 동영상 스타일을 조정하는 대신 실행된 seekingseeked 동영상 이벤트를 사용하여 동영상 밝기 조정 맞춤 seeking CSS 클래스는 filter: brightness(0);만큼 간단합니다.

video.addEventListener('seeking', function () {
  video.classList.add('seeking');
});

video.addEventListener('seeked', function () {
  video.classList.remove('seeking');
});

다음은 지금까지 만든 내용입니다. 다음 섹션에서는 전체 화면 버튼을 사용합니다.

전체 화면

여기서는 몇 가지 웹 API를 활용하여 원활한 전체 화면 환경을 제공합니다. 실제 사례를 보려면 sample을 선택합니다.

물론 모든 것을 사용할 필요는 없습니다. 여러분의 삶을 풍요롭게 하는 이를 결합하여 맞춤형 흐름을 만들 수 있습니다.

자동 전체 화면 방지

iOS에서 미디어가 재생되면 video 요소가 자동으로 전체 화면 모드로 전환됩니다. 재생이 시작됩니다 Google에서는 가능한 한 맞춤화하고 제어하기 위해 여러 모바일 브라우저에 미디어 환경을 제공하려면 playsinline video 요소의 속성을 사용하여 iPhone에서 인라인으로 재생되도록 하고 재생이 시작되면 전체 화면 모드로 전환됩니다. 이 작업은 부작용이 없으며 를 사용해야 합니다.

<div id="videoContainer"></div>
  <video id="video" src="file.mp4"></video><strong>playsinline</strong></video>
  <div id="videoControls">...</div>
</div>
드림

버튼 클릭 시 전체 화면 전환

이제 자동 전체 화면이 실행되지 않도록 Fullscreen API를 사용하는 동영상의 전체화면 모드. 사용자가 '전체화면 버튼'을 클릭하고 document.exitFullscreen(): 현재 문서를 참조하세요. 아니면 다음 메서드를 사용하여 동영상 컨테이너에서 전체 화면을 요청합니다. 사용 가능한 경우 requestFullscreen(), 다음 날짜에 webkitEnterFullscreen()로 대체 동영상 요소는 iOS에서만 사용할 수 있습니다.

<div id="videoContainer">
  <video id="video" src="file.mp4"></video>
  <div id="videoControls">
    <button id="playPauseButton"></button>
    <button id="seekForwardButton"></button>
    <button id="seekBackwardButton"></button>
    <strong><button id="fullscreenButton"></button></strong>
    <div id="videoCurrentTime"></div>
    <div id="videoDuration"></div>
    <div id="videoProgressBar"></div>
  </div>
</div>
fullscreenButton.addEventListener('click', function (event) {
  event.stopPropagation();
  if (document.fullscreenElement) {
    document.exitFullscreen();
  } else {
    requestFullscreenVideo();
  }
});

function requestFullscreenVideo() {
  if (videoContainer.requestFullscreen) {
    videoContainer.requestFullscreen();
  } else {
    video.webkitEnterFullscreen();
  }
}

document.addEventListener('fullscreenchange', function () {
  fullscreenButton.classList.toggle('active', document.fullscreenElement);
});

화면 방향 변경 시 전체 화면 전환

사용자가 기기를 가로 모드로 회전할 때 스마트하게 자동으로 전체 화면을 요청하여 몰입도 높은 환경을 제공합니다. 이를 위해 아직 지원되지 않는 Screen Orientation API가 필요합니다. 그 시점에 일부 브라우저에서는 여전히 접두사가 붙어 있습니다. 따라서 이 값은 첫 번째 단계적 개선 작업을 진행했습니다.

작동 방식 화면 방향 변경을 감지하는 즉시 브라우저 창이 가로 모드 (즉, 너비가 높이보다 큼). 그렇지 않으면 전체 화면을 종료합니다. 여기까지입니다.

if ('orientation' in screen) {
  screen.orientation.addEventListener('change', function () {
    // Let's request fullscreen if user switches device in landscape mode.
    if (screen.orientation.type.startsWith('landscape')) {
      requestFullscreenVideo();
    } else if (document.fullscreenElement) {
      document.exitFullscreen();
    }
  });
}
드림

버튼 클릭 시 가로 모드 잠금 화면

동영상을 가로 모드로 더 잘 볼 수 있으므로 화면을 잠그는 것이 좋습니다. 사용자가 '전체화면 버튼'을 클릭하면 가로 방향입니다. 인코더-디코더 아키텍처를 이전에 사용한 Screen Orientation API 및 일부 미디어 쿼리하는 것이 가장 좋습니다.

전화를 거는 것만큼 간단한 가로 모드 화면 잠금 screen.orientation.lock('landscape') 하지만 이 작업은 기기가 matchMedia('(orientation: portrait)') 세로 모드이며 다음 작업을 할 수 있습니다. matchMedia('(max-device-width: 768px)')을(를) 한 손으로 잡으세요. 태블릿 사용자에게는 그다지 좋지 않을 것입니다.

fullscreenButton.addEventListener('click', function (event) {
  event.stopPropagation();
  if (document.fullscreenElement) {
    document.exitFullscreen();
  } else {
    requestFullscreenVideo();
    <strong>lockScreenInLandscape();</strong>;
  }
});
function lockScreenInLandscape() {
  if (!('orientation' in screen)) {
    return;
  }
  // Let's force landscape mode only if device is in portrait mode and can be held in one hand.
  if (
    matchMedia('(orientation: portrait) and (max-device-width: 768px)').matches
  ) {
    screen.orientation.lock('landscape');
  }
}

기기 방향 변경 시 화면 잠금 해제

방금 만든 잠금 화면 환경이 하지만 화면이 잠겼을 때 화면 방향 변경을 수신하지 않기 때문에 완벽합니다.

이 문제를 해결하기 위해 다음과 같은 경우 Device Orientation API를 사용하겠습니다. 있습니다. 이 API는 기기의 사용자 인증 정보를 측정하는 하드웨어에서 우주에서의 위치와 움직임: 자이로스코프와 디지털 나침반 방향, 속도에 대한 가속도계가 있습니다. 기기가 감지되면 방향 변경, 다음 경우에 screen.orientation.unlock()(으)로 화면 잠금 해제 사용자가 기기를 세로 모드로 들고 화면이 가로 모드로 잠겨 있습니다.

function lockScreenInLandscape() {
  if (!('orientation' in screen)) {
    return;
  }
  // Let's force landscape mode only if device is in portrait mode and can be held in one hand.
  if (matchMedia('(orientation: portrait) and (max-device-width: 768px)').matches) {
    screen.orientation.lock('landscape')
    <strong>.then(function() {
      listenToDeviceOrientationChanges();
    })</strong>;
  }
}
function listenToDeviceOrientationChanges() {
  if (!('DeviceOrientationEvent' in window)) {
    return;
  }
  var previousDeviceOrientation, currentDeviceOrientation;
  window.addEventListener(
    'deviceorientation',
    function onDeviceOrientationChange(event) {
      // event.beta represents a front to back motion of the device and
      // event.gamma a left to right motion.
      if (Math.abs(event.gamma) > 10 || Math.abs(event.beta) < 10) {
        previousDeviceOrientation = currentDeviceOrientation;
        currentDeviceOrientation = 'landscape';
        return;
      }
      if (Math.abs(event.gamma) < 10 || Math.abs(event.beta) > 10) {
        previousDeviceOrientation = currentDeviceOrientation;
        // When device is rotated back to portrait, let's unlock screen orientation.
        if (previousDeviceOrientation == 'landscape') {
          screen.orientation.unlock();
          window.removeEventListener(
            'deviceorientation',
            onDeviceOrientationChange,
          );
        }
      }
    },
  );
}

보시다시피, 이것이 우리가 원했던 완벽한 전체 화면 환경입니다. 실제 예를 보려면 샘플을 확인하세요.

백그라운드 재생

웹페이지나 웹페이지에서 동영상이 더 이상 보이지 않는 것을 감지하면 이를 반영하도록 분석을 업데이트하는 것이 좋습니다 또한 다른 트랙을 선택하거나, 일시 중지하거나, 사용자에게 맞춤 버튼을 제공할 수도 있습니다.

페이지 공개 상태 변경 시 동영상 일시중지

Page Visibility API를 사용하면 문서의 현재 공개 상태를 확인할 수 있습니다. 공개 상태 변경에 대한 알림을 받습니다. 아래 코드는 페이지가 있을 때 동영상을 일시중지합니다. 이(가) 숨겨져 있습니다. 화면 잠금이 활성 상태이거나 인스턴스를 만들 수 있습니다

오늘날 대부분의 모바일 브라우저는 브라우저 외부에서 동영상을 재개하려면 사용자가 지정할 수 있습니다.

document.addEventListener('visibilitychange', function () {
  // Pause video when page is hidden.
  if (document.hidden) {
    video.pause();
  }
});
드림

동영상 공개 상태 변경 시 음소거 버튼 표시/숨기기

새로운 Intersection Observer API를 사용하면 훨씬 더 세분화할 수 있습니다. 무료로 이용할 수 있습니다 이 API를 사용하면 관찰된 요소가 변경할 수 있습니다.

페이지의 동영상 공개 상태에 따라 음소거 버튼을 표시하거나 숨겨 보겠습니다. 만약 동영상이 재생 중이지만 현재 보이지 않을 경우 작은 음소거 버튼이 표시됩니다. 페이지 오른쪽 하단 모서리의 버튼을 사용하여 동영상 사운드를 제어할 수 있습니다. 이 volumechange 동영상 이벤트는 음소거 버튼 스타일을 업데이트하는 데 사용됩니다.

<button id="muteButton"></button>
if ('IntersectionObserver' in window) {
  // Show/hide mute button based on video visibility in the page.
  function onIntersection(entries) {
    entries.forEach(function (entry) {
      muteButton.hidden = video.paused || entry.isIntersecting;
    });
  }
  var observer = new IntersectionObserver(onIntersection);
  observer.observe(video);
}

muteButton.addEventListener('click', function () {
  // Mute/unmute video on button click.
  video.muted = !video.muted;
});

video.addEventListener('volumechange', function () {
  muteButton.classList.toggle('active', video.muted);
});

한 번에 하나의 동영상만 재생

한 페이지에 동영상이 두 개 이상인 경우 한 개의 동영상만 재생하는 것이 좋습니다. 사용자가 소리를 들을 필요가 없도록 다른 오디오는 자동으로 일시중지합니다. 여러 오디오 트랙이 동시에 재생되는 경우

// This array should be initialized once all videos have been added.
var videos = Array.from(document.querySelectorAll('video'));

videos.forEach(function (video) {
  video.addEventListener('play', pauseOtherVideosPlaying);
});

function pauseOtherVideosPlaying(event) {
  var videosToPause = videos.filter(function (video) {
    return !video.paused && video != event.target;
  });
  // Pause all other videos currently playing.
  videosToPause.forEach(function (video) {
    video.pause();
  });
}

미디어 알림 맞춤설정

Media Session API를 사용하여 미디어를 맞춤설정할 수도 있습니다. 현재 재생 중인 동영상에 대한 메타데이터를 제공하여 알림을 더 쉽게 설정할 수 있습니다. 또한 를 사용하면 변경사항을 탐색하거나 추적하는 등 미디어 관련 이벤트를 처리할 수 있습니다. 알림이나 미디어 키에서 전송될 수 있습니다 실제 동작을 보려면 샘플을 참조하세요.

웹 앱에서 오디오나 동영상을 재생하는 경우 미디어가 알림이 표시됩니다. Android에서 최고의 성능을 자랑하는 을 사용하여 적절한 정보를 표시할 수 있습니다. 아이콘 이미지를 찾을 수 있습니다.

미디어를 설정하여 이 미디어 알림을 맞춤설정하는 방법을 알아봅시다 제목, 아티스트, 앨범 이름 및 아트워크와 같은 세션 메타데이터를 Media Session API.

playPauseButton.addEventListener('click', function(event) {
  event.stopPropagation();
  if (video.paused) {
    video.play()
    <strong>.then(function() {
      setMediaSession();
    });</strong>
  } else {
    video.pause();
  }
});
function setMediaSession() {
  if (!('mediaSession' in navigator)) {
    return;
  }
  navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Never Gonna Give You Up',
    artist: 'Rick Astley',
    album: 'Whenever You Need Somebody',
    artwork: [
      {src: 'https://dummyimage.com/96x96', sizes: '96x96', type: 'image/png'},
      {
        src: 'https://dummyimage.com/128x128',
        sizes: '128x128',
        type: 'image/png',
      },
      {
        src: 'https://dummyimage.com/192x192',
        sizes: '192x192',
        type: 'image/png',
      },
      {
        src: 'https://dummyimage.com/256x256',
        sizes: '256x256',
        type: 'image/png',
      },
      {
        src: 'https://dummyimage.com/384x384',
        sizes: '384x384',
        type: 'image/png',
      },
      {
        src: 'https://dummyimage.com/512x512',
        sizes: '512x512',
        type: 'image/png',
      },
    ],
  });
}

재생이 끝나면 손을 떼지 않아도 됩니다. 미디어 세션을 알림이 자동으로 사라집니다. 한 가지 최신 기능이 재생이 시작되면 navigator.mediaSession.metadata가 사용됩니다. 이 그렇기 때문에 관련성 높은 사용자에게 항상 관련성 높은 광고가 표시되도록 미디어 알림의 정보가 표시됩니다.

웹 앱에서 재생목록을 제공하는 경우 사용자가 "이전 노래"와 함께 미디어 알림에서 재생목록을 Track' '다음 트랙'을 선택하겠습니다. 있습니다.

if ('mediaSession' in navigator) {
  navigator.mediaSession.setActionHandler('previoustrack', function () {
    // User clicked "Previous Track" media notification icon.
    playPreviousVideo(); // load and play previous video
  });
  navigator.mediaSession.setActionHandler('nexttrack', function () {
    // User clicked "Next Track" media notification icon.
    playNextVideo(); // load and play next video
  });
}

미디어 작업 핸들러는 유지됩니다. 이것은 이 이벤트가 단, 이벤트 처리는 브라우저가 중지되고 기본 동작을 수행하고 이를 웹 앱이 미디어 작업을 지원합니다. 따라서 미디어 작업 컨트롤은 적절한 작업 핸들러를 설정해야 합니다.

미디어 작업 핸들러를 설정 해제하려면 null에 할당하는 것만큼 간단합니다.

Media Session API를 사용하면 '뒤로 탐색'을 표시할 수 있습니다. '앞으로 탐색' 건너뛸 시간을 제어하려면 미디어 알림 아이콘을 클릭합니다.

if ('mediaSession' in navigator) {
  let skipTime = 10; // Time to skip in seconds

  navigator.mediaSession.setActionHandler('seekbackward', function () {
    // User clicked "Seek Backward" media notification icon.
    video.currentTime = Math.max(video.currentTime - skipTime, 0);
  });
  navigator.mediaSession.setActionHandler('seekforward', function () {
    // User clicked "Seek Forward" media notification icon.
    video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
  });
}

'재생/일시중지' 아이콘이 항상 미디어 알림과 관련 이벤트는 브라우저에서 자동으로 처리합니다. 어떤 이유로든 기본값이 작동하지 않는 경우 '재생'을 처리하고 '일시중지'를 선택합니다. 미디어 이벤트를 사용하세요.

Media Session API의 멋진 점은 알림 트레이가 미디어 메타데이터와 컨트롤이 표시되는 유일한 위치입니다. 미디어 알림이 페어링된 웨어러블 기기에 자동으로 동기화됩니다. 또한 잠금 화면에 표시됩니다.

의견