เพิ่มฟีเจอร์หลักลงในตัวรับสัญญาณเว็บที่กำหนดเอง

หน้านี้มีข้อมูลโค้ดและคำอธิบายฟีเจอร์ที่พร้อมใช้งานสำหรับแอป Custom Web Receiver

  1. องค์ประกอบ cast-media-player ที่แสดงถึง UI ของโปรแกรมเล่นในตัวที่มีให้กับเว็บรีซีฟเวอร์
  2. การจัดรูปแบบที่คล้ายกับ CSS ที่กำหนดเองสำหรับองค์ประกอบ cast-media-player เพื่อจัดสไตล์ขององค์ประกอบ UI ต่างๆ เช่น background-image, splash-image และ font-family
  3. องค์ประกอบสคริปต์สำหรับโหลดเฟรมเวิร์กเว็บรีซีฟเวอร์
  4. โค้ด JavaScript เพื่อสกัดกั้นข้อความและการจัดการเหตุการณ์
  5. คิวสำหรับเล่นอัตโนมัติ
  6. ตัวเลือกในการกำหนดค่าการเล่น
  7. ตัวเลือกในการตั้งค่าบริบทของตัวรับสัญญาณเว็บ
  8. ตัวเลือกในการตั้งคำสั่งที่แอปเว็บรีซีฟเวอร์รองรับ
  9. การเรียก JavaScript เพื่อเริ่มแอปพลิเคชันเว็บรีซีฟเวอร์

การกำหนดค่าแอปพลิเคชันและตัวเลือก

กำหนดค่าแอปพลิเคชัน

CastReceiverContext เป็นคลาสที่อยู่ด้านนอกสุดที่นักพัฒนาแอปเห็น เครื่องมือนี้จัดการการโหลดไลบรารีที่มีอยู่และจัดการการเริ่มต้น SDK ของ Web Receiver SDK มี API ที่ให้นักพัฒนาแอปพลิเคชันกำหนดค่า SDK ผ่าน CastReceiverOptions การกำหนดค่าเหล่านี้จะได้รับการประเมินเพียงครั้งเดียวต่อการเปิดใช้แอปพลิเคชันและจะส่งไปยัง SDK เมื่อตั้งค่าพารามิเตอร์ที่ไม่บังคับในการเรียกไปยัง start

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

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

กำหนดค่าโปรแกรมเล่น

เมื่อโหลดเนื้อหา SDK รีซีฟเวอร์ของเว็บมีวิธีกำหนดค่าตัวแปรการเล่น เช่น ข้อมูล DRM, ลองกำหนดค่าใหม่ และเครื่องจัดการคำขอโดยใช้ cast.framework.PlaybackConfig ข้อมูลนี้จัดการโดย PlayerManager และจะประเมินเมื่อมีการสร้างโปรแกรมเล่นขึ้น ระบบจะสร้างโปรแกรมเล่นขึ้นทุกครั้งที่โหลดใหม่ส่งไปยัง SDK ของ Web Receiver การแก้ไข PlaybackConfig หลังจากสร้างโปรแกรมเล่นแล้วจะได้รับการประเมินในการโหลดเนื้อหาถัดไป SDK มีวิธีแก้ไข PlaybackConfig ดังต่อไปนี้

  • CastReceiverOptions.playbackConfig เพื่อลบล้างตัวเลือกการกำหนดค่าเริ่มต้นเมื่อเริ่มต้น CastReceiverContext
  • PlayerManager.getPlaybackConfig() เพื่อรับการกำหนดค่าปัจจุบัน
  • PlayerManager.setPlaybackConfig() เพื่อลบล้างการกำหนดค่าปัจจุบัน การตั้งค่านี้มีผลกับการโหลดครั้งต่อๆ ไปทั้งหมดหรือจนกว่าจะถูกลบล้างอีกครั้ง
  • PlayerManager.setMediaPlaybackInfoHandler() เพื่อใช้การกำหนดค่าเพิ่มเติมเฉพาะสำหรับรายการสื่อที่โหลดทับการกำหนดค่าปัจจุบัน ระบบจะเรียกเครื่องจัดการ ก่อนการสร้างโปรแกรมเล่น การเปลี่ยนแปลงที่เกิดขึ้นที่นี่ไม่ได้เป็นแบบถาวรและไม่รวมอยู่ในคำค้นหาสำหรับ getPlaybackConfig() เมื่อรายการสื่อถัดไปโหลดขึ้นมา ระบบจะเรียกเครื่องจัดการนี้อีกครั้ง

