1. ภาพรวม
Codelab นี้จะสอนวิธีแก้ไขแอปวิดีโอบนเว็บที่มีอยู่เพื่อแคสต์เนื้อหาบนอุปกรณ์ที่พร้อมใช้งาน Google Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยังทีวีได้ ผู้ใช้จะใช้อุปกรณ์เคลื่อนที่เป็นรีโมตคอนโทรลในการเล่นสื่อบนทีวีได้
Google Cast SDK ช่วยให้คุณขยายแอปเพื่อควบคุมทีวีหรือระบบเสียงได้ Cast SDK ช่วยให้คุณสามารถเพิ่มคอมโพเนนต์ UI ที่จำเป็นได้ตามรายการตรวจสอบการออกแบบของ Google Cast
รายการตรวจสอบสำหรับการออกแบบของ Google Cast มีไว้เพื่อมอบประสบการณ์ของผู้ใช้ Cast ที่เรียบง่ายและคาดเดาได้ในทุกแพลตฟอร์มที่รองรับ
เราจะสร้างอะไร
เมื่อเสร็จสิ้น Codelab นี้แล้ว คุณจะมีแอปวิดีโอบนเว็บของ Chrome ที่จะแคสต์วิดีโอไปยังอุปกรณ์ Google Cast ได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีเพิ่ม Google Cast SDK ลงในแอปวิดีโอตัวอย่าง
- วิธีเพิ่มปุ่ม "แคสต์" เพื่อเลือกอุปกรณ์ Google Cast
- วิธีเชื่อมต่อกับอุปกรณ์แคสต์และเปิดใช้งานเครื่องรับสื่อ
- วิธีแคสต์วิดีโอ
- วิธีผสานรวม Cast Connect
สิ่งที่คุณต้องมี
- เบราว์เซอร์ Google Chrome เวอร์ชันล่าสุด
- บริการโฮสติ้ง HTTPS เช่น โฮสติ้งของ Firebase หรือ ngrok
- อุปกรณ์ Google Cast เช่น Chromecast หรือ Android TV ที่กำหนดค่าการเข้าถึงอินเทอร์เน็ต
- ทีวีหรือจอภาพที่มีอินพุต HDMI
- คุณต้องใช้ Chromecast พร้อม Google TV เพื่อทดสอบการผสานรวม Cast Connect แต่จะไม่บังคับสำหรับส่วนอื่นของ Codelab หากไม่มี ให้ข้ามขั้นตอนเพิ่มการสนับสนุน Cast Connect ในตอนท้ายของบทแนะนำนี้
ประสบการณ์การใช้งาน
- คุณจะต้องมีความรู้ด้านการพัฒนาเว็บมาก่อน
- คุณจะต้องมีความรู้เบื้องต้นเกี่ยวกับการดูทีวีด้วย :)
คุณจะใช้บทแนะนำนี้อย่างไร
คุณจะให้คะแนนประสบการณ์การสร้างเว็บแอปอย่างไร
คุณจะให้คะแนนประสบการณ์ในการดูทีวีอย่างไร
2. รับโค้ดตัวอย่าง
คุณดาวน์โหลดโค้ดตัวอย่างทั้งหมดลงในคอมพิวเตอร์ได้...
แล้วแตกไฟล์ ZIP ที่ดาวน์โหลดมา
3. เรียกใช้แอปตัวอย่าง
ก่อนอื่น มาดูตัวอย่างแอปตัวอย่างที่เสร็จสมบูรณ์ แอปนี้เป็นโปรแกรมเล่นวิดีโอพื้นฐาน ผู้ใช้สามารถเลือกวิดีโอจากรายการ แล้วเล่นวิดีโอในอุปกรณ์หรือแคสต์ไปยังอุปกรณ์ Google Cast ก็ได้
หากต้องการใช้ URL เวอร์ชันสมบูรณ์ จะต้องมีการโฮสต์
หากยังไม่มีเซิร์ฟเวอร์ ให้ใช้โฮสติ้งของ Firebase หรือ ngrok
เรียกใช้เซิร์ฟเวอร์
เมื่อตั้งค่าบริการที่ต้องการแล้ว ให้ไปที่ app-done
แล้วเริ่มต้นเซิร์ฟเวอร์
ในเบราว์เซอร์ ให้ไปที่ URL https สำหรับตัวอย่างที่คุณโฮสต์ไว้
- จากนั้นคุณจะเห็นแอปวิดีโอปรากฏขึ้น
- คลิกปุ่ม "แคสต์" และเลือกอุปกรณ์ Google Cast ของคุณ
- เลือกวิดีโอ แล้วคลิกปุ่มเล่น
- วิดีโอจะเริ่มเล่นในอุปกรณ์ Google Cast
คลิกปุ่มหยุดชั่วคราวในองค์ประกอบวิดีโอเพื่อหยุดวิดีโอบนตัวรับชั่วคราว คลิกปุ่มเล่นในองค์ประกอบวิดีโอเพื่อเล่นวิดีโอต่ออีกครั้ง
คลิกปุ่ม "แคสต์" เพื่อหยุดแคสต์ไปยังอุปกรณ์ Google Cast
ก่อนดำเนินการต่อ ให้หยุดเซิร์ฟเวอร์
4. เตรียมเริ่มโปรเจ็กต์
เราต้องเพิ่มการรองรับ Google Cast ไปยังแอปเริ่มต้นที่คุณดาวน์โหลด คำศัพท์ของ Google Cast บางส่วนที่เราจะใช้ใน Codelab มีดังนี้
- แอปผู้ส่งทำงานบนอุปกรณ์เคลื่อนที่หรือแล็ปท็อป
- แอปตัวรับทำงานบนอุปกรณ์ Google Cast
ตอนนี้คุณพร้อมที่จะต่อยอดจากโปรเจ็กต์เริ่มต้นโดยใช้เครื่องมือแก้ไขข้อความที่คุณชอบแล้ว
- เลือกไดเรกทอรี
app-start
จากการดาวน์โหลดโค้ดตัวอย่าง - เรียกใช้แอปโดยใช้เซิร์ฟเวอร์และสำรวจ UI
โปรดทราบว่า ขณะที่คุณดำเนินการผ่าน Codelab นี้ คุณจะต้องโฮสต์ตัวอย่างดังกล่าวอีกครั้งบนเซิร์ฟเวอร์ของคุณโดยขึ้นอยู่กับบริการ
การออกแบบแอป
แอปจะดึงรายการวิดีโอจากเว็บเซิร์ฟเวอร์ระยะไกลและแสดงรายการให้ผู้ใช้เรียกดู ผู้ใช้สามารถเลือกวิดีโอเพื่อดูรายละเอียดหรือเล่นวิดีโอบนอุปกรณ์เคลื่อนที่ก็ได้
แอปประกอบด้วยมุมมองหลัก 1 มุมมองที่กำหนดไว้ใน index.html
และตัวควบคุมหลัก CastVideos.js.
index.html
ไฟล์ HTML นี้จะประกาศ UI เกือบทั้งหมดของเว็บแอป
การดูมีไม่กี่ส่วน คือเรามี div#main_video
ซึ่งมีองค์ประกอบวิดีโอ สำหรับ div ของวิดีโอ เรามี div#media_control
ซึ่งกำหนดการควบคุมทั้งหมดสำหรับองค์ประกอบวิดีโอ ด้านล่างคือ media_info
ซึ่งจะแสดงรายละเอียดของวิดีโอในมุมมอง สุดท้าย div carousel
จะแสดงรายการวิดีโอใน div
ไฟล์ index.html
จะเปิดเครื่อง Cast SDK ด้วย และบอกให้ฟังก์ชัน CastVideos
โหลด
เนื้อหาส่วนใหญ่ที่จะสร้างองค์ประกอบเหล่านี้มีการกำหนด แทรก และควบคุมใน CastVideos.js
เรามาดูกันเลย
CastVideos.js
สคริปต์นี้จัดการตรรกะทั้งหมดสำหรับเว็บแอปแคสต์วิดีโอ รายการวิดีโอและข้อมูลเมตาที่เกี่ยวข้องซึ่งระบุไว้ใน CastVideos.js
อยู่ในออบเจ็กต์ชื่อ mediaJSON
มีส่วนหลักๆ อยู่ 2-3 ส่วนที่มีหน้าที่รับผิดชอบในการจัดการและเล่นวิดีโอทั้งในเครื่องและจากระยะไกล โดยรวมแล้วแอปนี้เป็นเว็บแอปพลิเคชันที่ค่อนข้างตรงไปตรงมา
CastPlayer
เป็นคลาสหลักที่จัดการทั้งแอป การตั้งค่าโปรแกรมเล่น การเลือกสื่อ และเชื่อมโยงเหตุการณ์กับ PlayerHandler
สำหรับการเล่นสื่อ CastPlayer.prototype.initializeCastPlayer
คือเมธอดที่ใช้ตั้งค่าฟังก์ชันการแคสต์ทั้งหมด CastPlayer.prototype.switchPlayer
จะเปลี่ยนสถานะระหว่างโปรแกรมเล่นในเครื่องและโปรแกรมเล่นระยะไกล CastPlayer.prototype.setupLocalPlayer
และ CastPlayer.prototype.setupRemotePlayer
เริ่มต้นโปรแกรมเล่นในเครื่องและระยะไกล
PlayerHandler
เป็นชั้นเรียนที่มีหน้าที่รับผิดชอบในการจัดการการเล่นสื่อ ยังมีวิธีอื่นๆ อีกมากมายที่ใช้ดูรายละเอียดของการจัดการสื่อและการเล่น
คำถามที่พบบ่อย
5. การเพิ่มปุ่ม "แคสต์"
แอปพลิเคชันที่พร้อมใช้งาน Cast จะแสดงปุ่ม "แคสต์" ในองค์ประกอบวิดีโอ การคลิกปุ่ม "แคสต์" จะแสดงรายการอุปกรณ์แคสต์ที่ผู้ใช้เลือกได้ หากผู้ใช้เล่นเนื้อหาบนอุปกรณ์ของผู้ส่ง การเลือกอุปกรณ์แคสต์จะเริ่มต้นหรือเล่นต่อในอุปกรณ์แคสต์นั้น ผู้ใช้สามารถคลิกปุ่ม "แคสต์" และหยุดแคสต์แอปพลิเคชันไปยังอุปกรณ์แคสต์ได้ทุกเมื่อในระหว่างเซสชันการแคสต์ ผู้ใช้ต้องสามารถเชื่อมต่อหรือยกเลิกการเชื่อมต่อจากอุปกรณ์ Cast ขณะอยู่ในหน้าจอแอปพลิเคชันใดก็ได้ตามที่อธิบายไว้ในรายการตรวจสอบการออกแบบของ Google Cast
การกำหนดค่า
โปรเจ็กต์เริ่มต้นต้องใช้ทรัพยากร Dependency และการตั้งค่าเหมือนกับที่คุณใช้สำหรับแอปตัวอย่างที่สมบูรณ์ แต่ครั้งนี้โฮสต์เนื้อหาของ app-start
ในเบราว์เซอร์ ให้ไปที่ URL https
สำหรับตัวอย่างที่คุณโฮสต์ไว้
โปรดทราบว่าขณะที่ทำการเปลี่ยนแปลง คุณจะต้องโฮสต์ตัวอย่างดังกล่าวอีกครั้งบนเซิร์ฟเวอร์ของคุณโดยขึ้นอยู่กับบริการ
การเริ่มต้น
เฟรมเวิร์กการแคสต์มีออบเจ็กต์ Singleton สำหรับใช้งานทั่วโลก ซึ่งก็คือ CastContext
ซึ่งประสานงานกิจกรรมทั้งหมดของเฟรมเวิร์ก ออบเจ็กต์นี้ต้องเริ่มต้นตั้งแต่เนิ่นๆ ในวงจรของแอปพลิเคชัน โดยทั่วไปจะเรียกจาก Callback ที่กำหนดให้กับ window['__onGCastApiAvailable']
ซึ่งมีการเรียกใช้หลังจากโหลด Cast SDK แล้วและพร้อมใช้งาน ในกรณีนี้ ระบบจะเรียก CastContext
ใน CastPlayer.prototype.initializeCastPlayer
ซึ่งถูกเรียกจาก Callback ที่กล่าวถึงข้างต้น
ต้องระบุออบเจ็กต์ JSON options
เมื่อเริ่มต้น CastContext
คลาสนี้มีตัวเลือกที่ส่งผลต่อลักษณะการทำงานของเฟรมเวิร์ก สิ่งสำคัญที่สุดคือรหัสแอปพลิเคชันของผู้รับ ซึ่งใช้เพื่อกรองรายการอุปกรณ์แคสต์ที่พร้อมใช้งานเพื่อแสดงเฉพาะอุปกรณ์ที่เรียกใช้แอปที่ระบุได้ และเพื่อเปิดแอปพลิเคชันตัวรับเมื่อเริ่มเซสชันการแคสต์
เมื่อคุณพัฒนาแอปที่พร้อมใช้งาน Cast ขึ้นมาเอง คุณจะต้องลงทะเบียนเป็นนักพัฒนาซอฟต์แวร์ Cast จากนั้นขอรับรหัสแอปพลิเคชันสำหรับแอป สำหรับ Codelab นี้ เราจะใช้รหัสแอปตัวอย่าง
เพิ่มโค้ดต่อไปนี้ลงใน index.html
ที่ท้ายสุดของส่วน body
:
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
เพิ่มโค้ดต่อไปนี้ลงใน index.html
เพื่อเริ่มต้นแอป CastVideos
และเริ่มต้น CastContext
:
<script src="CastVideos.js"></script>
<script type="text/javascript">
var castPlayer = new CastPlayer();
window['__onGCastApiAvailable'] = function(isAvailable) {
if (isAvailable) {
castPlayer.initializeCastPlayer();
}
};
</script>
ตอนนี้ เราต้องเพิ่มเมธอดใหม่ใน CastVideos.js
ซึ่งสอดคล้องกับเมธอดที่เราเพิ่งเรียกใน index.html
เพิ่มเมธอดใหม่ชื่อ initializeCastPlayer
ซึ่งตั้งค่าตัวเลือกใน CastContext และเริ่มต้น RemotePlayer
และ RemotePlayerControllers
ใหม่
/**
* This method sets up the CastContext, and a few other members
* that are necessary to play and control videos on a Cast
* device.
*/
CastPlayer.prototype.initializeCastPlayer = function() {
var options = {};
// Set the receiver application ID to your own (created in
// the Google Cast Developer Console), or optionally
// use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
options.receiverApplicationId = 'C0868879';
// Auto join policy can be one of the following three:
// ORIGIN_SCOPED - Auto connect from same appId and page origin
// TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab
// PAGE_SCOPED - No auto connect
options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED;
cast.framework.CastContext.getInstance().setOptions(options);
this.remotePlayer = new cast.framework.RemotePlayer();
this.remotePlayerController = new cast.framework.RemotePlayerController(this.remotePlayer);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
this.switchPlayer.bind(this)
);
};
สุดท้าย เราจะต้องสร้างตัวแปรสำหรับ RemotePlayer
และ RemotePlayerController
ดังนี้
var CastPlayer = function() {
//...
/* Cast player variables */
/** @type {cast.framework.RemotePlayer} */
this.remotePlayer = null;
/** @type {cast.framework.RemotePlayerController} */
this.remotePlayerController = null;
//...
};
ปุ่ม "แคสต์"
เมื่อเริ่มต้น CastContext
แล้ว เราต้องเพิ่มปุ่ม "แคสต์" เพื่อให้ผู้ใช้เลือกอุปกรณ์แคสต์ได้ Cast SDK มีคอมโพเนนต์ปุ่ม "แคสต์" ที่ชื่อ google-cast-launcher
ที่มีรหัส "castbutton"
และสามารถเพิ่มลงในองค์ประกอบวิดีโอของแอปพลิเคชันได้ง่ายๆ เพียงเพิ่ม button
ในส่วน media_control
นี่คือลักษณะขององค์ประกอบปุ่ม
<google-cast-launcher id="castbutton"></google-cast-launcher>
เพิ่มโค้ดต่อไปนี้ลงใน index.html
ในส่วน media_control
:
<div id="media_control">
<div id="play"></div>
<div id="pause"></div>
<div id="progress_bg"></div>
<div id="progress"></div>
<div id="progress_indicator"></div>
<div id="fullscreen_expand"></div>
<div id="fullscreen_collapse"></div>
<google-cast-launcher id="castbutton"></google-cast-launcher>
<div id="audio_bg"></div>
<div id="audio_bg_track"></div>
<div id="audio_indicator"></div>
<div id="audio_bg_level"></div>
<div id="audio_on"></div>
<div id="audio_off"></div>
<div id="duration">00:00:00</div>
</div>
ตอนนี้ให้รีเฟรชหน้าดังกล่าวในเบราว์เซอร์ Chrome คุณจะเห็นปุ่ม "แคสต์" ในองค์ประกอบวิดีโอ และเมื่อคลิกที่ปุ่มนี้ ระบบจะแสดงอุปกรณ์แคสต์ในเครือข่ายภายในของคุณ เบราว์เซอร์ Chrome จะจัดการการค้นพบอุปกรณ์โดยอัตโนมัติ เลือกอุปกรณ์แคสต์แล้วแอปตัวรับสัญญาณตัวอย่างจะโหลดขึ้นในอุปกรณ์แคสต์
เรายังไม่ได้รองรับการเล่นสื่อใดๆ คุณจึงยังไม่สามารถเล่นวิดีโอบนอุปกรณ์ Cast ได้ คลิกปุ่ม "แคสต์" เพื่อหยุดแคสต์
6. กำลังแคสต์เนื้อหาวิดีโอ
เราจะขยายแอปตัวอย่างให้เล่นวิดีโอจากระยะไกลบนอุปกรณ์แคสต์ได้ด้วย ในการทำเช่นนั้น เราต้องฟังเหตุการณ์ต่างๆ ที่สร้างโดยเฟรมเวิร์กของ Cast
กำลังแคสต์สื่อ
หากคุณต้องการเล่นสื่อในอุปกรณ์ Cast ในระดับสูง คุณจะต้องดำเนินการต่อไปนี้
- สร้างออบเจ็กต์
MediaInfo
JSON
จาก Cast SDK ที่จำลองรายการสื่อ - ผู้ใช้เชื่อมต่อกับอุปกรณ์แคสต์เพื่อเปิดใช้งานแอปพลิเคชันตัวรับสัญญาณ
- โหลดออบเจ็กต์
MediaInfo
ลงในเครื่องรับและเล่นเนื้อหา - ติดตามสถานะสื่อ
- ส่งคำสั่งการเล่นไปยังผู้รับตามการโต้ตอบของผู้ใช้
ขั้นตอนที่ 1 เกี่ยวข้องกับการจับคู่ออบเจ็กต์หนึ่งกับอีกออบเจ็กต์ MediaInfo
เป็นสิ่งที่ Cast SDK เข้าใจและ mediaJSON
เป็นการสรุปรวมแอปสำหรับรายการสื่อ เราสามารถจับคู่ mediaJSON
กับ MediaInfo
ได้โดยง่าย เราทำขั้นตอนที่ 2 ในส่วนก่อนหน้าไปแล้ว ขั้นตอนที่ 3 สามารถทำได้โดยง่ายด้วย Cast SDK
แอปตัวอย่าง CastPlayer
ได้แยกความแตกต่างระหว่างการเล่นในเครื่องกับการเล่นระยะไกลในเมธอด switchPlayer
อยู่แล้ว:
if (cast && cast.framework) {
if (this.remotePlayer.isConnected) {
//...
ใน Codelab นี้ คุณไม่จำเป็นต้องเข้าใจอย่างถ่องแท้ว่าตรรกะของโปรแกรมเล่นตัวอย่างทั้งหมดทำงานอย่างไร อย่างไรก็ตาม คุณต้องเข้าใจว่ามีเดียเพลเยอร์ของแอปจะต้องได้รับการแก้ไขเพื่อรับรู้การเล่นทั้งในเครื่องและระยะไกล
ตอนนี้โปรแกรมเล่นในเครื่องจะอยู่ในสถานะเล่นในเครื่องเสมอ เนื่องจากยังไม่ทราบข้อมูลเกี่ยวกับสถานะการแคสต์ เราจำเป็นต้องอัปเดต UI ตามการเปลี่ยนแปลงสถานะที่เกิดขึ้นในเฟรมเวิร์กของ Cast เช่น หากเราเริ่มแคสต์ เราจำเป็นต้องหยุดการเล่นในเครื่องและปิดใช้การควบคุมบางอย่าง ในทำนองเดียวกัน หากเราหยุดแคสต์เมื่ออยู่ในตัวควบคุมมุมมองนี้ เราจำเป็นต้องเปลี่ยนไปใช้การเล่นในเครื่อง เราจึงจำเป็นต้องรับฟังเหตุการณ์ต่างๆ ที่เฟรมเวิร์กของ Cast สร้างขึ้น
การจัดการเซสชันการแคสต์
สำหรับเฟรมเวิร์กการแคสต์ เซสชันการแคสต์จะรวมขั้นตอนการเชื่อมต่ออุปกรณ์ การเปิด (หรือการเข้าร่วมเซสชันที่มีอยู่) การเชื่อมต่อกับแอปพลิเคชันตัวรับสัญญาณ และการเริ่มต้นช่องทางควบคุมสื่อตามความเหมาะสม ช่องทางควบคุมสื่อคือวิธีที่เฟรมเวิร์กของ Cast ส่งและรับข้อความที่เกี่ยวข้องกับการเล่นสื่อจากตัวรับ
เซสชันการแคสต์จะเริ่มต้นโดยอัตโนมัติเมื่อผู้ใช้เลือกอุปกรณ์จากปุ่ม "แคสต์" และจะหยุดโดยอัตโนมัติเมื่อผู้ใช้ยกเลิกการเชื่อมต่อ เฟรมเวิร์กของ Cast จะจัดการการเชื่อมต่อเซสชันตัวรับอีกครั้งเนื่องจากปัญหาเกี่ยวกับเครือข่ายโดยอัตโนมัติ
เซสชันการแคสต์จะได้รับการจัดการโดย CastSession
ซึ่งเข้าถึงได้ผ่าน cast.framework.CastContext.getInstance().getCurrentSession()
คุณใช้ Callback ของ EventListener
เพื่อตรวจสอบเหตุการณ์ของเซสชันได้ เช่น การสร้าง การระงับ การกลับมาทำงานอีกครั้ง และการสิ้นสุด
ในแอปพลิเคชันปัจจุบัน เราจัดการเซสชันและการจัดการสถานะทั้งหมดโดยใช้เมธอด setupRemotePlayer
มาเริ่มกำหนดค่าดังกล่าวในแอปโดยเพิ่มโค้ดต่อไปนี้ลงใน CastVideos.js
กัน
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
this.playerHandler.setTarget(playerTarget);
// Setup remote player volume right on setup
// The remote player may have had a volume set from previous playback
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
}
var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = currentVolume + 'px';
p.style.marginTop = -currentVolume + 'px';
this.hideFullscreenButton();
this.playerHandler.play();
};
เรายังคงต้องเชื่อมโยงเหตุการณ์ทั้งหมดจาก Callback และจัดการเหตุการณ์ทั้งหมดที่เข้ามา หัวข้อนี้ค่อนข้างตรงไปตรงมา มาเริ่มกันเลย
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
// Add event listeners for player changes which may occur outside sender app
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
function() {
if (this.remotePlayer.isPaused) {
this.playerHandler.pause();
} else {
this.playerHandler.play();
}
}.bind(this)
);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,
function() {
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
} else {
this.playerHandler.unMute();
}
}.bind(this)
);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.VOLUME_LEVEL_CHANGED,
function() {
var newVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = newVolume + 'px';
p.style.marginTop = -newVolume + 'px';
}.bind(this)
);
// This object will implement PlayerHandler callbacks with
// remotePlayerController, and makes necessary UI updates specific
// to remote playback
var playerTarget = {};
playerTarget.play = function () {
if (this.remotePlayer.isPaused) {
this.remotePlayerController.playOrPause();
}
var vi = document.getElementById('video_image');
vi.style.display = 'block';
var localPlayer = document.getElementById('video_element');
localPlayer.style.display = 'none';
}.bind(this);
playerTarget.pause = function () {
if (!this.remotePlayer.isPaused) {
this.remotePlayerController.playOrPause();
}
}.bind(this);
playerTarget.stop = function () {
this.remotePlayerController.stop();
}.bind(this);
playerTarget.getCurrentMediaTime = function() {
return this.remotePlayer.currentTime;
}.bind(this);
playerTarget.getMediaDuration = function() {
return this.remotePlayer.duration;
}.bind(this);
playerTarget.updateDisplayMessage = function () {
document.getElementById('playerstate').style.display = 'block';
document.getElementById('playerstatebg').style.display = 'block';
document.getElementById('video_image_overlay').style.display = 'block';
document.getElementById('playerstate').innerHTML =
this.mediaContents[ this.currentMediaIndex]['title'] + ' ' +
this.playerState + ' on ' + castSession.getCastDevice().friendlyName;
}.bind(this);
playerTarget.setVolume = function (volumeSliderPosition) {
// Add resistance to avoid loud volume
var currentVolume = this.remotePlayer.volumeLevel;
var p = document.getElementById('audio_bg_level');
if (volumeSliderPosition < FULL_VOLUME_HEIGHT) {
var vScale = this.currentVolume * FULL_VOLUME_HEIGHT;
if (volumeSliderPosition > vScale) {
volumeSliderPosition = vScale + (pos - vScale) / 2;
}
p.style.height = volumeSliderPosition + 'px';
p.style.marginTop = -volumeSliderPosition + 'px';
currentVolume = volumeSliderPosition / FULL_VOLUME_HEIGHT;
} else {
currentVolume = 1;
}
this.remotePlayer.volumeLevel = currentVolume;
this.remotePlayerController.setVolumeLevel();
}.bind(this);
playerTarget.mute = function () {
if (!this.remotePlayer.isMuted) {
this.remotePlayerController.muteOrUnmute();
}
}.bind(this);
playerTarget.unMute = function () {
if (this.remotePlayer.isMuted) {
this.remotePlayerController.muteOrUnmute();
}
}.bind(this);
playerTarget.isMuted = function() {
return this.remotePlayer.isMuted;
}.bind(this);
playerTarget.seekTo = function (time) {
this.remotePlayer.currentTime = time;
this.remotePlayerController.seek();
}.bind(this);
this.playerHandler.setTarget(playerTarget);
// Setup remote player volume right on setup
// The remote player may have had a volume set from previous playback
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
}
var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = currentVolume + 'px';
p.style.marginTop = -currentVolume + 'px';
this.hideFullscreenButton();
this.playerHandler.play();
};
กำลังโหลดสื่อ
ใน Cast SDK RemotePlayer
และ RemotePlayerController
มีชุด API ที่ใช้งานง่ายสำหรับการจัดการการเล่นสื่อระยะไกลในตัวรับสัญญาณ สำหรับ CastSession
ที่รองรับการเล่นสื่อ SDK จะสร้างอินสแตนซ์ของ RemotePlayer
และ RemotePlayerController
โดยอัตโนมัติ คุณสามารถเข้าถึงได้โดยการสร้างอินสแตนซ์ของ cast.framework.RemotePlayer
และ cast.framework.RemotePlayerController
ตามลำดับ ดังที่แสดงใน Codelab ก่อนหน้านี้
ต่อไป เราต้องโหลดวิดีโอที่เลือกในปัจจุบันบนรีซีฟเวอร์โดยการสร้างออบเจ็กต์ MediaInfo ให้ SDK ประมวลผลและส่งไปในคำขอ เพิ่มโค้ดต่อไปนี้ลงใน setupRemotePlayer
เพื่อดำเนินการดังกล่าว
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
//...
playerTarget.load = function (mediaIndex) {
console.log('Loading...' + this.mediaContents[mediaIndex]['title']);
var mediaInfo = new chrome.cast.media.MediaInfo(
this.mediaContents[mediaIndex]['sources'][0], 'video/mp4');
mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();
mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;
mediaInfo.metadata.title = this.mediaContents[mediaIndex]['title'];
mediaInfo.metadata.images = [
{'url': MEDIA_SOURCE_ROOT + this.mediaContents[mediaIndex]['thumb']}];
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
this.playerHandler.loaded.bind(this.playerHandler),
function (errorCode) {
this.playerState = PLAYER_STATE.ERROR;
console.log('Remote media load error: ' +
CastPlayer.getErrorMessage(errorCode));
}.bind(this));
}.bind(this);
//...
};
ตอนนี้ ให้เพิ่มวิธีการในการสลับระหว่างการเล่นในเครื่องและการเล่นระยะไกล ดังนี้
/**
* This is a method for switching between the local and remote
* players. If the local player is selected, setupLocalPlayer()
* is run. If there is a cast device connected we run
* setupRemotePlayer().
*/
CastPlayer.prototype.switchPlayer = function() {
this.stopProgressTimer();
this.resetVolumeSlider();
this.playerHandler.stop();
this.playerState = PLAYER_STATE.IDLE;
if (cast && cast.framework) {
if (this.remotePlayer.isConnected) {
this.setupRemotePlayer();
return;
}
}
this.setupLocalPlayer();
};
สุดท้าย เพิ่มวิธีการจัดการข้อความแสดงข้อผิดพลาดของการแคสต์ ดังนี้
/**
* Makes human-readable message from chrome.cast.Error
* @param {chrome.cast.Error} error
* @return {string} error message
*/
CastPlayer.getErrorMessage = function(error) {
switch (error.code) {
case chrome.cast.ErrorCode.API_NOT_INITIALIZED:
return 'The API is not initialized.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.CANCEL:
return 'The operation was canceled by the user' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.CHANNEL_ERROR:
return 'A channel to the receiver is not available.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.EXTENSION_MISSING:
return 'The Cast extension is not available.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.INVALID_PARAMETER:
return 'The parameters to the operation were not valid.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE:
return 'No receiver was compatible with the session request.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.SESSION_ERROR:
return 'A session could not be created, or a session was invalid.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.TIMEOUT:
return 'The operation timed out.' +
(error.description ? ' :' + error.description : '');
}
};
เรียกใช้แอปได้เลย เชื่อมต่ออุปกรณ์ Cast และเริ่มเล่นวิดีโอ คุณควรเห็นวิดีโอกำลังเล่นอยู่บนเครื่องรับ
7. เพิ่มการรองรับ Cast Connect
ไลบรารีของ Cast Connect ช่วยให้แอปพลิเคชันของผู้ส่งที่มีอยู่สามารถสื่อสารกับแอปพลิเคชัน Android TV ผ่านโปรโตคอล Cast Cast Connect สร้างขึ้นจากโครงสร้างพื้นฐานของ Cast โดยแอป Android TV จะทำหน้าที่เป็นตัวรับสัญญาณ
การอ้างอิง
- เบราว์เซอร์ Chrome เวอร์ชัน M87 ขึ้นไป
ตั้งค่าความเข้ากันได้กับตัวรับสัญญาณ Android
ในการเปิดแอปพลิเคชัน Android TV หรือที่เรียกว่าตัวรับสัญญาณ Android เราต้องตั้งค่า Flag androidReceiverCompatible
เป็น "จริง" ในออบเจ็กต์ CastOptions
เพิ่มโค้ดต่อไปนี้ลงใน CastVideos.js
ในฟังก์ชัน initializeCastPlayer
:
var options = {};
...
options.androidReceiverCompatible = true;
cast.framework.CastContext.getInstance().setOptions(options);
ตั้งค่าข้อมูลเข้าสู่ระบบการเปิดตัว
ทางฝั่งผู้ส่ง คุณสามารถระบุ CredentialsData
เพื่อแสดงถึงผู้ที่จะเข้าร่วมเซสชันได้ credentials
เป็นสตริงที่ผู้ใช้กำหนดได้ตราบใดที่แอป ATV เข้าใจได้ ระบบจะส่งCredentialsData
ไปยังแอป Android TV ของคุณในช่วงเวลาเปิดหรือเข้าร่วมเท่านั้น หากคุณตั้งค่าอีกครั้งขณะเชื่อมต่ออยู่ ระบบจะไม่ส่งข้อความดังกล่าวไปยังแอป Android TV
หากต้องการตั้งค่าข้อมูลเข้าสู่ระบบการเปิดตัว คุณต้องกำหนด CredentialsData
ได้ทุกเมื่อหลังจากตั้งค่าตัวเลือกการเปิดใช้งานแล้ว
เพิ่มโค้ดต่อไปนี้ลงในชั้นเรียน CastVideos.js
ในส่วนฟังก์ชัน initializeCastPlayer
cast.framework.CastContext.getInstance().setOptions(options);
...
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
...
ตั้งค่าข้อมูลเข้าสู่ระบบในคำขอโหลด
ในกรณีที่แอป Web Receiver และแอป Android TV จัดการ credentials
แตกต่างกัน คุณอาจต้องกำหนดข้อมูลเข้าสู่ระบบแยกกันสำหรับแต่ละรายการ หากต้องการจัดการเรื่องดังกล่าว ให้เพิ่มโค้ดต่อไปนี้ใน CastVideos.js
ใต้ playerTarget.load
ในฟังก์ชัน setupRemotePlayer
...
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...
SDK จะจัดการโดยอัตโนมัติว่าจะใช้ข้อมูลเข้าสู่ระบบใดสำหรับเซสชันปัจจุบัน ทั้งนี้ขึ้นอยู่กับแอปตัวรับสัญญาณที่ผู้ส่งกำลังแคสต์ไป
การทดสอบ Cast Connect
ขั้นตอนการติดตั้ง APK ของ Android TV ใน Chromecast พร้อม Google TV มีดังนี้
- ค้นหาที่อยู่ IP ของอุปกรณ์ Android TV โดยปกติแล้ว วิธีการนี้จะอยู่ในส่วนการตั้งค่า > เครือข่ายและ อินเทอร์เน็ต > (ชื่อเครือข่ายที่อุปกรณ์เชื่อมต่ออยู่) ที่มือขวาจะแสดงรายละเอียดและ IP ของอุปกรณ์บนเครือข่าย
- ใช้ที่อยู่ IP ของอุปกรณ์เพื่อเชื่อมต่อกับอุปกรณ์ผ่าน ADB โดยใช้เทอร์มินัล:
$ adb connect <device_ip_address>:5555
- จากหน้าต่างเทอร์มินัล ให้ไปที่โฟลเดอร์ระดับบนสุดเพื่อดูตัวอย่าง Codelab ที่คุณดาวน์โหลดไว้ตอนเริ่มต้น Codelab นี้ เช่น
$ cd Desktop/chrome_codelab_src
- ติดตั้งไฟล์ .apk ในโฟลเดอร์นี้ไปยัง Android TV โดยเรียกใช้สิ่งต่อไปนี้
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- ตอนนี้คุณควรเห็นแอปด้วยชื่อแคสต์วิดีโอในเมนูแอปของคุณบนอุปกรณ์ Android TV แล้ว
- เรียกใช้รหัสผู้ส่งเว็บที่อัปเดตแล้วและสร้างเซสชันการแคสต์ด้วยอุปกรณ์ Android TV โดยใช้ไอคอนแคสต์ หรือเลือก
Cast..
จากเมนูแบบเลื่อนลงในเบราว์เซอร์ Chrome ขั้นตอนนี้จะเปิดแอป Android TV บนตัวรับสัญญาณ Android ของคุณ และให้คุณควบคุมการเล่นโดยใช้รีโมต Android TV ได้
8. ขอแสดงความยินดี
ตอนนี้คุณรู้วิธีเปิดใช้การแคสต์แอปวิดีโอโดยใช้วิดเจ็ต Cast SDK ในเว็บแอป Chrome แล้ว
โปรดดูรายละเอียดเพิ่มเติมในคู่มือนักพัฒนาผู้ส่งเว็บ