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

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

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

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

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

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

ตัวอย่างด้านล่างแสดงวิธีลบล้างการทำงานเริ่มต้นสำหรับการตรวจหาว่าการเชื่อมต่อของผู้ส่งยังคงเชื่อมต่ออยู่ เมื่อ Web Receiver สื่อสารกับผู้ส่งไม่ได้เป็นเวลา 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);

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

เมื่อโหลดเนื้อหา Web Receiver 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
});

การดักจับข้อความ

Web Receiver 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 เหตุการณ์จะใช้เพื่อทริกเกอร์การวิเคราะห์หรือฟังก์ชันที่กำหนดเองได้ดีที่สุด
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();

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

ผู้ใช้สามารถโต้ตอบกับแอปพลิเคชัน Web Receiver ของคุณผ่านแอปพลิเคชันของผู้ส่ง (เว็บ, 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 สำหรับจัดการคำขอประเภทนี้ หากต้องการรองรับคำขอดังกล่าว คุณต้องดำเนินการต่อไปนี้

  • สกัดกั้น USER_ACTION ข้อความและระบุการดำเนินการที่ร้องขอ
  • อัปเดต UserActionState ของ MediaInformation เพื่ออัปเดต UI

ข้อมูลโค้ดด้านล่างสกัดกั้นข้อความ 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;
}

คำสั่งเสียง

ปัจจุบัน Web Receiver 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 ไปยังแอปพลิเคชัน Web Receiver เมื่อกิจกรรมเริ่มต้นขึ้น ระบบจะส่งข้อความอื่นที่มี 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

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

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

การโอนสตรีม

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

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

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

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

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

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

วิธีใช้การโอนสตรีมสำหรับ Web Receiver มีดังนี้

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

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

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

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

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

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

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

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

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

Android TV

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

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

Google Web Receiver ที่ทำงานบนอุปกรณ์ 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 แต่แพลตฟอร์มการแคสต์อื่นๆ ซึ่งรวมถึง Android TV อาจแสดงหน้าได้สูงสุดถึง 1080p ตรวจสอบว่าหน้ารีซีฟเวอร์ของคุณปรับขนาดอย่างสวยงามที่ความละเอียดต่างๆ