ตัวอย่างด้านล่างแสดงวิธีตั้งค่า PlaybackConfig เมื่อเริ่มต้น CastReceiverContext การกำหนดค่าจะลบล้างคำขอขาออกสำหรับการรับไฟล์ Manifest เครื่องจัดการระบุว่าคำขอควบคุมการเข้าถึง CORS ควรทำโดยใช้ข้อมูลเข้าสู่ระบบ เช่น คุกกี้หรือส่วนหัวการให้สิทธิ์

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

ตัวอย่างด้านล่างแสดงวิธีลบล้าง PlaybackConfig โดยใช้ Getter and Setter ที่ให้ไว้ใน PlayerManager การตั้งค่านี้เป็นการกำหนดค่าให้โปรแกรมเล่นกลับมาเล่นเนื้อหาต่อหลังจากที่โหลด 1 ส่วนแล้ว

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

ตัวอย่างด้านล่างแสดงวิธีลบล้าง PlaybackConfig สำหรับคำขอโหลดที่เฉพาะเจาะจงโดยใช้เครื่องจัดการข้อมูลการเล่นสื่อ เครื่องจัดการจะเรียกเมธอด getLicenseUrlForMedia ที่ใช้แอปพลิเคชันเพื่อรับ licenseUrl จาก contentId ของรายการปัจจุบัน

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

Listener เหตุการณ์

Web Receiver SDK ช่วยให้แอป Web Receiver จัดการเหตุการณ์ของโปรแกรมเล่นได้ Listener เหตุการณ์จะใช้พารามิเตอร์ cast.framework.events.EventType (หรืออาร์เรย์ของพารามิเตอร์เหล่านี้) ที่ระบุเหตุการณ์ที่ควรทริกเกอร์ Listener ดูอาร์เรย์ที่กำหนดค่าไว้ล่วงหน้าของ cast.framework.events.EventType ซึ่งมีประโยชน์ในการแก้ไขข้อบกพร่องได้ใน cast.framework.events.category พารามิเตอร์เหตุการณ์จะให้ข้อมูลเพิ่มเติมเกี่ยวกับเหตุการณ์

ตัวอย่างเช่น หากคุณต้องการทราบเวลาที่การเปลี่ยนแปลง mediaStatus เผยแพร่ คุณสามารถใช้ตรรกะต่อไปนี้ในการจัดการเหตุการณ์ได้

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

การสกัดกั้นข้อความ

SDK ตัวรับสัญญาณเว็บช่วยให้แอป Web Receiver สามารถสกัดกั้นข้อความและเรียกใช้โค้ดที่กำหนดเองกับข้อความเหล่านั้น ตัวตรวจจับข้อความจะใช้พารามิเตอร์ cast.framework.messages.MessageType ที่ระบุประเภทของข้อความที่ควรดักจับ

ผู้สอดแนมควรส่งคืนคำขอที่แก้ไขแล้วหรือคำสัญญาที่แก้ไขด้วยค่าของคำขอที่แก้ไขแล้ว การส่งคืน null จะป้องกันไม่ให้เรียกใช้ตัวแฮนเดิลข้อความเริ่มต้น ดูการโหลดสื่อสำหรับรายละเอียดเพิ่มเติม

ตัวอย่างเช่น หากต้องการเปลี่ยนข้อมูลคำขอโหลด คุณสามารถใช้ตรรกะต่อไปนี้เพื่อสกัดกั้นและแก้ไขได้

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

การจัดการข้อผิดพลาด

เมื่อเกิดข้อผิดพลาดในเครื่องมือดักจับข้อความ แอป Web Receiver ควรแสดงผล cast.framework.messages.ErrorType และ cast.framework.messages.ErrorReason ที่เหมาะสม

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

การสกัดกั้นข้อความกับ Listener เหตุการณ์

ความแตกต่างที่สําคัญระหว่างการสกัดกั้นข้อความและ Listener เหตุการณ์มีดังนี้

  • Listener เหตุการณ์ไม่อนุญาตให้คุณแก้ไขข้อมูลคำขอ
  • ควรใช้ Listener เหตุการณ์ในการทริกเกอร์ Analytics หรือฟังก์ชันที่กำหนดเอง
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • การดักฟังข้อความช่วยให้คุณฟังข้อความ สกัดกั้น และแก้ไขข้อมูลคำขอได้
  • การดักจับข้อความจะใช้ในการจัดการกับตรรกะที่กำหนดเองเกี่ยวกับข้อมูลคำขอได้ดีที่สุด

