ผสานรวม SDK ของ Cast ลงในแอป Web Sender

คู่มือนักพัฒนาซอฟต์แวร์นี้อธิบายวิธีเพิ่มการรองรับ Google Cast ลงในแอป Web Sender โดยใช้ Cast SDK

คำศัพท์

อุปกรณ์เคลื่อนที่หรือเบราว์เซอร์คือผู้ส่งซึ่งควบคุมการเล่น ส่วนอุปกรณ์ Google Cast คือผู้รับซึ่งแสดงเนื้อหาบนหน้าจอเพื่อเล่น

Web Sender SDK ประกอบด้วย 2 ส่วน ได้แก่ Framework API (cast.framework) และ Base API (chrome.cast) โดยทั่วไป คุณจะเรียกใช้ Framework API ระดับสูงที่ง่ายกว่า ซึ่งจะประมวลผลโดย Base API ระดับต่ำกว่า

เฟรมเวิร์กผู้ส่งหมายถึง Framework API, โมดูล และทรัพยากรที่เกี่ยวข้องซึ่งมี Wrapper สำหรับฟังก์ชันการทำงานระดับต่ำกว่า แอปผู้ส่งหรือแอป Google Cast สำหรับ Chrome หมายถึงแอปบนเว็บ (HTML/JavaScript) ที่ทำงานภายในเบราว์เซอร์ Chrome บนอุปกรณ์ผู้ส่ง แอป Web Receiver หมายถึงแอป HTML/JavaScript ที่ทำงานบน Chromecast หรืออุปกรณ์ Google Cast

เฟรมเวิร์กผู้ส่งใช้การออกแบบ Callback แบบอะซิงโครนัสเพื่อแจ้งแอปผู้ส่งเกี่ยวกับเหตุการณ์และเปลี่ยนสถานะต่างๆ ของวงจรแอป Cast

โหลดไลบรารี

เพื่อให้แอปใช้ฟีเจอร์ของ Google Cast ได้ แอปจะต้องทราบตำแหน่งของ Google Cast Web Sender SDK ดังที่แสดงด้านล่าง เพิ่มพารามิเตอร์การค้นหา URL loadCastFramework เพื่อโหลด 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
  • Listener เหตุการณ์สำหรับฟังก์ชัน Listener ใน API

เฟรมเวิร์กประกอบด้วยองค์ประกอบหลักต่อไปนี้

  • CastContext เป็นออบเจ็กต์ Singleton ที่ให้ข้อมูลเกี่ยวกับสถานะปัจจุบันของ Cast และทริกเกอร์เหตุการณ์สำหรับการเปลี่ยนแปลงสถานะ Cast และสถานะเซสชัน Cast
  • ออบเจ็กต์ CastSession จะจัดการเซสชัน โดยจะให้ข้อมูลสถานะและทริกเกอร์เหตุการณ์ เช่น การเปลี่ยนแปลงระดับเสียงของอุปกรณ์ สถานะการปิดเสียง และข้อมูลเมตาของแอป
  • องค์ประกอบปุ่มแคสต์ ซึ่งเป็นองค์ประกอบ HTML ที่กำหนดเองแบบง่ายที่ขยายปุ่ม HTML หากปุ่มแคสต์ที่ให้มาไม่เพียงพอ คุณสามารถใช้สถานะ Cast เพื่อใช้ปุ่มแคสต์ได้
  • RemotePlayerController ให้การเชื่อมโยงข้อมูลเพื่อลดความซับซ้อนในการติดตั้งใช้งานเพลเยอร์ระยะไกล

ดูคำอธิบายทั้งหมดของเนมสเปซได้ที่เอกสารอ้างอิง Google Cast Web Sender API

ปุ่ม "แคสต์"

คอมโพเนนต์ปุ่มแคสต์ในแอปจะได้รับการจัดการโดยเฟรมเวิร์กทั้งหมด ซึ่งรวมถึงการจัดการระดับการเข้าถึงและการจัดการกิจกรรมการคลิก

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

หรือจะสร้างปุ่มแบบเป็นโปรแกรมก็ได้ ดังนี้

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

