Web Sender 앱에 Cast SDK 통합

이 개발자 가이드에서는 Cast SDK를 사용하여 Web Sender 앱에 Google Cast 지원을 추가하는 방법을 설명합니다.

용어

휴대기기나 브라우저는 재생을 제어하는 송신자이고, Google Cast 기기는 재생을 위해 화면에 콘텐츠를 표시하는 수신기입니다.

Web Sender SDK는 Framework API(cast.framework)와 Base API(chrome.cast)의 두 부분으로 구성됩니다. 일반적으로 더 간단한 상위 수준의 Framework API를 호출한 다음 하위 수준의 Base API에서 처리합니다.

발신자 프레임워크는 하위 수준 기능의 래퍼를 제공하는 프레임워크 API, 모듈, 관련 리소스를 의미합니다. 발신자 앱 또는 Google Cast Chrome 앱은 발신기 기기의 Chrome 브라우저 내에서 실행되는 웹 (HTML/JavaScript) 앱을 의미합니다. 웹 수신기 앱은 Chromecast 또는 Google Cast 기기에서 실행되는 HTML/JavaScript 앱을 의미합니다.

발신자 프레임워크는 비동기 콜백 설계를 사용하여 발신자 앱에 이벤트를 알리고 Cast 앱 수명 주기의 다양한 상태 간에 전환합니다.

라이브러리 로드

앱에서 Google Cast의 기능을 구현하려면 아래와 같이 Google Cast Web Sender SDK의 위치를 알아야 합니다. loadCastFramework URL 쿼리 매개변수를 추가하여 Web Sender Framework API도 로드합니다. 앱의 모든 페이지는 다음과 같이 라이브러리를 참조해야 합니다.

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

프레임워크

Web Sender SDK는 cast.framework.* 네임스페이스를 사용합니다. 네임스페이스는 다음을 나타냅니다.

  • API에서 작업을 호출하는 메서드 또는 함수
  • API의 리스너 함수용 이벤트 리스너

프레임워크는 다음과 같은 주요 구성요소로 구성됩니다.

  • CastContext는 현재 전송 상태에 관한 정보를 제공하고 전송 상태 및 Cast 세션 상태 변경 이벤트를 트리거하는 싱글톤 객체입니다.
  • CastSession 객체는 세션을 관리하며 상태 정보를 제공하고 기기 볼륨 변경, 음소거 상태, 앱 메타데이터와 같은 이벤트를 트리거합니다.
  • 전송 버튼 요소: HTML 버튼을 확장하는 간단한 HTML 맞춤 요소 제공된 전송 버튼이 충분하지 않으면 전송 상태를 사용하여 전송 버튼을 구현할 수 있습니다.
  • RemotePlayerController는 데이터 결합을 제공하여 원격 플레이어의 구현을 단순화합니다.

네임스페이스에 관한 자세한 설명은 Google Cast Web Sender API 참조를 확인하세요.

전송 버튼

앱의 전송 버튼 구성요소는 전적으로 프레임워크에 의해 처리됩니다. 여기에는 공개 상태 관리 및 클릭 이벤트 처리가 포함됩니다.

<google-cast-launcher></google-cast-launcher>

또는 프로그래매틱 방식으로 버튼을 만들 수도 있습니다.

document.createElement("google-cast-launcher");

필요에 따라 크기 또는 위치와 같은 추가 스타일을 요소에 적용할 수 있습니다. --connected-color 속성을 사용하여 연결된 웹 수신기 상태의 색상을 선택하고 연결 해제 상태의 색상을 --disconnected-color로 선택합니다.

초기화

프레임워크 API를 로드한 후 앱은 핸들러 window.__onGCastApiAvailable를 호출합니다. 발신자 라이브러리를 로드하기 전에 앱이 window에서 이 핸들러를 설정하는지 확인해야 합니다.

이 핸들러 내에서 CastContextsetOptions(options) 메서드를 호출하여 전송 상호작용을 초기화합니다.

예를 들면 다음과 같습니다.

<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    initializeCastApi();
  }
};
</script>

그런 다음 API를 다음과 같이 초기화합니다.

initializeCastApi = function() {
  cast.framework.CastContext.getInstance().setOptions({
    receiverApplicationId: applicationId,
    autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
  });
};

먼저 앱은 프레임워크에서 제공하는 CastContext 객체의 싱글톤 인스턴스를 검색합니다. 그런 다음 CastOptions 객체를 사용하는 setOptions(options)를 사용하여 applicationID를 설정합니다.

등록이 필요 없는 기본 미디어 수신기를 사용하는 경우 applicationID 대신 아래와 같이 Web Sender SDK에서 사전 정의한 상수를 사용합니다.

cast.framework.CastContext.getInstance().setOptions({
  receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});

미디어 제어

CastContext가 초기화되고 나면 앱은 getCurrentSession()을 사용하여 언제든지 현재 CastSession를 가져올 수 있습니다.

var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

CastSessionloadMedia(loadRequest)를 통해 연결된 Cast 기기에 미디어를 로드하는 데 사용할 수 있습니다. 먼저 contentId, contentType, 콘텐츠와 관련된 기타 정보를 사용하여 MediaInfo를 만듭니다. 그런 다음 여기서 LoadRequest를 만들고 요청과 관련된 모든 정보를 설정합니다. 마지막으로 CastSession에서 loadMedia(loadRequest)를 호출합니다.

var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  function() { console.log('Load succeed'); },
  function(errorCode) { console.log('Error code: ' + errorCode); });

loadMedia 메서드는 성공적인 결과를 얻는 데 필요한 작업을 수행하는 데 사용할 수 있는 프로미스를 반환합니다. 프로미스가 거부되면 함수 인수는 chrome.cast.ErrorCode이 됩니다.

