1. ภาพรวม
Codelab นี้จะสอนวิธีปรับแต่งแอปวิดีโอบนเว็บที่มีอยู่เพื่อแคสต์เนื้อหาบนอุปกรณ์ที่พร้อมใช้งาน Google Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยัง TV ได้ จากนั้นผู้ใช้จะใช้อุปกรณ์เคลื่อนที่เป็นรีโมตคอนโทรลในการเล่นสื่อบนทีวีได้
Google Cast SDK ช่วยให้คุณขยายแอปเพื่อควบคุมทีวีหรือระบบเสียงได้ Cast SDK ช่วยให้คุณเพิ่มคอมโพเนนต์ UI ที่จําเป็นได้ตามรายการตรวจสอบการออกแบบ Google Cast
รายการตรวจสอบการออกแบบ Google Cast มีไว้ให้ผู้ใช้ของ Cast ใช้งานได้ง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ
สิ่งที่เรากําลังจะสร้าง
หลังจากที่คุณสร้าง Codelab นี้เสร็จแล้ว คุณจะมีแอปวิดีโอบนเว็บ Chrome ซึ่งสามารถแคสต์วิดีโอไปยังอุปกรณ์ Google Cast ได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีเพิ่ม Google Cast SDK ลงในตัวอย่างแอปวิดีโอ
- วิธีการเพิ่มปุ่ม "แคสต์" เพื่อเลือกอุปกรณ์ Google Cast
- วิธีเชื่อมต่ออุปกรณ์ 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 ได้
หากต้องการใช้โฮสต์ที่เสร็จสมบูรณ์ คุณจะต้องโฮสต์โฮสต์
หากไม่มีเซิร์ฟเวอร์พร้อมให้ใช้งาน คุณก็ใช้ Firebase Hosting หรือ 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
การกำหนดค่า
โปรเจ็กต์เริ่มต้นต้องมีการอ้างอิงและการตั้งค่าเหมือนกับที่คุณดําเนินการกับแอปตัวอย่างที่สมบูรณ์ แต่ครั้งนี้โฮสต์เนื้อหาของ app-start
ในเบราว์เซอร์ ให้ไปที่ URL https
เพื่อดูตัวอย่างที่คุณโฮสต์
โปรดจําไว้ว่าเมื่อทําการเปลี่ยนแปลง คุณจะต้องโฮสต์ตัวอย่างบนเซิร์ฟเวอร์ของคุณใหม่โดยขึ้นอยู่กับบริการ
การเริ่มต้น
เฟรมเวิร์กแคสต์มีออบเจ็กต์ Singleton ทั่วโลก นั่นคือ CastContext
ซึ่งจะประสานงานกิจกรรมของเฟรมเวิร์กทั้งหมด ออบเจ็กต์นี้ต้องมีการเริ่มต้นในช่วงต้นของวงจรแอปพลิเคชัน ซึ่งมักจะถูกเรียกจากโค้ดเรียกกลับที่กําหนดให้กับ window['__onGCastApiAvailable']
ซึ่งเรียกใช้หลังจากที่โหลด SDK ของ Cast แล้วและพร้อมใช้งานแล้ว ในกรณีนี้ ระบบจะเรียก CastContext
ใน CastPlayer.prototype.initializeCastPlayer
ซึ่งเป็นการเรียกจากโค้ดเรียกกลับที่กล่าวถึงก่อนหน้านี้
ต้องระบุออบเจ็กต์ 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 และแอปตัวรับสัญญาณตัวอย่างจะโหลดในอุปกรณ์ Cast
เรายังไม่ได้รองรับการใช้งานการเล่นสื่อใดๆ เลย คุณจึงยังไม่สามารถเล่นวิดีโอในอุปกรณ์ 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) {
//...
การเขียนโค้ดนี้ไม่สําคัญสําหรับคุณที่จะต้องเข้าใจวิธีการทํางานของตรรกะของตัวอย่างโปรแกรมเล่นทั้งหมด อย่างไรก็ตาม คุณควรเข้าใจว่าโปรแกรมเล่นสื่อของแอปจะต้องได้รับการแก้ไขให้ทราบเกี่ยวกับการเล่นในเครื่องและการเล่นระยะไกล
ตอนนี้โปรแกรมเล่นในพื้นที่จะอยู่ในสถานะการเล่นในเครื่องอยู่เสมอ เนื่องจากยังไม่ไม่ทราบสถานะของการแคสต์ เราจําเป็นต้องอัปเดต UI ตามการเปลี่ยนแปลงสถานะที่เกิดขึ้นในกรอบการทํางาน Cast เช่น หากเราเริ่มแคสต์ เราจะต้องหยุดการเล่นในเครื่องและปิดใช้การควบคุมบางรายการ ในทํานองเดียวกัน หากเราหยุดส่งเมื่อเราอยู่ในตัวควบคุมมุมมองนี้ จะต้องสลับไปใช้การเล่นในเครื่อง ในการจัดการว่าเราจําเป็นต้องฟังเหตุการณ์ต่างๆ ที่เฟรมเวิร์ก Cast สร้างขึ้น
การจัดการเซสชันการแคสต์
สําหรับกรอบ "แคสต์" เซสชันแคสต์จะรวมขั้นตอนการเชื่อมต่ออุปกรณ์ การเปิด (หรือการเข้าร่วมเซสชันที่มีอยู่) การเชื่อมต่อกับแอปพลิเคชันตัวรับสัญญาณ และการเริ่มต้นช่องควบคุมสื่อตามความเหมาะสม ช่องทางการควบคุมสื่อคือวิธีที่เฟรมเวิร์ก Cast ส่งและรับข้อความที่เกี่ยวข้องกับการเล่นสื่อจากเครื่องรับ
เซสชันการแคสต์จะเริ่มต้นโดยอัตโนมัติเมื่อผู้ใช้เลือกอุปกรณ์จากปุ่ม "แคสต์" และจะหยุดโดยอัตโนมัติเมื่อผู้ใช้ยกเลิกการเชื่อมต่อ เฟรมเวิร์ก "แคสต์" จะเชื่อมต่อเซสชันผู้รับอีกครั้งเนื่องจากปัญหาการเชื่อมต่อโดยอัตโนมัติ
เซสชันการแคสต์ได้รับการจัดการโดย CastSession
ซึ่งสามารถเข้าถึงได้ทาง cast.framework.CastContext.getInstance().getCurrentSession()
คุณใช้โค้ดเรียกกลับ 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();
};
เรายังคงเชื่อมโยงเหตุการณ์ทั้งหมดจากโค้ดเรียกกลับ และจะจัดการกับเหตุการณ์ทั้งหมดที่เข้ามาใหม่ นี่เป็นเรื่องที่ค่อนข้างตรงไปตรงมา ดังนั้นเราต้องจัดการเรื่องนี้ตอนนี้เลย
/**
* 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();
};
สุดท้าย ให้เพิ่มวิธีการจัดการกับข้อความแสดงข้อผิดพลาดของ Cast ดังนี้
/**
* 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 Receiver ที่ใช้ร่วมกันได้
ในการเปิดใช้แอปพลิเคชัน Android TV หรือเรียกอีกอย่างว่า Android Receiver เราจําเป็นต้องตั้งค่าสถานะของ androidReceiverCompatible
เป็น true ในออบเจ็กต์ 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 Receiver ของคุณ และให้คุณควบคุมการเล่นโดยใช้รีโมต Android TV ของคุณ
8. ขอแสดงความยินดี
ตอนนี้คุณก็รู้วิธีเปิดใช้แอป "แคสต์วิดีโอ" โดยใช้วิดเจ็ต Cast SDK บนเว็บแอป Chrome แล้ว
สําหรับรายละเอียดเพิ่มเติม โปรดดูคู่มือนักพัฒนาซอฟต์แวร์ผู้ส่งเว็บ