1. ภาพรวม
Codelab นี้จะสอนวิธีสร้างแอป Web Receiver ที่กำหนดเองเพื่อเล่นเนื้อหาบนอุปกรณ์ที่พร้อมใช้งาน Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยังทีวีได้ จากนั้นผู้ใช้จะใช้อุปกรณ์เคลื่อนที่หรือเบราว์เซอร์ Chrome บนเดสก์ท็อปเป็นรีโมตคอนโทรลสำหรับการเล่นสื่อบนทีวีได้
Google Cast SDK ช่วยให้แอปของคุณควบคุมอุปกรณ์ที่พร้อมใช้งาน Google Cast ได้ (เช่น ทีวีหรือระบบเสียง) Cast SDK มีคอมโพเนนต์ UI ที่จำเป็นตามรายการตรวจสอบการออกแบบ Google Cast
รายการตรวจสอบการออกแบบ Google Cast มีไว้เพื่อให้ประสบการณ์การใช้งาน Cast ของผู้ใช้ง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ ดูเพิ่มเติมที่นี่
เราจะสร้างอะไร
เมื่อทำ Codelab นี้เสร็จแล้ว คุณจะมีแอป HTML5 ที่ทำหน้าที่เป็นตัวรับที่กำหนดเองของคุณเอง ซึ่งสามารถแสดงเนื้อหาวิดีโอในอุปกรณ์ที่พร้อมใช้งาน Cast
สิ่งที่คุณจะได้เรียนรู้
- วิธีตั้งค่าสําหรับการพัฒนาอุปกรณ์รับ
- ข้อมูลเบื้องต้นเกี่ยวกับอุปกรณ์รับที่พร้อมใช้งาน Cast ซึ่งอิงตามเฟรมเวิร์กแอปพลิเคชัน Cast
- วิธีรับวิดีโอที่แคสต์
- วิธีผสานรวมเครื่องมือบันทึกข้อบกพร่อง
- วิธีเพิ่มประสิทธิภาพตัวรับสำหรับจออัจฉริยะ
สิ่งที่คุณต้องมี
- เบราว์เซอร์ Google Chrome เวอร์ชันล่าสุด
- บริการโฮสติ้ง HTTPS เช่น Firebase Hosting หรือ ngrok
- อุปกรณ์ Google Cast เช่น Chromecast หรือ Android TV ที่กําหนดค่าให้เข้าถึงอินเทอร์เน็ตได้
- ทีวีหรือจอภาพที่มีอินพุต HDMI
ประสบการณ์การใช้งาน
- คุณจะต้องมีความรู้ด้านการพัฒนาเว็บมาก่อน
- คุณจะต้องมีความรู้เบื้องต้นเกี่ยวกับการดูทีวีด้วย :)
คุณจะใช้บทแนะนำนี้อย่างไร
คุณจะให้คะแนนประสบการณ์การสร้างเว็บแอปอย่างไร
คุณจะให้คะแนนประสบการณ์ในการดูทีวีเท่าใด
2. รับโค้ดตัวอย่าง
คุณดาวน์โหลดโค้ดตัวอย่างทั้งหมดลงในคอมพิวเตอร์ได้...
และแตกไฟล์ ZIP ที่ดาวน์โหลด
3. การติดตั้งใช้งานเครื่องรับในเครื่อง
อุปกรณ์แคสต์นั้นจะต้องโฮสต์ไว้ในที่ที่อุปกรณ์แคสต์สามารถเข้าถึงได้ จึงจะใช้เว็บรับสัญญาณกับอุปกรณ์แคสต์ได้ หากคุณมีเซิร์ฟเวอร์ที่รองรับ https อยู่แล้ว ให้ข้ามวิธีการต่อไปนี้และจด URL ไว้ เนื่องจากคุณจะต้องใช้ในส่วนถัดไป
หากไม่มีเซิร์ฟเวอร์ให้ใช้งาน คุณสามารถใช้โฮสติ้งของ Firebase หรือ ngrok
เรียกใช้เซิร์ฟเวอร์
เมื่อตั้งค่าบริการที่ต้องการแล้ว ให้ไปที่ app-start
แล้วเริ่มเซิร์ฟเวอร์
จดบันทึก URL ของผู้รับที่โฮสต์ไว้ คุณจะใช้รหัสนี้ในส่วนถัดไป
4. ลงทะเบียนแอปพลิเคชันในแผงควบคุมสำหรับนักพัฒนาแอป Cast
คุณต้องลงทะเบียนแอปพลิเคชันจึงจะเรียกใช้ตัวรับที่กำหนดเองซึ่งสร้างขึ้นในโค้ดแล็บนี้ในอุปกรณ์ Chromecast ได้ หลังจากลงทะเบียนแอปพลิเคชันแล้ว คุณจะได้รับรหัสแอปพลิเคชันที่แอปพลิเคชันผู้ส่งต้องใช้เพื่อเรียก API เช่น เพื่อเปิดแอปพลิเคชันผู้รับ
คลิก "เพิ่มแอปพลิเคชันใหม่"
เลือก "ตัวรับแบบกำหนดเอง" นี่คือสิ่งที่เรากำลังสร้าง
ป้อนรายละเอียดของผู้รับรายใหม่ โปรดใช้ URL ที่คุณได้รับ
ในส่วนสุดท้าย จดบันทึกรหัสแอปพลิเคชันที่กำหนดให้กับตัวรับใหม่
นอกจากนี้ คุณยังต้องลงทะเบียนอุปกรณ์ Google Cast เพื่อให้อุปกรณ์เข้าถึงแอปพลิเคชันตัวรับได้ก่อนที่จะเผยแพร่ เมื่อเผยแพร่แอปพลิเคชันตัวรับแล้ว แอปพลิเคชันจะพร้อมใช้งานในอุปกรณ์ Google Cast ทั้งหมด สําหรับวัตถุประสงค์ของโค้ดแล็บนี้ เราขอแนะนําให้ใช้แอปพลิเคชันตัวรับที่ยังไม่ได้เผยแพร่
คลิก "เพิ่มอุปกรณ์ใหม่"
ป้อนหมายเลขซีเรียลที่พิมพ์ไว้ที่ด้านหลังของอุปกรณ์แคสต์ แล้วตั้งชื่อที่สื่อความหมาย หรือจะดูหมายเลขซีเรียลด้วยการแคสต์หน้าจอใน Chrome เมื่อเข้าถึงแผงควบคุมสำหรับนักพัฒนาซอฟต์แวร์ Google Cast SDK ก็ได้
อุปกรณ์รับสัญญาณและอุปกรณ์จะใช้เวลา 5-15 นาทีในการเตรียมพร้อมสำหรับการทดสอบ หลังจากรอ 5-15 นาที คุณต้องรีบูตอุปกรณ์แคสต์
5. เรียกใช้แอปตัวอย่าง
ในขณะที่เรารอใบสมัครตัวรับสัญญาณใหม่จะพร้อมสำหรับการทดสอบ มาดูกันว่าตัวอย่างแอปตัวรับสัญญาณที่สมบูรณ์ตัวอย่างมีลักษณะอย่างไร ตัวรับที่เรากำลังจะสร้างจะเล่นสื่อโดยใช้สตรีมมิงแบบปรับอัตราบิตได้ (เราจะใช้เนื้อหาตัวอย่างที่เข้ารหัสสำหรับ Dynamic Adaptive Streaming over HTTP (DASH))
เปิดเครื่องมือ Command and Control (CaC) ในเบราว์เซอร์
- คุณควรเห็นเครื่องมือ CaC
- ใช้รหัสผู้รับตัวอย่าง "CC1AD845" เริ่มต้น แล้วคลิกปุ่ม "ตั้งค่ารหัสแอป"
- คลิกปุ่มแคสต์ที่ด้านซ้ายบน แล้วเลือกอุปกรณ์ Google Cast
- ไปที่แท็บ "โหลดสื่อ" ที่ด้านบน
- คลิกปุ่ม "โหลดตามเนื้อหา" เพื่อเล่นวิดีโอตัวอย่าง
- วิดีโอจะเริ่มเล่นในอุปกรณ์ Google Cast เพื่อแสดงลักษณะการทำงานของเครื่องรับพื้นฐานโดยใช้เครื่องรับเริ่มต้น
6. เตรียมโปรเจ็กต์เริ่มต้น
เราต้องเพิ่มการรองรับ Google Cast ไปยังแอปเริ่มต้นที่คุณดาวน์โหลด คําศัพท์บางส่วนของ Google Cast ที่เราจะใช้ใน Codelab นี้
- แอปผู้ส่งทำงานบนอุปกรณ์เคลื่อนที่หรือแล็ปท็อป
- แอปตัวรับที่ทำงานบนอุปกรณ์ Google Cast
ตอนนี้คุณก็พร้อมที่จะต่อยอดจากโปรเจ็กต์เริ่มต้นโดยใช้เครื่องมือแก้ไขข้อความที่คุณชอบแล้ว โดยทำดังนี้
- เลือกไดเรกทอรี
app-start
จากการดาวน์โหลดโค้ดตัวอย่าง - เปิด
js/receiver.js
และindex.html
โปรดทราบว่า http-server
น่าจะกำลังรับการเปลี่ยนแปลงที่คุณทำขณะทำงานผ่าน Codelab นี้ หากสังเกตเห็นว่าไม่ทำงาน ให้ลองหยุด http-server
แล้วรีสตาร์ท
การออกแบบแอป
แอปตัวรับจะเริ่มต้นเซสชันการแคสต์ และจะสแตนด์บายจนกว่าคำขอ LOAD (หรืออีกนัยหนึ่งคือคำสั่งให้เล่นสื่อ) จากผู้ส่งมาถึง
แอปประกอบด้วยมุมมองหลัก 1 รายการที่กําหนดไว้ใน index.html
และไฟล์ JavaScript 1 ไฟล์ชื่อ js/receiver.js
ซึ่งมีตรรกะทั้งหมดเพื่อให้ตัวรับของเราทํางานได้
index.html
ไฟล์ html นี้จะประกอบด้วย UI สําหรับแอปรับของเรา แต่ตอนนี้ยังว่างเปล่าอยู่ เราจะเพิ่มข้อมูลลงในไฟล์นี้ตลอดทั้งห้องทดลองโค้ด
receiver.js
สคริปต์นี้จะจัดการตรรกะทั้งหมดสําหรับแอปรับของเรา ตอนนี้เป็นเพียงไฟล์ว่างเปล่า แต่เราจะเปลี่ยนให้เป็นอุปกรณ์รับ Cast ที่ทํางานได้อย่างสมบูรณ์ด้วยโค้ดเพียงไม่กี่บรรทัดในส่วนถัดไป
7. อุปกรณ์รับการแคสต์พื้นฐาน
อุปกรณ์รับการแคสต์พื้นฐานจะเริ่มต้นเซสชัน Cast เมื่อเริ่มต้นระบบ ซึ่งจำเป็นต้องใช้เพื่อแจ้งให้แอปพลิเคชันผู้ส่งที่เชื่อมต่อทั้งหมดทราบว่าการเปิดใช้ผู้รับสำเร็จ นอกจากนี้ SDK ใหม่ยังได้รับการกําหนดค่าล่วงหน้าให้จัดการสื่อสตรีมมิงแบบปรับอัตราบิต (โดยใช้ DASH, HLS และ Smooth Streaming) และไฟล์ MP4 ธรรมดาได้ทันที มาลองกันเลย
การเริ่มต้น
เพิ่มโค้ดต่อไปนี้ลงใน index.html
ในส่วนหัว
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>
เพิ่มโค้ดต่อไปนี้ลงใน index.html
<body>
ก่อน <footer>
loading receiver.js,
เพื่อให้ SDK ตัวรับมีพื้นที่ในการเปิด UI ตัวรับเริ่มต้นซึ่งมาพร้อมกับสคริปต์ที่คุณเพิ่งเพิ่ม
<cast-media-player></cast-media-player>
ตอนนี้เราต้องเริ่มต้นใช้งาน SDK ใน js/receiver.js
ซึ่งประกอบด้วย
- การอ้างอิง
CastReceiverContext
ซึ่งเป็นจุดแรกเข้าหลักไปยัง Receiver SDK ทั้งหมด - จัดเก็บการอ้างอิงไปยัง
PlayerManager
ซึ่งเป็นออบเจ็กต์ที่จัดการการเล่นและจัดเตรียมฮุกทั้งหมดที่จําเป็นในการเสียบตรรกะที่กำหนดเอง - กำลังเริ่มต้น SDK โดยเรียกใช้
start()
ในCastReceiverContext
เพิ่มรายการต่อไปนี้ไปยัง js/receiver.js
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. การแคสต์เนื้อหาวิดีโอ "พื้นฐาน"
สำหรับ Codelab นี้ ให้ใช้เครื่องมือ CaC เพื่อลองใช้รีซีฟเวอร์เครื่องใหม่
ชี้เว็บเบราว์เซอร์ไปที่เครื่องมือ Command and Control (CaC)
โปรดแทนที่รหัสแอปของคุณเองตามที่จดทะเบียนไว้ก่อนหน้าในช่อง และคลิก "ตั้งค่ารหัสแอป" ซึ่งจะบอกให้เครื่องมือใช้ตัวรับเมื่อเริ่มเซสชันแคสต์
การแคสต์สื่อ
ในระดับสูง หากต้องการเล่นสื่อในอุปกรณ์แคสต์ จะต้องดำเนินการต่อไปนี้
- ผู้ส่งสร้างออบเจ็กต์
MediaInfo
JSON
จาก Cast SDK ที่จำลองรายการสื่อ - ผู้ส่งเชื่อมต่อกับอุปกรณ์แคสต์เพื่อเปิดแอปพลิเคชันผู้รับ
- ผู้รับจะโหลดออบเจ็กต์
MediaInfo
ผ่านคำขอLOAD
เพื่อเล่นเนื้อหา - ผู้รับจะตรวจสอบและติดตามสถานะของสื่อ
- ผู้ส่งจะส่งคำสั่งการเล่นไปยังผู้รับเพื่อควบคุมการเล่นตามการโต้ตอบของผู้ใช้กับแอปของผู้ส่ง
ในการพยายามขั้นพื้นฐานครั้งแรกนี้ เราจะป้อนข้อมูล MediaInfo
ด้วย URL ของชิ้นงานที่เล่นได้ (จัดเก็บไว้ใน MediaInfo.contentUrl
)
ผู้ส่งในชีวิตจริงใช้ตัวระบุสื่อเฉพาะแอปพลิเคชันใน MediaInfo.contentId
ผู้รับจะใช้ contentId
เป็นตัวระบุเพื่อเรียกใช้ API แบ็กเอนด์ที่เหมาะสมเพื่อแก้ไข URL ของชิ้นงานจริงและตั้งค่าเป็น MediaInfo.contentUrl.
นอกจากนี้ ผู้รับจะจัดการงานต่างๆ เช่น การรับใบอนุญาต DRM หรือแทรกข้อมูลเกี่ยวกับช่วงพักโฆษณา
เราจะขยายระยะสัญญาณของรีซีฟเวอร์เพื่อให้ทำสิ่งนั้นในส่วนถัดไป ในระหว่างนี้ ให้คลิกไอคอนแคสต์และเลือกอุปกรณ์เพื่อเปิดรีซีฟเวอร์
ไปที่แท็บ "โหลดสื่อ" แล้วคลิกปุ่ม "โหลดตามเนื้อหา" เครื่องรับควรเริ่มเล่นเนื้อหาตัวอย่าง
ดังนั้น Receiver SDK จะจัดการสิ่งต่อไปนี้โดยอัตโนมัติ
- กำลังเริ่มต้นเซสชันการแคสต์
- จัดการคำขอของ
LOAD
ที่ส่งเข้ามาจากผู้ส่งซึ่งมีเนื้อหาที่เล่นได้ - จัดให้มี UI โปรแกรมเล่นพื้นฐานที่พร้อมแสดงบนหน้าจอขนาดใหญ่
คุณอาจสำรวจเครื่องมือ CaC และโค้ดของเครื่องมือก่อนไปยังส่วนถัดไป ซึ่งเราจะขยายตัวรับเพื่อพูดคุยถึง API ตัวอย่างง่ายๆ เพื่อดำเนินการตามคำขอ LOAD
ขาเข้าจากผู้ส่ง
9. ผสานรวมกับ API ภายนอก
เราจะแก้ไขตัวรับเพื่อจัดการคำขอ LOAD
ที่อ้างอิงเนื้อหาสื่อที่ต้องการด้วยคีย์ API แทนการส่ง URL ของชิ้นงานที่เล่นได้ เพื่อให้สอดคล้องกับวิธีที่นักพัฒนาแอปส่วนใหญ่โต้ตอบกับตัวรับ Cast ในแอปพลิเคชันในชีวิตจริง
โดยปกติแล้วแอปพลิเคชันจะดำเนินการนี้เนื่องจากเหตุผลต่อไปนี้
- ผู้ส่งอาจไม่ทราบ URL ของเนื้อหา
- แอปพลิเคชันแคสต์ออกแบบมาเพื่อจัดการการตรวจสอบสิทธิ์ ตรรกะทางธุรกิจอื่นๆ หรือการเรียก API โดยตรงบนอุปกรณ์ที่รับ
ฟังก์ชันนี้ใช้เป็นหลักในเมธอด PlayerManager
setMessageInterceptor()
ซึ่งจะช่วยให้คุณขัดขวางข้อความขาเข้าตามประเภทและแก้ไขข้อความก่อนที่จะถึงตัวแฮนเดิลข้อความภายในของ SDK ได้ ในส่วนนี้เราจะจัดการกับคำขอ LOAD
โดยจะทำสิ่งต่อไปนี้
- อ่านคำขอ
LOAD
ที่เข้ามาและcontentId
ที่กําหนดเอง - เรียกใช้
GET
ไปยัง API ของเราเพื่อค้นหาเนื้อหาที่สตรีมได้ผ่านทางcontentId
- แก้ไขคําขอ
LOAD
ด้วย URL ของสตรีม - แก้ไขออบเจ็กต์
MediaInformation
เพื่อตั้งค่าพารามิเตอร์ประเภทสตรีม - ส่งคำขอไปยัง SDK เพื่อเล่น หรือปฏิเสธคําสั่งหากเราค้นหาสื่อที่ขอไม่ได้
ตัวอย่าง API ที่ระบุแสดงฮุกของ SDK สำหรับการปรับแต่งงานของผู้รับทั่วไป ในขณะที่ยังคงใช้ประสบการณ์การใช้งานที่พร้อมใช้งานได้ทันทีเป็นส่วนใหญ่
Sample API
ไปที่ https://storage.googleapis.com/cpe-sample-media/content.json เพื่อดูแคตตาล็อกวิดีโอตัวอย่าง เนื้อหาดังกล่าวประกอบด้วย URL ของภาพโปสเตอร์ในรูปแบบ PNG รวมถึงสตรีม DASH และ HLS สตรีม DASH และ HLS ชี้ไปที่แหล่งที่มาของวิดีโอและเสียงที่ได้รับการถอดรหัสซึ่งจัดเก็บในคอนเทนเนอร์ mp4 แบบแยกส่วน
{
"bbb": {
"author": "The Blender Project",
"description": "Grumpy Bunny is grumpy",
"poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
"stream": {
"dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
"hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
"title": "Big Buck Bunny"
},
"fbb_ad": {
"author": "Google Inc.",
"description": "Introducing Chromecast. The easiest way to enjoy [...]",
"poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
"stream": {
"dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
"hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
"title": "For Bigger Blazes"
},
[...]
}
ในขั้นตอนถัดไป เราจะแมปคีย์ของรายการแต่ละรายการ (เช่น bbb, fbb_ad
) กับ URL ของสตรีมหลังจากที่มีการเรียกใช้ตัวรับด้วยคําขอ LOAD
สกัดกั้นคําขอ LOAD
ในขั้นตอนนี้ เราจะสร้างตัวขัดจังหวะการโหลดที่มีฟังก์ชันที่ส่งคําขอ XHR
ไปยังไฟล์ JSON
ที่โฮสต์ เมื่อได้รับไฟล์ JSON
แล้ว เราจะแยกวิเคราะห์เนื้อหาและตั้งค่าข้อมูลเมตา ในส่วนต่อไปนี้ เราจะปรับแต่งพารามิเตอร์ MediaInformation
เพื่อระบุประเภทเนื้อหา
เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js
ก่อนโทรหา context.start()
function makeRequest (method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
reject();
} else {
// Add metadata
let metadata = new
cast.framework.messages.GenericMediaMetadata();
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
ส่วนถัดไปจะอธิบายวิธีกำหนดค่าพร็อพเพอร์ตี้ media
ของคำขอโหลดสำหรับเนื้อหา DASH
การใช้เนื้อหา DASH ตัวอย่างสำหรับ API
เมื่อเตรียมตัวสกัดโหลดแล้ว เราจะระบุประเภทเนื้อหาไปยังผู้รับ ข้อมูลนี้จะระบุ URL ของเพลย์ลิสต์หลักและประเภท MIME ของสตรีมให้แก่ผู้รับ เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js ใน LOAD
ของอินเตอร์เซปเตอร์ Promise()
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
...
}
});
});
});
เมื่อทำขั้นตอนนี้เสร็จแล้ว ให้ไปที่ "ทดสอบ" เพื่อลองโหลดเนื้อหา DASH หากต้องการทดสอบการโหลดด้วยเนื้อหา HLS แทน ให้ดูขั้นตอนถัดไป
การใช้เนื้อหา HLS ของ API ตัวอย่าง
API ตัวอย่างมีเนื้อหา HLS และ DASH ด้วย นอกจากการตั้งค่า contentType
อย่างเช่นที่เราทำในขั้นตอนก่อนหน้า คำขอโหลดจะต้องมีพร็อพเพอร์ตี้เพิ่มเติมบางอย่างเพื่อใช้ URL HLS ของ API ตัวอย่าง เมื่อกำหนดค่าตัวรับให้เล่นสตรีม HLS ประเภทคอนเทนเนอร์เริ่มต้นที่คาดไว้คือ Transport Stream (TS) ด้วยเหตุนี้ ผู้รับจะพยายามเปิดสตรีม MP4 ตัวอย่างในรูปแบบ TS หากมีการแก้ไขเฉพาะพร็อพเพอร์ตี้ contentUrl
ในคำขอโหลด คุณควรแก้ไขออบเจ็กต์ MediaInformation
ด้วยพร็อพเพอร์ตี้เพิ่มเติมเพื่อให้ผู้รับทราบว่าเนื้อหาเป็นประเภท MP4 ไม่ใช่ TS เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js ในตัวเก็บข้อมูลโหลดเพื่อแก้ไขพร็อพเพอร์ตี้ contentUrl
และ contentType
นอกจากนี้ ให้เพิ่มพร็อพเพอร์ตี้ HlsSegmentFormat
และ HlsVideoSegmentFormat
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.hls;
request.media.contentType = 'application/x-mpegurl';
request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
...
}
});
});
});
การทดสอบ
เปิดเครื่องมือ Command and Control (CaC) อีกครั้งและตั้งค่ารหัสแอปเป็นรหัสแอปของผู้รับ เลือกอุปกรณ์โดยใช้ปุ่ม "แคสต์"
ไปที่แท็บ "โหลดสื่อ" ครั้งนี้ ให้ลบข้อความในช่อง "URL ของเนื้อหา" ข้างปุ่ม "โหลดตามเนื้อหา" ซึ่งจะบังคับให้แอปพลิเคชันของเราส่งคําขอ LOAD
ที่มีเฉพาะการอ้างอิง contentId
ไปยังสื่อของเรา
สมมติว่าทุกอย่างทำงานได้ตามปกติกับการแก้ไขตัวรับ Interceptor ควรจัดรูปแบบออบเจ็กต์ MediaInfo
ให้เป็นรูปแบบที่ SDK สามารถเล่นบนหน้าจอได้
คลิกปุ่ม "โหลดตามเนื้อหา" เพื่อดูว่าสื่อเล่นอย่างถูกต้องหรือไม่ คุณจะเปลี่ยน Content ID เป็นรหัสอื่นในไฟล์ content.json ได้
10. การเพิ่มประสิทธิภาพสําหรับจออัจฉริยะ
จออัจฉริยะเป็นอุปกรณ์ที่มีฟังก์ชันการสัมผัส ซึ่งช่วยให้แอปพลิเคชันผู้รับรองรับการควบคุมด้วยการสัมผัส
ส่วนนี้จะอธิบายวิธีเพิ่มประสิทธิภาพแอปพลิเคชันตัวรับสัญญาณเมื่อเปิดบนจออัจฉริยะ และวิธีปรับแต่งตัวควบคุมวิดีโอเพลเยอร์
การเข้าถึงตัวควบคุม UI
คุณเข้าถึงออบเจ็กต์การควบคุม UI ของจออัจฉริยะได้โดยใช้ cast.framework.ui.Controls.GetInstance()
เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js
เหนือ context.start()
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
context.start();
หากไม่ใช้องค์ประกอบ <cast-media-player> คุณจะต้องตั้งค่า touchScreenOptimizedApp
ใน CastReceiverOptions
ใน Codelab นี้ เราจะใช้องค์ประกอบ <cast-media-player>
context.start({ touchScreenOptimizedApp: true });
กำหนดปุ่มควบคุมเริ่มต้นให้กับช่องแต่ละช่องตาม MetadataType
และ MediaStatus.supportedMediaCommands
การควบคุมวิดีโอ
สำหรับ MetadataType.MOVIE
, MetadataType.TV_SHOW
และ MetadataType.GENERIC
ออบเจ็กต์การควบคุม UI สำหรับจออัจฉริยะจะแสดงดังตัวอย่างด้านล่าง
--playback-logo-image
MediaMetadata.subtitle
MediaMetadata.title
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.QUEUE_PREV
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.SEEK_BACKWARD_30
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.SEEK_FORWARD_30
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.QUEUE_NEXT
การควบคุมเสียง
สำหรับ MetadataType.MUSIC_TRACK
ออบเจ็กต์ตัวควบคุม UI สำหรับจออัจฉริยะจะแสดงดังต่อไปนี้
--playback-logo-image
MusicTrackMediaMetadata.albumName
MusicTrackMediaMetadata.title
MusicTrackMediaMetadata.albumArtist
MusicTrackMediaMetadata.images[0]
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.NO_BUTTON
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.QUEUE_PREV
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.QUEUE_NEXT
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.NO_BUTTON
การอัปเดตคำสั่งสื่อที่รองรับ
ออบเจ็กต์ตัวควบคุม UI จะกำหนดด้วยว่า ControlsButton
จะแสดงหรือไม่โดยอิงตาม MediaStatus.supportedMediaCommands
เมื่อค่าของ supportedMediaCommands
เท่ากับ ALL_BASIC_MEDIA
เลย์เอาต์การควบคุมเริ่มต้นจะแสดงข้อมูลต่อไปนี้
เมื่อค่าของ supportedMediaCommands
เท่ากับ ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT
เลย์เอาต์การควบคุมเริ่มต้นจะแสดงดังต่อไปนี้
เมื่อค่าของ supportedMediaCommands เท่ากับ PAUSE | QUEUE_PREV | QUEUE_NEXT
เลย์เอาต์การควบคุมเริ่มต้นจะแสดงด้านล่าง
เมื่อแทร็กข้อความพร้อมใช้งาน ปุ่มคำบรรยายแทนเสียงจะแสดงที่ SLOT_1
เสมอ
หากต้องการเปลี่ยนค่าของ supportedMediaCommands
แบบไดนามิกหลังจากเริ่มบริบทตัวรับ ให้เรียกใช้ PlayerManager.setSupportedMediaCommands
เพื่อลบล้างค่า นอกจากนี้ คุณยังเพิ่มคำสั่งใหม่ได้โดยใช้ addSupportedMediaCommands
หรือนำคำสั่งที่มีอยู่ออกได้โดยใช้ removeSupportedMediaCommands
การปรับแต่งปุ่มควบคุม
คุณปรับแต่งการควบคุมได้โดยใช้ PlayerDataBinder
เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js
ใต้ touchControls เพื่อตั้งค่าช่องแรกของการควบคุม
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
// Clear default buttons and re-assign
touchControls.clearDefaultSlotAssignments();
touchControls.assignButton(
cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
);
});
context.start();
11. การใช้การเรียกดูสื่อใน Smart Display
Media Browse คือฟีเจอร์ CAF Receiver ที่ช่วยให้ผู้ใช้สำรวจเนื้อหาเพิ่มเติมในอุปกรณ์แบบสัมผัสได้ หากต้องการใช้ คุณจะต้องใช้ PlayerDataBinder
เพื่อตั้งค่า UI BrowseContent
จากนั้นคุณจะป้อนข้อมูลใน BrowseItems
โดยอิงตามเนื้อหาที่ต้องการแสดงได้
BrowseContent
ด้านล่างนี้คือตัวอย่างของ UI และพร็อพเพอร์ตี้ของ BrowseContent
BrowseContent.title
BrowseContent.items
สัดส่วนภาพ
ใช้ targetAspectRatio property
เพื่อเลือกสัดส่วนภาพที่ดีที่สุดสำหรับชิ้นงานรูปภาพ SDK ตัวรับ CAF รองรับสัดส่วนภาพ 3 แบบ ได้แก่ SQUARE_1_TO_1
, PORTRAIT_2_TO_3
, LANDSCAPE_16_TO_9
BrowseItem
ใช้ BrowseItem
เพื่อแสดงชื่อ ชื่อรอง ระยะเวลา และรูปภาพของแต่ละรายการ
BrowseItem.image
BrowseItem.duration
BrowseItem.title
BrowseItem.subtitle
ตั้งค่าข้อมูลการเรียกดูสื่อ
คุณสามารถระบุรายการเนื้อหาสื่อเพื่อเรียกดูได้โดยเรียกใช้ setBrowseContent
เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js
ด้านล่าง playerDataBinder
และใน Listener กิจกรรม MEDIA_CHANGED
เพื่อตั้งค่าการเรียกดูรายการด้วยชื่อ "รายการถัดไป"
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
...
let browseItems = getBrowseItems();
function getBrowseItems() {
let browseItems = [];
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
for (let key in data) {
let item = new cast.framework.ui.BrowseItem();
item.entity = key;
item.title = data[key].title;
item.subtitle = data[key].description;
item.image = new cast.framework.messages.Image(data[key].poster);
item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
browseItems.push(item);
}
});
return browseItems;
}
let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
....
// Media browse
touchControls.setBrowseContent(browseContent);
});
การคลิกรายการเรียกดูสื่อจะทริกเกอร์ LOAD
Interceptor เพิ่มโค้ดต่อไปนี้ลงใน LOAD
interceptor เพื่อแมป request.media.contentId
กับ request.media.entity
จากรายการเรียกดูสื่อ
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
...
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
...
});
});
คุณยังตั้งค่าออบเจ็กต์ BrowseContent
เป็น null
เพื่อนำ UI การเรียกดูสื่อออกได้ด้วย
12. การแก้ไขข้อบกพร่องของแอปตัวรับสัญญาณ
Cast Receiver SDK เป็นตัวเลือกอีกทางหนึ่งสำหรับนักพัฒนาแอปในการแก้ไขข้อบกพร่องของแอปรีซีฟเวอร์ได้อย่างง่ายดายโดยใช้ CastDebugLogger API และเครื่องมือ Command and Control (CaC) ที่ใช้ร่วมกันเพื่อบันทึกบันทึก
การเริ่มต้น
หากต้องการรวม API ให้เพิ่มสคริปต์แหล่งที่มา CastDebugLogger
ในไฟล์ index.html ควรประกาศแหล่งที่มาในแท็ก <head> หลังจากการประกาศ SDK ของตัวรับสัญญาณ
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
<!-- Cast Debug Logger -->
<script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>
ใน js/receiver.js
ที่ด้านบนของไฟล์และใต้ playerManager
ให้เพิ่มโค้ดต่อไปนี้เพื่อดึงข้อมูลอินสแตนซ์ CastDebugLogger
และเปิดใช้โปรแกรมบันทึก
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
เมื่อเปิดใช้โปรแกรมบันทึกข้อบกพร่อง ภาพซ้อนทับที่แสดง DEBUG MODE
จะแสดงในเครื่องรับ
เหตุการณ์โปรแกรมเล่นบันทึก
เมื่อใช้ CastDebugLogger
คุณจะบันทึกเหตุการณ์ของเพลเยอร์ซึ่ง CAF Receiver SDK เรียกใช้ได้อย่างง่ายดาย และใช้ระดับบันทึกที่แตกต่างกันเพื่อบันทึกข้อมูลเหตุการณ์ การกําหนดค่า loggerLevelByEvents
ใช้ cast.framework.events.EventType
และ cast.framework.events.category
เพื่อระบุเหตุการณ์ที่จะบันทึก
เพิ่มโค้ดต่อไปนี้ใต้ประกาศ castDebugLogger
เพื่อบันทึกเมื่อมีการเรียกเหตุการณ์ CORE
ของผู้เล่นหรือมีการออกอากาศการเปลี่ยนแปลง mediaStatus
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
ข้อความในบันทึกและแท็กที่กำหนดเอง
CastDebugLogger API ช่วยให้คุณสร้างข้อความบันทึกที่ปรากฏบนการวางซ้อนการแก้ไขข้อบกพร่องของตัวรับด้วยสีต่างๆ ได้ วิธีการบันทึกต่อไปนี้พร้อมใช้งาน โดยเรียงตามลําดับความสําคัญจากสูงสุดไปต่ำสุด
castDebugLogger.error(custom_tag, message);
castDebugLogger.warn(custom_tag, message);
castDebugLogger.info(custom_tag, message);
castDebugLogger.debug(custom_tag, message);
สำหรับแต่ละวิธีในบันทึก พารามิเตอร์แรกคือแท็กที่กำหนดเอง สตริงนี้อาจเป็นสตริงระบุใดก็ได้ที่คุณคิดว่ามีความหมาย CastDebugLogger
ใช้แท็กเพื่อกรองบันทึก การใช้งานแท็กมีคำอธิบายโดยละเอียดด้านล่าง พารามิเตอร์ที่ 2 คือข้อความบันทึก
หากต้องการแสดงบันทึกขณะใช้งาน ให้เพิ่มบันทึกลงในLOAD
ตัวสกัด
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
castDebugLogger.error(LOG_TAG, 'Content not found');
reject();
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);
// Add metadata
let metadata = new cast.framework.messages.MovieMediaMetadata();
metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
คุณควบคุมข้อความที่จะปรากฏบนการวางซ้อนการแก้ไขข้อบกพร่องได้โดยการตั้งค่าระดับบันทึกใน loggerLevelByTags
สําหรับแท็กที่กําหนดเองแต่ละรายการ เช่น การเปิดใช้แท็กที่กำหนดเองที่มีระดับบันทึก cast.framework.LoggerLevel.DEBUG
จะแสดงข้อความทั้งหมดที่เพิ่มพร้อมกับข้อความแสดงข้อผิดพลาด คำเตือน ข้อมูล และการแก้ไขข้อบกพร่อง การเปิดใช้แท็กที่กําหนดเองที่มีระดับ WARNING
จะแสดงเฉพาะข้อความแสดงข้อผิดพลาดและข้อความเตือนในบันทึก
คุณจะระบุการกําหนดค่า loggerLevelByTags
หรือไม่ก็ได้ หากไม่ได้กําหนดค่าแท็กที่กําหนดเองสําหรับระดับบันทึก ข้อความบันทึกทั้งหมดจะแสดงในวางซ้อนการแก้ไขข้อบกพร่อง
เพิ่มโค้ดต่อไปนี้ใต้เครื่องมือบันทึกเหตุการณ์ CORE
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
[LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};
หน้าจอแก้ไขข้อบกพร่องแบบวางซ้อน
เครื่องมือบันทึกข้อบกพร่องของ Cast มีการวางซ้อนการแก้ไขข้อบกพร่องบนอุปกรณ์รับเพื่อแสดงข้อความบันทึกที่กำหนดเองบนอุปกรณ์แคสต์ ใช้ showDebugLogs
เพื่อเปิด/ปิดการวางซ้อนการแก้ไขข้อบกพร่อง และ clearDebugLogs
เพื่อล้างข้อความบันทึกในการแสดงซ้อนทับ
เพิ่มโค้ดต่อไปนี้เพื่อแสดงตัวอย่างการวางซ้อนการแก้ไขข้อบกพร่องบนเครื่องรับ
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);
// Show debug overlay
castDebugLogger.showDebugLogs(true);
// Clear log messages on debug overlay
castDebugLogger.clearDebugLogs();
}
});
13. ขอแสดงความยินดี
ตอนนี้คุณทราบวิธีสร้างแอปพลิเคชันตัวรับเว็บที่กำหนดเองโดยใช้ Cast Web Receiver SDK แล้ว
ดูรายละเอียดเพิ่มเติมได้ที่คู่มือนักพัฒนาซอฟต์แวร์ของ Web Receiver