คุณสามารถใช้การจัดรูปแบบเพิ่มเติม เช่น ขนาดหรือการจัดตำแหน่ง กับองค์ประกอบได้ตามความจำเป็น ใช้แอตทริบิวต์ --connected-color เพื่อเลือกสีสำหรับสถานะ Web Receiver ที่เชื่อมต่อ และ --disconnected-color สำหรับสถานะที่ไม่ได้เชื่อมต่อ

การเริ่มต้น

หลังจากโหลด API ของเฟรมเวิร์กแล้ว แอปจะเรียกใช้แฮนเดิล window.__onGCastApiAvailable คุณควรตรวจสอบว่าแอปตั้งค่าแฮนเดิลนี้ใน window ก่อนโหลดไลบรารีผู้ส่ง

ภายในแฮนเดิลนี้ คุณจะเริ่มต้นการโต้ตอบของ Cast โดยเรียกใช้เมธอด setOptions(options) ของ CastContext

เช่น

<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
  });
};

ก่อนอื่น แอปจะดึงข้อมูลอินสแตนซ์ Singleton ของออบเจ็กต์ CastContext ที่เฟรมเวิร์กมีให้ จากนั้นจะใช้ setOptions(options) โดยใช้ออบเจ็กต์ CastOptions เพื่อตั้งค่า applicationID

หากใช้ตัวรับสื่อเริ่มต้นซึ่งไม่จำเป็นต้องลงทะเบียน คุณจะใช้ค่าคงที่ที่กำหนดไว้ล่วงหน้าโดย Web Sender SDK ดังที่แสดงด้านล่างแทน applicationID

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

ตัวควบคุมสื่อ

เมื่อเริ่มต้น CastContext แล้ว แอปจะดึงข้อมูล CastSession ปัจจุบันได้ทุกเมื่อโดยใช้ getCurrentSession()

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

คุณสามารถใช้ CastSession เพื่อโหลดสื่อไปยังอุปกรณ์แคสต์ที่เชื่อมต่อโดยใช้ loadMedia(loadRequest) ขั้นแรก ให้สร้าง MediaInfo โดยใช้ contentId และ contentType รวมถึงข้อมูลอื่นๆ ที่เกี่ยวข้องกับเนื้อหา จากนั้นสร้าง LoadRequest จากออบเจ็กต์ดังกล่าว โดยตั้งค่าข้อมูลที่เกี่ยวข้องทั้งหมดสำหรับคำขอ สุดท้าย ให้เรียก loadMedia(loadRequest) ใน CastSession

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 จะส่งกลับ Promise ที่สามารถใช้เพื่อดำเนินการที่จำเป็นเพื่อให้ได้ผลลัพธ์ที่สำเร็จ หาก Promise ถูกปฏิเสธ อาร์กิวเมนต์ของฟังก์ชันจะเป็น chrome.cast.ErrorCode

คุณเข้าถึงตัวแปรสถานะโปรแกรมเล่นได้ใน RemotePlayer การโต้ตอบทั้งหมดกับ RemotePlayer ซึ่งรวมถึงคอลแบ็กและคำสั่งเหตุการณ์สื่อจะได้รับการจัดการด้วย RemotePlayerController

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

RemotePlayerController ช่วยให้แอปควบคุมสื่อได้อย่างเต็มรูปแบบ ไม่ว่าจะเป็นการเล่น หยุดชั่วคราว หยุด และกรอสำหรับสื่อที่โหลด

  • เล่น/หยุดชั่วคราว: playerController.playOrPause();
  • STOP: playerController.stop();
  • กรอ: playerController.seek();

RemotePlayer และ RemotePlayerController สามารถใช้กับเฟรมเวิร์กการเชื่อมโยงข้อมูล เช่น 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>

สถานะสื่อ

ระหว่างการเล่นสื่อ เหตุการณ์ต่างๆ จะเกิดขึ้นซึ่งสามารถบันทึกได้โดยการตั้งค่า Listener สำหรับเหตุการณ์ cast.framework.RemotePlayerEventType ต่างๆ ในออบเจ็กต์ RemotePlayerController

