หน้านี้มีข้อมูลโค้ดและคำอธิบายฟีเจอร์ที่พร้อมใช้งานสำหรับแอป Custom Web Receiver
- องค์ประกอบ
cast-media-playerที่แสดงถึง UI ของเพลเยอร์ในตัวที่มาพร้อมกับ Web Receiver - การจัดรูปแบบที่คล้ายกับ CSS ที่กำหนดเองสำหรับองค์ประกอบ
cast-media-playerเพื่อจัดรูปแบบองค์ประกอบ UI ต่างๆ เช่นbackground-image,splash-imageและfont-family - องค์ประกอบสคริปต์เพื่อโหลดเฟรมเวิร์ก Web Receiver
- โค้ด JavaScript เพื่อสกัดกั้นข้อความและจัดการเหตุการณ์
- คิวสำหรับการเล่นอัตโนมัติ
- ตัวเลือกในการกำหนดค่าการเล่น
- ตัวเลือกในการตั้งค่าบริบทของ Web Receiver
- ตัวเลือกในการตั้งค่าคำสั่งที่แอปรับบนเว็บรองรับ
- การเรียกใช้ JavaScript เพื่อเริ่มแอปพลิเคชัน Web Receiver
การกำหนดค่าและตัวเลือกของแอปพลิเคชัน
กำหนดค่าแอปพลิเคชัน
CastReceiverContext เป็นคลาสชั้นนอกสุดที่แสดงต่อนักพัฒนาซอฟต์แวร์ และจัดการการโหลดไลบรารีที่เกี่ยวข้อง รวมถึงจัดการการเริ่มต้น Web Receiver SDK 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 และจะได้รับการประเมินเมื่อสร้างเพลเยอร์ ระบบจะสร้างเพลเยอร์ทุกครั้งที่มีการส่งการโหลดใหม่ไปยัง Web Receiver SDK การแก้ไข PlaybackConfig หลังจากสร้างเพลเยอร์แล้วจะได้รับการประเมินในการโหลดเนื้อหาครั้งถัดไป SDK มีเมธอดต่อไปนี้สำหรับการแก้ไข PlaybackConfig
CastReceiverOptions.playbackConfigเพื่อลบล้างตัวเลือกการกำหนดค่าเริ่มต้นเมื่อเริ่มต้นใช้งานCastReceiverContextPlayerManager.getPlaybackConfig()เพื่อดูการกำหนดค่าปัจจุบันPlayerManager.setPlaybackConfig()เพื่อลบล้างการกำหนดค่าปัจจุบัน การตั้งค่านี้จะมีผลกับการโหลดครั้งต่อๆ ไปทั้งหมดหรือจนกว่าจะมีการลบล้างอีกครั้งPlayerManager.setMediaPlaybackInfoHandler()เพื่อใช้การกำหนดค่าเพิ่มเติมสำหรับรายการสื่อที่โหลดไว้ด้านบนของการกำหนดค่าปัจจุบันเท่านั้น ระบบจะเรียกใช้แฮนเดิลก่อนสร้างเพลเยอร์ การเปลี่ยนแปลงที่ทำที่นี่ไม่ใช่การเปลี่ยนแปลงถาวรและจะไม่รวมอยู่ในการค้นหาไปยังgetPlaybackConfig()เมื่อโหลดรายการสื่อถัดไป ระบบจะเรียกใช้แฮนเดิลนี้อีกครั้ง
ตัวอย่างด้านล่างแสดงวิธีตั้งค่า PlaybackConfig เมื่อเริ่มต้น CastReceiverContext การกำหนดค่าจะลบล้างคำขอขาออกเพื่อรับไฟล์ Manifest เครื่องมือจัดการระบุว่าควรส่งคำขอ Access-Control ของ CORS โดยใช้ข้อมูลเข้าสู่ระบบ เช่น คุกกี้หรือส่วนหัวการให้สิทธิ์
const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});
ตัวอย่างด้านล่างแสดงวิธีลบล้าง PlaybackConfig โดยใช้ Getter และ 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 เหตุการณ์
SDK ของ Web Receiver ช่วยให้แอป 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
ซึ่งระบุประเภทข้อความที่ควรสกัดกั้น
ตัวสกัดกั้นควรแสดงผลคำขอที่แก้ไขแล้วหรือ Promise ที่แก้ไขด้วยค่าคำขอที่แก้ไขแล้ว การแสดงผล 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 ซึ่งอาจเป็นเพลย์ลิสต์หรือเนื้อหาสื่อก็ได้ แอปพลิเคชันของคุณควรแยกวิเคราะห์ URL นี้และป้อนข้อมูลในช่องอื่นๆ อย่างน้อย 1 ช่องจาก 2 ช่องcontentUrlสอดคล้องกับ URL ที่เล่นได้ซึ่งโปรแกรมเล่นจะใช้เพื่อโหลดเนื้อหา เช่น URL นี้อาจชี้ไปยังไฟล์ Manifest ของ DASHcontentIdอาจเป็น URL ของเนื้อหาที่เล่นได้ (คล้ายกับพร็อพเพอร์ตี้contentUrl) หรือตัวระบุที่ไม่ซ้ำกันสำหรับเนื้อหาหรือเพลย์ลิสต์ที่โหลดอยู่ หากใช้พร็อพเพอร์ตี้นี้เป็นตัวระบุ แอปพลิเคชันของคุณควรป้อน URL ที่เล่นได้ในcontentUrl
เราขอแนะนำให้ใช้ entity เพื่อจัดเก็บ REAL ID หรือพารามิเตอร์คีย์ และใช้ 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
ตัวอย่างนี้จะตรวจสอบว่าอุปกรณ์ตัวรับสัญญาณบนเว็บสามารถเล่น 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 ระดับบิตที่เฉพาะเจาะจงในพร็อพเพอร์ตี้ ระบบจะเปิดใช้ปุ่มที่เกี่ยวข้องกับการดำเนินการนั้น หากไม่ได้ตั้งค่า ปุ่มจะปิดใช้ คุณเปลี่ยนค่าเหล่านี้ในตัวรับสัญญาณบนเว็บได้โดยทำดังนี้
- การใช้
PlayerManager.setSupportedMediaCommandsเพื่อตั้งค่าCommandsที่เฉพาะเจาะจง - การเพิ่มคำสั่งใหม่โดยใช้
addSupportedMediaCommands - การนำคำสั่งที่มีอยู่ออกโดยใช้
removeSupportedMediaCommands
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
cast.framework.messages.Command.PAUSE);
เมื่อผู้รับเตรียม MediaStatus ที่อัปเดตแล้ว ระบบจะรวมการเปลี่ยนแปลงในพร็อพเพอร์ตี้ supportedMediaCommands เมื่อมีการประกาศสถานะ แอปผู้ส่งที่เชื่อมต่อจะอัปเดตปุ่มใน UI ของตนตามนั้น
ดูข้อมูลเพิ่มเติมเกี่ยวกับคำสั่งสื่อและอุปกรณ์ระบบสัมผัสที่รองรับได้ที่คู่มือ Accessing UI controls
การจัดการสถานะการดำเนินการของผู้ใช้
เมื่อผู้ใช้โต้ตอบกับ UI หรือส่งคำสั่งเสียง ผู้ใช้จะควบคุมการเล่นเนื้อหาและพร็อพเพอร์ตี้ที่เกี่ยวข้องกับรายการที่เล่นได้ SDK จะจัดการคำขอที่ควบคุมการเล่นโดยอัตโนมัติ คำขอที่แก้ไขพร็อพเพอร์ตี้ของรายการที่กำลังเล่นอยู่ เช่น คำสั่ง LIKE กำหนดให้แอปพลิเคชันตัวรับต้องจัดการคำขอเหล่านั้น SDK มีชุด API เพื่อจัดการคำขอประเภทเหล่านี้ คุณต้องดำเนินการต่อไปนี้เพื่อรองรับคำขอเหล่านี้
- ตั้งค่า
MediaInformationuserActionStatesตามค่ากำหนดของผู้ใช้เมื่อโหลดรายการสื่อ - สกัดกั้นข้อความ
USER_ACTIONและพิจารณาการดำเนินการที่ขอ - อัปเดต
UserActionStateMediaInformationเพื่ออัปเดต 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
| คำสั่ง | คำอธิบาย |
|---|---|
| Google Play | เล่นหรือเล่นต่อจากสถานะหยุดชั่วคราว |
| หยุดชั่วคราว | หยุดเนื้อหาที่เล่นอยู่ชั่วคราว |
| ก่อนหน้า | ข้ามไปยังรายการสื่อก่อนหน้าในคิวสื่อ |
| ถัดไป | ข้ามไปยังรายการสื่อถัดไปในคิวสื่อ |
| หยุด | หยุดสื่อที่กำลังเล่นอยู่ |
| ไม่เล่นซ้ำ | ปิดใช้การเล่นซ้ำรายการสื่อในคิวเมื่อเล่นรายการสุดท้ายในคิวเสร็จแล้ว |
| เล่นซ้ำเพลงเดียว | เล่นสื่อที่กำลังเล่นอยู่ซ้ำไปเรื่อยๆ |
| เล่นซ้ำทั้งหมด | เล่นซ้ำทุกรายการในคิวเมื่อเล่นรายการสุดท้ายในคิวแล้ว |
| เล่นซ้ำทั้งหมดและสุ่ม | เมื่อเล่นรายการสุดท้ายในคิวเสร็จแล้ว ให้สุ่มคิวและเล่นซ้ำรายการทั้งหมดในคิว |
| สุ่ม | สุ่มรายการสื่อในคิวสื่อ |
| เปิด/ปิดคำบรรยายแทนเสียง | เปิด/ปิดใช้คำบรรยายแทนเสียงสำหรับสื่อของคุณ นอกจากนี้ คุณยังเปิด/ปิดใช้ตามภาษาได้ด้วย |
| กรอไปที่เวลาสัมบูรณ์ | ข้ามไปยังเวลาสัมบูรณ์ที่ระบุ |
| กรอไปยังเวลาที่สัมพันธ์กับเวลาปัจจุบัน | ข้ามไปข้างหน้าหรือย้อนกลับตามระยะเวลาที่ระบุโดยสัมพันธ์กับเวลาที่เล่นอยู่ |
| เล่นอีกครั้ง | รีสตาร์ทสื่อที่กำลังเล่นอยู่ หรือเล่นรายการสื่อที่เล่นล่าสุดหากไม่มีสื่อใดเล่นอยู่ |
| ตั้งค่าอัตราการเล่น | ปรับเปลี่ยนอัตราการเล่นสื่อ ซึ่งควรได้รับการจัดการโดยค่าเริ่มต้น คุณสามารถใช้ตัวสกัดกั้นข้อความ 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 ไม่เรียกใช้การกรอในแอปพลิเคชัน Web Receiver
สำหรับคำสั่งสื่อที่แอปพลิเคชันของคุณไม่รองรับ ให้แสดงสาเหตุข้อผิดพลาดที่เหมาะสม เช่น 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
ข้อมูลเมตาและการแคสต์เสียง
แม้ว่าตัวรับสัญญาณบนเว็บจะจัดการคำสั่งเสียงโดยค่าเริ่มต้น แต่คุณควรตรวจสอบว่าข้อมูลเมตาของเนื้อหาสมบูรณ์และถูกต้อง ซึ่งจะช่วยให้ Assistant จัดการคำสั่งเสียงได้อย่างถูกต้อง และข้อมูลเมตาจะแสดงอย่างถูกต้องในอินเทอร์เฟซประเภทใหม่ๆ เช่น แอป Google Home และจออัจฉริยะอย่าง Google Home Hub
การถ่ายโอนสตรีม
การคงสถานะเซสชันเป็นพื้นฐานของการถ่ายโอนสตรีม ซึ่งผู้ใช้สามารถย้ายสตรีมเสียงและวิดีโอที่มีอยู่ไปยังอุปกรณ์ต่างๆ โดยใช้คำสั่งเสียง, แอป Google Home หรือจออัจฉริยะ สื่อจะหยุดเล่นในอุปกรณ์เครื่องหนึ่ง (ต้นทาง) และเล่นต่อในอุปกรณ์อีกเครื่องหนึ่ง (ปลายทาง) อุปกรณ์แคสต์ที่มีเฟิร์มแวร์เวอร์ชันล่าสุดสามารถทำหน้าที่เป็นต้นทางหรือปลายทางในการถ่ายโอนสตรีมได้
ขั้นตอนของเหตุการณ์สำหรับการถ่ายโอนสตรีมมีดังนี้
- ในอุปกรณ์ต้นทาง ให้ทำดังนี้
- สื่อหยุดเล่น
- แอปพลิเคชันตัวรับสัญญาณบนเว็บจะได้รับคำสั่งให้บันทึกสถานะสื่อปัจจุบัน
- แอปพลิเคชัน Web Receiver ปิดอยู่
- ในอุปกรณ์ปลายทาง ให้ทำดังนี้
- โหลดแอปพลิเคชัน Web Receiver แล้ว
- แอปพลิเคชันตัวรับสัญญาณบนเว็บจะได้รับคำสั่งให้คืนค่าสถานะสื่อที่บันทึกไว้
- สื่อจะเล่นต่อ
องค์ประกอบของสถานะสื่อมีดังนี้
- ตำแหน่งหรือการประทับเวลาที่เฉพาะเจาะจงของเพลง วิดีโอ หรือรายการสื่อ
- ตำแหน่งของเพลงในคิวที่กว้างขึ้น (เช่น เพลย์ลิสต์หรือวิทยุศิลปิน)
- ผู้ใช้ที่ผ่านการตรวจสอบสิทธิ์
- สถานะการเล่น (เช่น กำลังเล่นหรือหยุดชั่วคราว)
กำลังเปิดใช้การถ่ายโอนสตรีม
วิธีใช้การถ่ายโอนสตรีมสำหรับ Web Receiver
- อัปเดต
supportedMediaCommandsด้วยคำสั่งSTREAM_TRANSFERดังนี้playerManager.addSupportedMediaCommands( cast.framework.messages.Command.STREAM_TRANSFER, true);
- ลบล้างตัวสกัดกั้นข้อความ
SESSION_STATEและRESUME_SESSION(ไม่บังคับ) ตามที่อธิบายไว้ในการคงสถานะเซสชัน ลบล้างค่าเหล่านี้เฉพาะในกรณีที่จำเป็นต้องจัดเก็บข้อมูลที่กำหนดเองเป็นส่วนหนึ่งของสแนปชอตเซสชัน ไม่เช่นนั้น การติดตั้งใช้งานเริ่มต้นสำหรับการคงสถานะเซสชันจะรองรับการถ่ายโอนสตรีม
การคงสถานะเซสชัน
Web Receiver 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 การโหลดล่วงหน้าจะเกิดขึ้นโดยเร็วที่สุด ดังนั้น หากมีการระบุค่าการโหลดล่วงหน้าที่มีขนาดใหญ่มากใน queueItem คุณจะได้รับผลลัพธ์ที่ว่าเมื่อใดก็ตามที่เราเล่นรายการปัจจุบัน เราจะโหลดรายการถัดไปล่วงหน้าอยู่แล้ว อย่างไรก็ตาม เราปล่อยให้การตั้งค่าและตัวเลือกนี้เป็นของนักพัฒนาแอป เนื่องจากค่านี้อาจส่งผลต่อแบนด์วิดท์และประสิทธิภาพการสตรีมของรายการที่กำลังเล่นอยู่
การโหลดล่วงหน้าจะใช้ได้กับเนื้อหาสตรีมมิง HLS, DASH และ Smooth โดยค่าเริ่มต้น
ระบบจะไม่โหลดไฟล์วิดีโอ MP4 และไฟล์เสียงปกติ เช่น MP3 ไว้ล่วงหน้า เนื่องจากอุปกรณ์แคสต์รองรับองค์ประกอบสื่อเพียงรายการเดียว และไม่สามารถใช้เพื่อโหลดล่วงหน้าขณะที่เนื้อหาที่มีอยู่ยังคงเล่นอยู่
ข้อความที่กำหนดเอง
การแลกเปลี่ยนข้อความเป็นวิธีการโต้ตอบหลักสำหรับแอปพลิเคชันตัวรับสัญญาณบนเว็บ
ผู้ส่งจะส่งข้อความไปยังตัวรับสัญญาณบนเว็บโดยใช้ API ของผู้ส่งสำหรับแพลตฟอร์มที่ผู้ส่งใช้อยู่ (Android, iOS, เว็บ) ออบเจ็กต์เหตุการณ์ (ซึ่งเป็นการแสดงข้อความ) ที่ส่งไปยัง Listener เหตุการณ์มีองค์ประกอบข้อมูล (event.data) โดยที่ข้อมูลจะใช้พร็อพเพอร์ตี้ของประเภทเหตุการณ์ที่เฉพาะเจาะจง
แอปพลิเคชัน 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 Receiver สามารถส่งข้อความไปยังผู้ส่งแต่ละราย ไม่ว่าจะเป็นการตอบกลับข้อความที่ได้รับหรือเนื่องจากการเปลี่ยนแปลงสถานะของแอปพลิเคชัน นอกเหนือจากการรับส่งข้อความแบบจุดต่อจุด (จำกัดที่ 64 KB) แล้ว ตัวรับสัญญาณบนเว็บยังสามารถประกาศข้อความไปยังผู้ส่งที่เชื่อมต่อทั้งหมดได้ด้วย
Cast สำหรับอุปกรณ์เสียง
ดูคู่มือ 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 แต่แพลตฟอร์ม Cast อื่นๆ รวมถึง Android TV อาจแสดงหน้าเว็บได้สูงสุด 1080p ตรวจสอบว่าหน้าตัวรับสัญญาณปรับขนาดได้อย่างเหมาะสมที่ความละเอียดต่างๆ