กำลังโหลดสื่อ

MediaInformation มีพร็อพเพอร์ตี้มากมายสำหรับโหลดสื่อในข้อความ cast.framework.messages.MessageType.LOAD ซึ่งรวมถึง entity, contentUrl และ contentId

entity เป็นพร็อพเพอร์ตี้ที่แนะนำสำหรับใช้ในการใช้งานทั้งแอปของผู้ส่งและผู้รับ พร็อพเพอร์ตี้คือ URL ของ Deep Link ที่เป็นได้ทั้งเพลย์ลิสต์หรือเนื้อหาสื่อที่เจาะจง

contentUrl ออกแบบมาสำหรับ URL ที่เล่นได้และใช้งานได้เมื่อพร้อมใช้งาน

เราเลิกใช้งานcontentIdแล้วเนื่องจากความไม่ชัดเจนว่าค่านี้เป็น URL ของสื่อ รหัสจริง หรือพารามิเตอร์หลักสำหรับการค้นหาที่กำหนดเอง

ขอแนะนำให้ใช้ entity เพื่อจัดเก็บรหัสจริงหรือพารามิเตอร์ของคีย์และใช้ contentUrl สำหรับ URL ของสื่อ ตัวอย่างข้อมูลจะแสดงในข้อมูลโค้ดต่อไปนี้ ซึ่งมี entity อยู่ในคำขอ LOAD และมีการเรียก contentUrl ที่เล่นได้

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

ความสามารถของอุปกรณ์

เมธอด getDeviceCapabilities จะให้ข้อมูลอุปกรณ์ในอุปกรณ์แคสต์ที่เชื่อมต่อและอุปกรณ์วิดีโอหรือเสียงที่เชื่อมต่ออยู่ เมธอด getDeviceCapabilities จะให้ข้อมูลสนับสนุนสำหรับ Google Assistant, บลูทูธ รวมถึงอุปกรณ์แสดงผลและอุปกรณ์เสียงที่เชื่อมต่อ

เมธอดนี้จะแสดงออบเจ็กต์ที่ค้นหาได้โดยส่งผ่าน enum ที่ระบุรายการใดรายการหนึ่งเพื่อรับความสามารถของอุปกรณ์สำหรับ enum นั้น Enum จะมีอยู่ใน cast.framework.system.DeviceCapabilities

ตัวอย่างนี้ตรวจสอบว่าอุปกรณ์ Web Receiver เล่น HDR และ DolbyVision (DV) ด้วยคีย์ IS_HDR_SUPPORTED และ IS_DV_SUPPORTED ตามลำดับได้หรือไม่

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

การจัดการการโต้ตอบของผู้ใช้

ผู้ใช้สามารถโต้ตอบกับแอปพลิเคชันเว็บรีซีฟเวอร์ของคุณผ่านแอปพลิเคชันผู้ส่ง (เว็บ, Android และ iOS) คำสั่งเสียงในอุปกรณ์ที่พร้อมใช้งาน Assistant การควบคุมด้วยการสัมผัสบนจออัจฉริยะ และรีโมตคอนโทรลในอุปกรณ์ Android TV Cast SDK มี API ต่างๆ ที่จะช่วยให้แอป Web Receiver จัดการการโต้ตอบเหล่านี้ อัปเดต UI ของแอปพลิเคชันผ่านสถานะการดำเนินการของผู้ใช้ และเลือกที่จะส่งการเปลี่ยนแปลงเพื่ออัปเดตบริการแบ็กเอนด์ใดก็ได้

คำสั่งสื่อที่รองรับ

สถานะการควบคุม UI จะขับเคลื่อนด้วย MediaStatus.supportedMediaCommands สำหรับตัวควบคุมแบบขยายของตัวส่ง iOS และ Android แอปตัวรับสัญญาณและรีโมตคอนโทรลที่ทํางานในอุปกรณ์แบบสัมผัส และแอปตัวรับสัญญาณในอุปกรณ์ Android TV เมื่อเปิดใช้บิตไวส์ Command ที่เฉพาะเจาะจงในพร็อพเพอร์ตี้ ปุ่มที่เกี่ยวข้องกับการดําเนินการนั้นจะเปิดใช้ หากไม่ได้ตั้งค่านี้ไว้ ปุ่มจะปิดการทำงาน ค่าเหล่านี้จะเปลี่ยนใน Web Receiver ได้โดยวิธีต่อไปนี้

  1. การใช้ PlayerManager.setSupportedMediaCommands เพื่อกำหนด Commands แบบเจาะจง
  2. การเพิ่มคำสั่งใหม่โดยใช้ addSupportedMediaCommands
  3. นำคำสั่งที่มีอยู่ออกโดยใช้ removeSupportedMediaCommands
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