RemotePlayer에서 플레이어 상태 변수에 액세스할 수 있습니다. 미디어 이벤트 콜백 및 명령어를 비롯하여 RemotePlayer와의 모든 상호작용은 RemotePlayerController로 처리됩니다.

var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);

RemotePlayerController는 로드된 미디어의 재생, 일시중지, 중지, 탐색에 관한 전체 미디어 제어 권한을 앱에 제공합니다.

  • 재생/일시중지: playerController.playOrPause();
  • 중지: playerController.stop();
  • 탐색: playerController.seek();

RemotePlayerRemotePlayerController는 Polymer 또는 Angular와 같은 데이터 결합 프레임워크와 함께 사용하여 원격 플레이어를 구현할 수 있습니다.

다음은 Angular의 코드 스니펫입니다.

<button id="playPauseButton" class="playerButton"
  ng-disabled="!player.canPause"
  ng-click="controller.playOrPause()">
    {{player.isPaused ? 'Play' : 'Pause'}}
</button>
<script>
var player = new cast.framework.RemotePlayer();
var controller = new cast.framework.RemotePlayerController(player);
// Listen to any player update, and trigger angular data binding
update.controller.addEventListener(
  cast.framework.RemotePlayerEventType.ANY_CHANGE,
  function(event) {
    if (!$scope.$$phase) $scope.$apply();
  });
</script>

미디어 상태

미디어 재생 중에 다양한 이벤트가 발생합니다. 이러한 이벤트는 RemotePlayerController 객체에서 다양한 cast.framework.RemotePlayerEventType 이벤트의 리스너를 설정하여 캡처할 수 있습니다.

미디어 상태 정보를 가져오려면 재생이 변경될 때와 CastSession.getMediaSession().media가 변경될 때 트리거되는 cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED 이벤트를 사용합니다.

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    // Use the current session to get an up to date media status.
    let session = cast.framework.CastContext.getInstance().getCurrentSession();

    if (!session) {
        return;
    }

    // Contains information about the playing media including currentTime.
    let mediaStatus = session.getMediaSession();
    if (!mediaStatus) {
        return;
    }

    // mediaStatus also contains the mediaInfo containing metadata and other
    // information about the in progress content.
    let mediaInfo = mediaStatus.media;
  });

일시중지, 재생, 다시 시작, 탐색과 같은 이벤트가 발생하면 앱은 이러한 이벤트에 조치를 취하고 자체 및 Cast 기기의 웹 수신기 앱 간에 동기화해야 합니다. 자세한 내용은 상태 업데이트를 참고하세요.

세션 관리 작동 방식

Cast SDK에는 전송 세션이라는 개념이 도입되며, 이 설정에는 기기 연결, 웹 수신기 앱 실행 (또는 결합), 앱에 연결, 미디어 제어 채널 초기화 단계가 결합되어 있습니다. 전송 세션 및 웹 수신기 수명 주기에 관한 자세한 내용은 웹 수신기 애플리케이션 수명 주기 가이드를 참고하세요.

세션은 앱이 cast.framework.CastContext.getInstance()를 통해 검색할 수 있는 CastContext 클래스에 의해 관리됩니다. 개별 세션은 Session 클래스의 서브클래스로 표현됩니다. 예를 들어 CastSession는 Cast 기기가 있는 세션을 나타냅니다. 앱은 CastContext.getCurrentSession()를 통해 현재 활성 상태인 전송 세션에 액세스할 수 있습니다.

세션 상태를 모니터링하려면 CastContextEventType.SESSION_STATE_CHANGED 이벤트 유형의 CastContext에 리스너를 추가합니다.

var context = cast.framework.CastContext.getInstance();
context.addEventListener(
  cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
  function(event) {
    switch (event.sessionState) {
      case cast.framework.SessionState.SESSION_STARTED:
      case cast.framework.SessionState.SESSION_RESUMED:
        break;
      case cast.framework.SessionState.SESSION_ENDED:
        console.log('CastContext: CastSession disconnected');
        // Update locally as necessary
        break;
    }
  })

연결 해제의 경우(예: 사용자가 전송 대화상자에서 '전송 중지' 버튼을 클릭하는 경우) 리스너에 RemotePlayerEventType.IS_CONNECTED_CHANGED 이벤트 유형의 리스너를 추가할 수 있습니다. 리스너에서 RemotePlayer의 연결이 끊어졌는지 확인합니다. 이 경우 필요에 따라 로컬 플레이어 상태를 업데이트합니다. 예를 들면 다음과 같습니다.

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
    if (!player.isConnected) {
      console.log('RemotePlayerController: Player disconnected');
      // Update local player to disconnected state
    }
  });

사용자가 프레임워크 전송 버튼을 통해 Cast 종료를 직접 제어할 수 있지만 발신자 자체는 현재 CastSession 객체를 사용하여 전송을 중지할 수 있습니다.

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that Web Receiver app should be stopped.
  castSession.endSession(true);
}

스트림 이전

세션 상태는 사용자가 음성 명령, Google Home 앱 또는 스마트 디스플레이를 사용하여 기기 간에 기존 오디오 및 동영상 스트림을 이동할 수 있는 스트림 전송의 기반입니다. 미디어가 한 기기 (소스)에서 재생을 중지하고 다른 기기 (대상)에서 계속됩니다. 최신 펌웨어가 설치된 모든 Cast 기기가 스트림 전송의 소스 또는 대상 역할을 할 수 있습니다.

스트림 전송 중에 새 대상 기기를 가져오려면 cast.framework.SessionState.SESSION_RESUMED 이벤트가 호출될 때 CastSession#getCastDevice()를 호출합니다.

자세한 내용은 웹 수신기의 스트림 전송을 참고하세요.