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를 처리합니다.

발신자 프레임워크는 하위 수준 기능의 래퍼를 제공하는 프레임워크 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는 현재 전송 상태에 관한 정보를 제공하고 전송 상태 및 전송 세션 상태 변경에 관한 이벤트를 트리거하는 싱글톤 객체입니다.
  • 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) 메서드를 호출하여 Cast 상호작용을 초기화합니다.

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

<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는 로드된 미디어의 PLAY, PAUSE, STOP, SEEK의 전체 미디어 제어 권한을 앱에 부여합니다.

  • 재생/일시중지: 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 세션의 개념을 도입합니다. Cast 세션 및 웹 수신기 수명 주기에 관한 자세한 내용은 웹 수신기 애플리케이션 수명 주기 가이드를 참고하세요.

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

세션 상태를 모니터링하려면 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()를 호출합니다.

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