เมื่อผู้รับเตรียม MediaStatus ที่อัปเดตแล้ว ระบบจะรวมการเปลี่ยนแปลงไว้ในพร็อพเพอร์ตี้ supportedMediaCommands เมื่อมีการประกาศสถานะ แอปของผู้ส่งที่เชื่อมต่อจะอัปเดตปุ่มใน UI ของตนให้สอดคล้องกัน

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับคำสั่งของสื่อและอุปกรณ์สัมผัสที่รองรับ โปรดดูคู่มือ Accessing UI controls

การจัดการสถานะการดำเนินการของผู้ใช้

เมื่อโต้ตอบกับ UI หรือส่งคำสั่งเสียง ผู้ใช้จะควบคุมการเล่นเนื้อหาและคุณสมบัติที่เกี่ยวข้องกับรายการที่เล่นอยู่ได้ SDK จะจัดการคำขอที่ควบคุมการเล่นโดยอัตโนมัติ คำขอที่แก้ไขพร็อพเพอร์ตี้สำหรับรายการปัจจุบันที่เล่น เช่น คำสั่ง LIKE จำเป็นต้องให้แอปพลิเคชันฝั่งผู้รับจัดการพร็อพเพอร์ตี้ดังกล่าว SDK มีชุด API สำหรับจัดการคำขอประเภทนี้ หากต้องการรองรับคำขอดังกล่าว คุณต้องดำเนินการต่อไปนี้

  • ตั้งค่า MediaInformation userActionStates ด้วยค่ากำหนดของผู้ใช้เมื่อโหลดรายการสื่อ
  • สกัดกั้นข้อความ USER_ACTION รายการและพิจารณาการดำเนินการที่ขอ
  • อัปเดต UserActionState ของ MediaInformation เพื่ออัปเดต UI

ข้อมูลโค้ดต่อไปนี้สกัดกั้นคำขอ LOAD และป้อนข้อมูล MediaInformation ของ LoadRequestData ในกรณีนี้ ผู้ใช้ชอบ เนื้อหาที่โหลดอยู่

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

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

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

ข้อมูลโค้ดต่อไปนี้จำลองการเรียกใช้บริการแบ็กเอนด์ ฟังก์ชันนี้จะตรวจสอบ UserActionRequestData เพื่อดูประเภทการเปลี่ยนแปลงที่ผู้ใช้ขอและเรียกเครือข่ายต่อเมื่อแบ็กเอนด์รองรับการดำเนินการนี้

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

ข้อมูลโค้ดต่อไปนี้จะใช้ UserActionRequestData และเพิ่มหรือนำ UserActionState ออกจาก MediaInformation การอัปเดต UserActionState ของ MediaInformation จะเปลี่ยนสถานะของปุ่มที่เชื่อมโยงกับการดำเนินการที่ขอ การเปลี่ยนแปลงนี้จะแสดงใน UI การควบคุมจออัจฉริยะ, แอปรีโมตคอนโทรล และ UI ของ Android TV อีกทั้งระบบจะประกาศข้อความ MediaStatus ขาออกเพื่ออัปเดต UI ของตัวควบคุมแบบขยายสำหรับผู้ส่ง iOS และ Android

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

คำสั่งเสียง

ปัจจุบัน SDK ตัวรับสัญญาณเว็บสําหรับอุปกรณ์ที่พร้อมใช้งาน Assistant รองรับคําสั่งสื่อต่อไปนี้ การใช้งานเริ่มต้นของคำสั่งเหล่านี้จะอยู่ใน cast.framework.PlayerManager

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

คำสั่งสื่อที่รองรับด้วยเสียง

หากต้องการป้องกันไม่ให้คำสั่งเสียงเรียกคำสั่งสื่อในอุปกรณ์ที่พร้อมใช้งาน Assistant คุณต้องตั้งค่าคำสั่งสื่อที่รองรับซึ่งวางแผนจะรองรับก่อน จากนั้นคุณต้องบังคับใช้คำสั่งเหล่านั้นโดยเปิดใช้พร็อพเพอร์ตี้ CastReceiverOptions.enforceSupportedCommands UI ในผู้ส่ง Cast SDK และอุปกรณ์ที่เปิดใช้ระบบสัมผัสจะเปลี่ยนไปตามการกำหนดค่าเหล่านี้ หากไม่เปิดใช้การตั้งค่าสถานะ คำสั่งเสียงที่เข้ามาใหม่จะทำงาน

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