หากต้องการดูข้อมูลสถานะสื่อ ให้ใช้เหตุการณ์ cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED ซึ่งจะทริกเกอร์เมื่อการเล่นเปลี่ยนแปลงและเมื่อ CastSession.getMediaSession().media เปลี่ยนแปลง

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;
  });

เมื่อเกิดเหตุการณ์ต่างๆ เช่น หยุดชั่วคราว เล่น เล่นต่อ หรือกรอ แอปจะต้องดำเนินการกับเหตุการณ์เหล่านั้นและซิงค์ระหว่างตัวแอปเองกับแอป Web Receiver ในอุปกรณ์แคสต์ ดูข้อมูลเพิ่มเติมได้ที่การอัปเดตสถานะ

วิธีการทำงานของการจัดการเซสชัน

Cast SDK นำเสนอแนวคิดของเซสชันการแคสต์ ซึ่งเป็นการสร้างที่รวมขั้นตอนการเชื่อมต่อกับอุปกรณ์ การเปิด (หรือเข้าร่วม) แอป Web Receiver การเชื่อมต่อกับแอปนั้น และการเริ่มต้นช่องทางตัวควบคุมสื่อ ดูข้อมูลเพิ่มเติมเกี่ยวกับเซสชันการแคสต์และวงจรของ Web Receiver ได้ที่คู่มือวงจรของแอปพลิเคชัน Web Receiver

เซสชันจะได้รับการจัดการโดยคลาส CastContext ซึ่งแอปของคุณสามารถดึงข้อมูลผ่าน cast.framework.CastContext.getInstance() ได้ เซสชันแต่ละรายการจะแสดงโดยคลาสย่อยของคลาส Session เช่น CastSession แสดงเซสชันที่มีอุปกรณ์แคสต์ แอปของคุณสามารถเข้าถึงเซสชันการแคสต์ที่ใช้งานอยู่ในปัจจุบันผ่าน CastContext.getCurrentSession()

หากต้องการตรวจสอบสถานะเซสชัน ให้เพิ่ม Listener ลงใน CastContext สำหรับประเภทเหตุการณ์ CastContextEventType.SESSION_STATE_CHANGED

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;
    }
  })

สำหรับการยกเลิกการเชื่อมต่อ เช่น เมื่อผู้ใช้คลิกปุ่ม "หยุดแคสต์" จากกล่องโต้ตอบการแคสต์ คุณสามารถเพิ่ม Listener สำหรับประเภทเหตุการณ์ RemotePlayerEventType.IS_CONNECTED_CHANGED ใน Listener ได้ ใน Listener ให้ตรวจสอบว่า RemotePlayer ถูกยกเลิกการเชื่อมต่อหรือไม่ หากเป็นเช่นนั้น ให้อัปเดตสถานะเพลเยอร์ในเครื่องตามความจำเป็น เช่น

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

แม้ว่าผู้ใช้จะควบคุมการสิ้นสุดการแคสต์ได้โดยตรงผ่านปุ่มแคสต์ของเฟรมเวิร์ก แต่ตัวผู้ส่งเองก็สามารถหยุดแคสต์ได้โดยใช้ออบเจ็กต์ 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 หรือจออัจฉริยะ สื่อจะหยุดเล่นในอุปกรณ์เครื่องหนึ่ง (ต้นทาง) และเล่นต่อในอุปกรณ์อีกเครื่องหนึ่ง (ปลายทาง) อุปกรณ์แคสต์ที่มีเฟิร์มแวร์เวอร์ชันล่าสุดสามารถทำหน้าที่เป็นต้นทางหรือปลายทางในการถ่ายโอนสตรีมได้

หากต้องการรับอุปกรณ์ปลายทางใหม่ในระหว่างการถ่ายโอนสตรีม ให้เรียกใช้ CastSession#getCastDevice() เมื่อมีการเรียกใช้เหตุการณ์ cast.framework.SessionState.SESSION_RESUMED

ดูข้อมูลเพิ่มเติมได้ที่การถ่ายโอนสตรีมใน Web Receiver