ในตัวอย่างด้านล่าง เราจะระบุ CastReceiverOptions เมื่อเริ่มต้น CastReceiverContext เราได้เพิ่มการรองรับคำสั่ง PAUSE และบังคับให้โปรแกรมเล่นรองรับคำสั่งนั้นเท่านั้น ตอนนี้หากคำสั่งเสียงขอการดำเนินการอื่น เช่น SEEK ระบบจะปฏิเสธ ระบบจะแจ้งให้ผู้ใช้ทราบว่ายังไม่รองรับคำสั่งนี้

const context = cast.framework.CastReceiverContext.getInstance();

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

คุณสามารถใช้ตรรกะแบบแยกกันสำหรับแต่ละคำสั่งที่ต้องการจำกัดได้ นำแฟล็ก enforceSupportedCommands ออก และสำหรับแต่ละคำสั่งที่คุณต้องการจำกัด คุณสามารถสกัดกั้นข้อความขาเข้าได้ ในขั้นตอนนี้ เราจะสกัดกั้นคำขอที่ได้จาก SDK เพื่อไม่ให้คำสั่ง SEEK ที่ออกให้กับอุปกรณ์ที่พร้อมใช้งาน Assistant ทริกเกอร์การค้นหาในแอปพลิเคชันเว็บรีซีฟเวอร์ของคุณ

สำหรับคำสั่งของสื่อที่แอปพลิเคชันของคุณไม่รองรับ ให้แสดงผลเหตุผลข้อผิดพลาดที่เหมาะสม เช่น NOT_SUPPORTED

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

เล่นอยู่เบื้องหลังจากกิจกรรมเสียง

หากแพลตฟอร์ม Cast ทำให้เสียงของแอปพลิเคชันอยู่เบื้องหลังเนื่องจากกิจกรรมของ Assistant เช่น การฟังคำพูดของผู้ใช้หรือพูดตอบ ระบบจะส่งข้อความ FocusState ของ NOT_IN_FOCUS ไปยังแอปพลิเคชันเว็บรีซีฟเวอร์เมื่อกิจกรรมเริ่มต้นขึ้น ระบบจะส่งอีกข้อความกับ IN_FOCUS เมื่อกิจกรรมสิ้นสุดลง คุณอาจต้องการหยุดสื่อชั่วคราวเมื่อ FocusState มีสถานะNOT_IN_FOCUSโดยการสกัดกั้นข้อความประเภท FOCUS_STATE ทั้งนี้ขึ้นอยู่กับแอปพลิเคชันและสื่อที่เล่นอยู่

ตัวอย่างเช่น การหยุดเล่นหนังสือเสียงชั่วคราวเป็นประสบการณ์ที่ดีของผู้ใช้ ถ้า Assistant ตอบสนองต่อคำค้นหาของผู้ใช้

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

ภาษาของคำบรรยายด้วยเสียง

เมื่อผู้ใช้ไม่ได้ระบุภาษาของคำบรรยายไว้อย่างชัดแจ้ง ภาษาที่ใช้สำหรับคำบรรยายจะเป็นภาษาเดียวกับที่มีการใช้คำสั่ง ในสถานการณ์เช่นนี้ พารามิเตอร์ isSuggestedLanguage ของข้อความขาเข้าจะระบุว่าผู้ใช้แนะนำหรือขอภาษาที่เกี่ยวข้องอย่างชัดแจ้งหรือไม่

ตัวอย่างเช่น มีการตั้งค่า isSuggestedLanguage เป็น true สำหรับคำสั่ง "Ok Google เปิดคำบรรยาย" เพราะภาษาได้รับการอนุมานจากภาษาที่พูดคำสั่งดังกล่าว หากมีคำขอภาษานั้นอย่างชัดเจน เช่น ใน "Ok Google เปิดคำบรรยายภาษาอังกฤษ" isSuggestedLanguage จะตั้งค่าเป็น false

การแคสต์ข้อมูลเมตาและการแคสต์เสียง

แม้ว่าเว็บรีซีฟเวอร์จะจัดการคำสั่งเสียงโดยค่าเริ่มต้น แต่คุณก็ควรตรวจสอบว่าข้อมูลเมตาสำหรับเนื้อหาครบถ้วนและถูกต้อง วิธีนี้ช่วยให้มั่นใจว่า Assistant จัดการคำสั่งเสียงได้อย่างถูกต้องและดูแลให้ข้อมูลเมตาแสดงอย่างถูกต้องในอินเทอร์เฟซประเภทใหม่ๆ เช่น แอป Google Home และ Smart Display เช่น Google Home Hub

โอนสตรีม

การรักษาสถานะเซสชันเป็นพื้นฐานของการโอนสตรีม ซึ่งผู้ใช้สามารถย้ายสตรีมเสียงและวิดีโอที่มีอยู่ในอุปกรณ์ต่างๆ โดยใช้คำสั่งเสียง, แอป Google Home หรือ Smart Display สื่อจะหยุดเล่นในอุปกรณ์หนึ่ง (แหล่งที่มา) และเล่นต่อในอุปกรณ์อื่น (ปลายทาง) อุปกรณ์แคสต์ที่มีเฟิร์มแวร์เวอร์ชันล่าสุดจะใช้เป็นแหล่งที่มาหรือปลายทางในการโอนสตรีมได้

โฟลว์เหตุการณ์สำหรับการโอนสตรีมคือ

  1. ในอุปกรณ์ต้นทาง ให้ทำดังนี้
    1. สื่อหยุดเล่น
    2. แอปพลิเคชันเว็บรีซีฟเวอร์จะได้รับคำสั่งให้บันทึกสถานะสื่อปัจจุบัน
    3. แอปพลิเคชัน Web Receiver ปิดลงแล้ว
  2. ในอุปกรณ์ปลายทาง ให้ทำดังนี้
    1. โหลดแอปพลิเคชัน Web Receiver แล้ว
    2. แอปพลิเคชัน Web Receiver จะได้รับคำสั่งเพื่อคืนค่าสถานะสื่อที่บันทึกไว้
    3. สื่อกลับมาเล่นต่อ

องค์ประกอบของสถานะของสื่อมีดังนี้

  • ตำแหน่งหรือการประทับเวลาที่เฉพาะเจาะจงของเพลง วิดีโอ หรือรายการสื่อ
  • เพลย์ลิสต์จะอยู่ในคิวที่กว้างกว่า (เช่น เพลย์ลิสต์หรือวิทยุของศิลปิน)
  • ผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว
  • สถานะการเล่น (เช่น กำลังเล่นหรือหยุดชั่วคราว)

การเปิดใช้การโอนสตรีม

วิธีใช้การโอนสตรีมสำหรับเว็บรีซีฟเวอร์มีดังนี้

  1. อัปเดต supportedMediaCommands ด้วยคำสั่ง STREAM_TRANSFER ดังนี้
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. (ไม่บังคับ) ลบล้างตัวบล็อกข้อความ SESSION_STATE และ RESUME_SESSION ตามที่อธิบายไว้ในสถานะการเก็บรักษาเซสชัน โดยจะลบล้างรายการเหล่านี้ในกรณีที่ต้องเก็บข้อมูลที่กำหนดเอง เป็นส่วนหนึ่งของสแนปชอตเซสชันเท่านั้น มิเช่นนั้น การใช้งานเริ่มต้นสำหรับการเก็บรักษาสถานะเซสชันจะรองรับการโอนสตรีม

กำลังเก็บรักษาสถานะเซสชัน

SDK ของเว็บรีซีฟเวอร์มอบการใช้งานเริ่มต้นให้แอปเว็บรีซีฟเวอร์ในการรักษาสถานะเซสชันด้วยการเก็บสแนปชอตของสถานะสื่อปัจจุบัน แปลงสถานะเป็นคำขอโหลด และทำให้เซสชันกลับมาทำงานอีกครั้งด้วยคำขอโหลด

คำขอโหลดที่สร้างโดย Web Receiver สามารถลบล้างได้ในตัวตรวจจับข้อความ SESSION_STATE หากจำเป็น หากคุณต้องการเพิ่มข้อมูลที่กำหนดเองลงในคำขอโหลด เราขอแนะนำให้ใส่ข้อมูลที่กำหนดเองไว้ใน loadRequestData.customData

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

คุณสามารถดึงข้อมูลที่กําหนดเองได้จาก loadRequestData.customData ในตัวตรวจจับข้อความ RESUME_SESSION

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

การโหลดเนื้อหาล่วงหน้า

ตัวรับสัญญาณเว็บรองรับการโหลดรายการสื่อไว้ล่วงหน้าหลังจากรายการเล่นปัจจุบันในคิว

การดำเนินการโหลดล่วงหน้าจะดาวน์โหลดไฟล์หลายๆ ส่วนไว้ล่วงหน้า ข้อกำหนดจะดำเนินการกับค่า preloadTime ในออบเจ็กต์ QueueItem (มีค่าเริ่มต้นที่ 20 วินาทีหากไม่ได้ระบุไว้) เวลาจะแสดงเป็นวินาที สัมพันธ์กับจุดสิ้นสุดของรายการที่กำลังเล่นอยู่ ใช้ได้เฉพาะค่าที่เป็นบวก เท่านั้น เช่น หากค่าคือ 10 วินาที ระบบจะโหลดรายการนี้ล่วงหน้า 10 วินาทีก่อนที่รายการก่อนหน้าจะเสร็จสิ้น หากเวลาการโหลดล่วงหน้าสูงกว่าเวลาที่เหลือในรายการ currentItem การโหลดล่วงหน้าจะเกิดขึ้นทันทีที่ทำได้ ดังนั้น หากระบุค่าของการโหลดล่วงหน้าในคิวItem ค่าหนึ่งจำนวนมาก ค่าหนึ่งอาจส่งผลเมื่อเล่นรายการปัจจุบัน ซึ่งเราโหลดรายการถัดไปไว้ล่วงหน้าแล้ว อย่างไรก็ตาม เราคงการตั้งค่าและตัวเลือกนี้ไว้ให้นักพัฒนาซอฟต์แวร์ เนื่องจากค่านี้อาจส่งผลต่อแบนด์วิดท์และประสิทธิภาพการสตรีมของรายการเล่นปัจจุบัน

การโหลดล่วงหน้าจะใช้ได้กับเนื้อหา HLS, DASH และ Smooth สตรีมมิงโดยค่าเริ่มต้น

ระบบจะไม่โหลดไฟล์วิดีโอและไฟล์เสียง MP4 ทั่วไป เช่น MP3 ไว้ล่วงหน้าเนื่องจากอุปกรณ์แคสต์รองรับองค์ประกอบสื่อเพียงองค์ประกอบเดียว และจะใช้เพื่อโหลดล่วงหน้าไม่ได้ในขณะที่รายการเนื้อหาที่มีอยู่ยังเล่นอยู่

ข้อความที่กำหนดเอง

การแลกเปลี่ยนข้อความเป็นวิธีการโต้ตอบที่สำคัญสำหรับแอปพลิเคชันเว็บรีซีฟเวอร์

ผู้ส่งจะออกข้อความไปยังเว็บรีซีฟเวอร์โดยใช้ API ของผู้ส่งสำหรับแพลตฟอร์มที่ผู้ส่งกำลังใช้งานอยู่ (Android, iOS, เว็บ) ออบเจ็กต์เหตุการณ์ (ซึ่งเป็นการแสดงข้อความ) ที่ส่งไปยัง Listener เหตุการณ์มีองค์ประกอบข้อมูล (event.data) ซึ่งข้อมูลจะนำพร็อพเพอร์ตี้ของประเภทเหตุการณ์ที่เฉพาะเจาะจงไป

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

เนมสเปซทั้งหมดจะกำหนดโดยสตริงและต้องขึ้นต้นด้วย "urn:x-cast:" ตามด้วยสตริงใดๆ ตัวอย่างเช่น "urn:x-cast:com.example.cast.mynamespace"

ต่อไปนี้เป็นข้อมูลโค้ดเพื่อให้ Web Receiver ฟังข้อความที่กำหนดเองจากผู้ส่งที่เชื่อมต่อ

const context = cast.framework.CastReceiverContext.getInstance();

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

ในทำนองเดียวกัน แอปพลิเคชันเว็บรีซีฟเวอร์สามารถแจ้งให้ผู้ส่งทราบถึงสถานะของรีซีฟเวอร์ โดยส่งข้อความถึงผู้ส่งที่เชื่อมต่อ แอปพลิเคชัน Web Receiver จะส่งข้อความโดยใช้ sendCustomMessage(namespace, senderId, message) บน CastReceiverContext ได้ Webรีซีฟเวอร์สามารถส่งข้อความไปยังผู้ส่งแต่ละรายได้ ไม่ว่าจะตอบกลับข้อความที่ได้รับ หรือเกิดจากการเปลี่ยนแปลงสถานะของแอปพลิเคชัน นอกจากการส่งข้อความแบบจุดต่อจุด (โดยมีขีดจำกัดที่ 64 KB) เว็บรีซีฟเวอร์ยังอาจประกาศข้อความไปยังผู้ส่งที่เชื่อมต่อทุกคนอีกด้วย

แคสต์สำหรับอุปกรณ์เสียง

โปรดดูคู่มือ Google Cast สำหรับอุปกรณ์เสียงสำหรับการรองรับการเล่นเฉพาะเสียง

Android TV

หัวข้อนี้จะกล่าวถึงวิธีที่ Google Web Receiver ใช้อินพุตของคุณเป็นการเล่นและความเข้ากันได้ของ Android TV

การผสานรวมแอปพลิเคชันของคุณกับรีโมตคอนโทรล

เว็บรีซีฟเวอร์ของ Google ที่ทำงานบนอุปกรณ์ Android TV จะแปลอินพุตจากอินพุตการควบคุมของอุปกรณ์ (เช่น รีโมตคอนโทรลแบบมือถือ) เป็นข้อความการเล่นสื่อที่กำหนดไว้สำหรับเนมสเปซ urn:x-cast:com.google.cast.media ตามที่อธิบายไว้ในข้อความการเล่นสื่อ แอปพลิเคชันของคุณต้องรองรับข้อความเหล่านี้เพื่อควบคุมการเล่นสื่อของแอปพลิเคชันและอนุญาตการควบคุมการเล่นพื้นฐานจากอินพุตควบคุมของ Android TV

หลักเกณฑ์ความเข้ากันได้ของ Android TV

คำแนะนำและข้อผิดพลาดที่พบบ่อยที่ควรหลีกเลี่ยงเพื่อให้แน่ใจว่าแอปพลิเคชันจะทำงานร่วมกับ Android TV ได้มีดังนี้

  • โปรดทราบว่าสตริง User Agent มีทั้ง "Android" และ "CrKey" บางเว็บไซต์อาจเปลี่ยนเส้นทางไปยังเว็บไซต์สำหรับอุปกรณ์เคลื่อนที่เท่านั้นเนื่องจากตรวจพบป้ายกำกับ "Android" อย่าทึกทักเอาว่า "Android" ในสตริง user-agent บ่งบอกถึงผู้ใช้อุปกรณ์เคลื่อนที่เสมอ
  • สแต็กสื่อของ Android อาจใช้ GZIP แบบโปร่งใสในการดึงข้อมูล ตรวจดูว่าข้อมูลสื่อของคุณตอบสนองต่อ Accept-Encoding: gzip ได้
  • เหตุการณ์สื่อ HTML5 ของ Android TV อาจมีการทริกเกอร์ในเวลาที่ต่างจาก Chromecast ซึ่งอาจเปิดเผยปัญหาที่ซ่อนไว้ใน Chromecast
  • เมื่ออัปเดตสื่อ ให้ใช้เหตุการณ์ที่เกี่ยวข้องกับสื่อซึ่งองค์ประกอบ <audio>/<video> เริ่มทำงาน เช่น timeupdate, pause และ waiting หลีกเลี่ยงการใช้เหตุการณ์ที่เกี่ยวข้องกับเครือข่าย เช่น progress, suspend และ stalled เนื่องจากเหตุการณ์เหล่านี้มักขึ้นอยู่กับแพลตฟอร์ม ดูเหตุการณ์สื่อสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการจัดการเหตุการณ์สื่อในรีซีฟเวอร์
  • เมื่อกำหนดค่าใบรับรอง HTTPS ของเว็บไซต์ผู้รับ อย่าลืมใส่ใบรับรอง CA กลาง ดูหน้าทดสอบ Qualsys SSL เพื่อยืนยันว่าเส้นทางการรับรองที่เชื่อถือได้สำหรับเว็บไซต์มีใบรับรอง CA ที่มีป้ายกำกับว่า "การดาวน์โหลดเพิ่มเติม" ใบรับรองนั้นอาจไม่โหลดในแพลตฟอร์มที่ใช้ Android
  • แม้ว่า Chromecast จะแสดงหน้าเครื่องรับบนระนาบกราฟิก 720p แต่แพลตฟอร์ม Cast อื่นๆ ซึ่งรวมถึง Android TV อาจแสดงหน้าได้สูงสุดถึง 1080p ตรวจสอบว่าหน้ารีซีฟเวอร์ของคุณปรับขนาดได้อย่างงดงามที่ความละเอียดต่างๆ