1. ภาพรวม
Codelab นี้จะสอนวิธีสร้างแอปตัวรับสัญญาณเว็บแบบกําหนดเองเพื่อเล่นเนื้อหาบนอุปกรณ์ที่พร้อมใช้งาน Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยัง TV ได้ จากนั้นผู้ใช้จะใช้อุปกรณ์เคลื่อนที่หรือเบราว์เซอร์ Chrome บนเดสก์ท็อปเป็นรีโมตควบคุมการเล่นสื่อบนทีวีได้
Google Cast SDK ช่วยให้แอปควบคุมอุปกรณ์ที่พร้อมใช้งาน Google Cast (เช่น ทีวีหรือระบบเสียง) Cast SDK มีคอมโพเนนต์ UI ที่จําเป็นโดยอิงตามรายการตรวจสอบการออกแบบ Google Cast
รายการตรวจสอบการออกแบบ Google Cast มีไว้ให้ผู้ใช้ของ Cast ใช้งานได้ง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ ดูเพิ่มเติมที่นี่
สิ่งที่เรากําลังจะสร้าง
หลังจากที่คุณสร้างโค้ดแล็บนี้เสร็จแล้ว คุณจะมีแอป HTML5 ที่ทําหน้าที่เป็นตัวรับที่กําหนดเองและสามารถแสดงเนื้อหาวิดีโอบนอุปกรณ์ที่พร้อมใช้งาน Cast ได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีตั้งค่าการพัฒนาผู้รับ
- พื้นฐานของเครื่องรับที่พร้อมใช้งาน Cast โดยอิงตามเฟรมเวิร์กแอปพลิเคชัน Cast
- วิธีรับวิดีโอที่แคสต์
- วิธีผสานรวมบันทึกการแก้ไขข้อบกพร่อง
- วิธีเพิ่มประสิทธิภาพตัวรับสําหรับ Smart Display
สิ่งที่ต้องมี
- เบราว์เซอร์ Google Chrome เวอร์ชันล่าสุด
- บริการโฮสติ้ง HTTPS เช่น โฮสติ้งของ Firebase หรือ ngrok
- อุปกรณ์ Google Cast เช่น Chromecast หรือ Android TV ที่กําหนดค่าด้วยการเข้าถึงอินเทอร์เน็ต
- ทีวีหรือจอภาพที่มีอินพุต HDMI
ประสบการณ์การใช้งาน
- คุณจะต้องมีความรู้เกี่ยวกับการพัฒนาเว็บมาก่อน
- และคุณก็คงต้องมีความรู้ก่อนดูทีวีด้วย :)
คุณจะใช้บทแนะนํานี้อย่างไร
คุณจะให้คะแนนประสบการณ์ในการสร้างเว็บแอปอย่างไร
คุณจะให้คะแนนประสบการณ์การดูทีวีอย่างไร
2. รับโค้ดตัวอย่าง
คุณสามารถดาวน์โหลดตัวอย่างโค้ดทั้งหมดลงในคอมพิวเตอร์ของคุณได้...
และคลายไฟล์ ZIP ที่ดาวน์โหลด
3. การทําให้ผู้รับใช้งานได้ภายในเครื่อง
หากต้องการใช้อุปกรณ์รับสัญญาณบนเว็บกับอุปกรณ์ Cast คุณต้องโฮสต์อุปกรณ์ดังกล่าวไว้ในตําแหน่งที่อุปกรณ์ Cast เข้าถึงได้ ถ้ามีเซิร์ฟเวอร์ที่รองรับ https อยู่แล้ว ให้ข้ามวิธีการต่อไปนี้และจดบันทึก URL ไว้ เนื่องจากต้องใช้ในหัวข้อถัดไป
หากไม่มีเซิร์ฟเวอร์พร้อมให้ใช้งาน คุณก็ใช้ Firebase Hosting หรือ ngrok ได้
เรียกใช้เซิร์ฟเวอร์
เมื่อคุณตั้งค่าบริการที่คุณเลือกแล้ว ให้ไปที่ app-start
และเริ่มเซิร์ฟเวอร์ของคุณ
โปรดจด URL สําหรับผู้รับที่โฮสต์ของคุณ ซึ่งจะนําไปใช้ในส่วนถัดไป
4. ลงทะเบียนแอปพลิเคชันในคอนโซลนักพัฒนาซอฟต์แวร์ Cast
คุณต้องลงทะเบียนแอปพลิเคชันของคุณเพื่อให้สามารถเรียกใช้ตัวรับสัญญาณที่กําหนดเอง ดังเช่นใน Codelab นี้บนอุปกรณ์ Chromecast หลังจากที่คุณลงทะเบียนแอปพลิเคชัน คุณจะได้รับรหัสแอปพลิเคชันที่แอปพลิเคชันผู้ส่งของคุณต้องใช้ในการเรียก API เช่น ในการเรียกใช้แอปพลิเคชันตัวรับ
คลิก "เพิ่มแอปพลิเคชันใหม่"
เลือก "ตัวรับสัญญาณที่กําหนดเอง" ซึ่งเป็นสิ่งที่เรากําลังสร้าง
ป้อนรายละเอียดของผู้รับใหม่ อย่าลืมใช้ URL ที่คุณลงท้ายด้วย
ในส่วนสุดท้าย จดรหัสแอปพลิเคชันที่กําหนดให้กับผู้รับรายใหม่
นอกจากนี้ คุณต้องลงทะเบียนอุปกรณ์ Google Cast เพื่อให้เข้าถึงอุปกรณ์ของผู้รับก่อนเผยแพร่ เมื่อคุณเผยแพร่แอปพลิเคชันตัวรับสัญญาณแล้ว แอปพลิเคชันนั้นจะใช้งานได้กับอุปกรณ์ Google Cast ทั้งหมด สําหรับวัตถุประสงค์ของ Codelab นี้ ขอแนะนําให้คุณทํางานกับแอปพลิเคชันรีซีฟเวอร์ที่ไม่ได้เผยแพร่
คลิก "เพิ่มอุปกรณ์ใหม่"
ป้อนหมายเลขซีเรียลที่พิมพ์ไว้ด้านหลังอุปกรณ์ Cast และตั้งชื่อที่สื่อความหมาย นอกจากนี้ คุณยังค้นหาหมายเลขซีเรียลได้โดยแคสต์หน้าจอใน Chrome เมื่อเข้าถึง Google Cast SDK Developer Console
โดยจะใช้เวลาประมาณ 5-15 นาทีก่อนที่เครื่องรับและอุปกรณ์จะพร้อมสําหรับการทดสอบ หลังจากรอ 5-15 นาที คุณต้องรีบูตอุปกรณ์ Cast
5. เรียกใช้แอปตัวอย่าง
ระหว่างที่รอแอปตัวรับสัญญาณใหม่ของเราพร้อมทดสอบ มาดูตัวอย่างแอปผู้รับที่เสร็จสมบูรณ์กัน ตัวรับที่เรากําลังจะสร้างจะสามารถเล่นสื่อโดยใช้สตรีมมิงแบบปรับอัตราบิตได้ (เราจะใช้เนื้อหาตัวอย่างที่เข้ารหัสสําหรับสตรีมมิงแบบปรับอัตโนมัติแบบไดนามิกผ่าน HTTP (DASH))
เปิดคําสั่งและตัวควบคุม (CaC) ในเบราว์เซอร์
- คุณควรเห็นเครื่องมือ CaC ของเรา
- ใช้รหัสตัวรับตัวอย่าง "CC1AD845" เริ่มต้น แล้วคลิกปุ่ม "ตั้งค่ารหัสแอป"
- คลิกปุ่ม "แคสต์" ที่ด้านบนซ้ายและเลือกอุปกรณ์ Google Cast ของคุณ
- ไปที่แท็บ "โหลดสื่อ" ที่ด้านบน
- คลิกปุ่ม "โหลดตามเนื้อหา" เพื่อเล่นวิดีโอตัวอย่าง
- วิดีโอจะเริ่มเล่นในอุปกรณ์ Google Cast เพื่อแสดงฟังก์ชันตัวรับสัญญาณพื้นฐานโดยใช้ตัวรับเริ่มต้น
6. เตรียมโปรเจ็กต์เริ่มต้น
เราจําเป็นต้องเพิ่มการสนับสนุนสําหรับ Google Cast ไปยังแอปพลิเคชันเริ่มต้นที่คุณดาวน์โหลด ต่อไปนี้คือคําศัพท์ของ Google Cast ที่เราจะใช้ใน Codelab นี้
- แอปผู้ส่งทํางานในอุปกรณ์เคลื่อนที่หรือแล็ปท็อป
- แอปตัวรับจะทํางานบนอุปกรณ์ Google Cast
ตอนนี้คุณพร้อมที่จะสร้างโปรเจ็กต์เริ่มต้นเพิ่มเติมโดยใช้ตัวแก้ไขข้อความที่คุณชื่นชอบแล้ว โดยทําดังนี้
- เลือกไดเรกทอรี
app-start
จากตัวอย่างการดาวน์โหลดโค้ด - เปิด
js/receiver.js
และindex.html
โปรดทราบว่าในขณะที่ทํา Codelab นี้ http-server
ควรจะเลือกการเปลี่ยนแปลงที่คุณทํามา หากไม่พบ แสดงว่าพยายามฆ่าและรีสตาร์ท http-server
แทน
การออกแบบแอป
แอปผู้รับจะเริ่มเซสชันการแคสต์และจะสแตนด์บายจนกว่าคําขอ "โหลด" (ซึ่งก็คือคําสั่งให้เล่นสื่อชิ้นหนึ่ง) จากผู้ส่งจะมาถึง
แอปประกอบด้วยมุมมองหลัก 1 มุมมองที่กําหนดไว้ใน index.html
และไฟล์ JavaScript 1 ไฟล์ชื่อ js/receiver.js
ซึ่งมีตรรกะทั้งหมดเพื่อให้ตัวรับสัญญาณทํางานได้
index.html
ไฟล์ HTML นี้จะมี UI ของแอปรีซีฟเวอร์ของเรา สําหรับขณะนี้รหัสดังกล่าวว่างเปล่า และเราจะเพิ่มลงใน UI ของห้องทดลองโค้ด
Receiver.js
สคริปต์นี้จะจัดการตรรกะทั้งหมดสําหรับแอปตัวรับสัญญาณของเรา ตอนนี้นี้เป็นเพียงไฟล์เปล่า แต่เราจะเปลี่ยนให้เป็นตัวรับการแคสต์ที่ทํางานได้อย่างสมบูรณ์พร้อมโค้ดเพียงไม่กี่บรรทัดในส่วนถัดไป
7. ตัวรับการแคสต์พื้นฐาน
ตัวรับการแคสต์พื้นฐานจะเริ่มเซสชันการแคสต์เมื่อเริ่มต้น ซึ่งเป็นสิ่งจําเป็นเพื่อบอกแอปพลิเคชันของผู้ส่งที่เชื่อมต่อทั้งหมดว่ารับผู้รับสําเร็จ นอกจากนี้ 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>
กําลังโหลด receiver.js,
เพื่อมอบ SDK ตัวรับที่มีพื้นที่ว่างสําหรับดึง UI ตัวรับเริ่มต้น ซึ่งมาพร้อมกับสคริปต์ที่คุณเพิ่งเพิ่ม
<cast-media-player></cast-media-player>
ตอนนี้ เราจําเป็นต้องเริ่มต้น SDK ใน js/receiver.js
ซึ่งประกอบด้วย
- กําลังรับการอ้างอิงไปยัง
CastReceiverContext
ซึ่งเป็นจุดเข้าถึงหลักไปยัง SDK ตัวรับทั้งหมด - จัดเก็บการอ้างอิงไปยัง
PlayerManager
ซึ่งเป็นออบเจ็กต์ที่จัดการการเล่นและให้ตะขอทั้งหมดที่คุณต้องการสําหรับใช้ตรรกะที่กําหนดเอง - กําลังเริ่มต้น SDK โดยการเรียกใช้
start()
ในCastReceiverContext
เพิ่มรายการต่อไปนี้ลงใน js/receiver.js
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. การแคสต์เนื้อหาวิดีโอ "พื้นฐาน"
สําหรับวัตถุประสงค์ของ Codelab นี้ ให้ใช้เครื่องมือ CaC เพื่อทดลองใช้เครื่องรับใหม่ล่าสุด
ชี้เว็บเบราว์เซอร์ไปที่เครื่องมือสั่งการและควบคุม (CaC)
อย่าลืมใส่ App ID ของคุณเองตามที่ลงทะเบียนไว้ก่อนหน้านี้ในช่อง แล้วคลิก "Set App ID" การดําเนินการนี้จะสั่งให้เครื่องมือใช้ตัวรับสัญญาณเมื่อเริ่มเซสชันแคสต์
กําลังแคสต์สื่อ
ในระดับสูง หากต้องการเล่นสื่อในอุปกรณ์ Cast คุณต้องดําเนินการต่อไปนี้
- ผู้ส่งสร้างออบเจ็กต์
JSON
สําหรับMediaInfo
จาก Cast SDK ซึ่งสร้างแบบจําลองรายการสื่อ - ผู้ส่งเชื่อมต่อกับอุปกรณ์แคสต์เพื่อเริ่มใช้งานแอปพลิเคชันตัวรับ
- ผู้รับจะโหลดออบเจ็กต์
MediaInfo
ผ่านคําขอLOAD
เพื่อเล่นเนื้อหา - ผู้รับจะตรวจสอบและติดตามสถานะสื่อ
- ผู้ส่งจะส่งคําสั่งการเล่นไปยังผู้รับเพื่อควบคุมการเล่นโดยอิงตามการโต้ตอบของผู้ใช้กับแอปผู้ส่ง
ในความพยายามขั้นพื้นฐานครั้งแรกนี้ เราจะกรอก MediaInfo
ด้วย URL เนื้อหาที่เล่นได้ (จัดเก็บอยู่ใน MediaInfo.contentUrl
)
ผู้ส่งในชีวิตจริงจะใช้ตัวระบุสื่อเฉพาะแอปพลิเคชันในMediaInfo.contentId
ผู้รับใช้ contentId
เป็นตัวระบุในการเรียก API แบ็กเอนด์เพื่อแก้ไข URL เนื้อหาจริงและตั้งค่าเป็น MediaInfo.contentUrl.
ผู้รับจะจัดการกับงานต่างๆ เช่น การซื้อใบอนุญาต DRM หรือการแทรกข้อมูลเกี่ยวกับช่วงพักโฆษณา
เราจะยืดอายุให้ผู้รับของคุณทําสิ่งที่ต้องการได้ในส่วนถัดไป สําหรับตอนนี้ ให้คลิกไอคอน "ส่ง" และเลือกอุปกรณ์ของคุณเพื่อเปิดตัวรับ
ไปที่แท็บ "Load Media" แล้วคลิกปุ่ม "Load by Content" ผู้รับควรเริ่มเล่นเนื้อหาตัวอย่าง
ดังนั้น SDK ในฝั่งผู้รับแบบพร้อมใช้ทันทีจึงจัดการสิ่งต่อไปนี้
- กําลังเริ่มเซสชันแคสต์
- จัดการคําขอ
LOAD
ขาเข้าจากผู้ส่งที่มีเนื้อหาที่เล่นได้ - จัดเตรียม UI โปรแกรมเล่นพื้นฐานที่พร้อมแสดงบนหน้าจอขนาดใหญ่
ลองสํารวจเครื่องมือ CaC และโค้ดก่อนที่จะไปต่อที่หัวข้อถัดไป ซึ่งเราจะต่อเครื่องรับเพื่อพูดกับ API ตัวอย่างง่ายๆ ในการทําตามคําขอ LOAD
ที่ส่งเข้ามาจากผู้ส่ง
9. ผสานรวมกับ API ภายนอก
เพื่อให้สอดคล้องกับวิธีที่นักพัฒนาซอฟต์แวร์ส่วนใหญ่โต้ตอบกับเครื่องรับการแคสต์ของเราในการใช้งานในชีวิตจริง เราจึงจะแก้ไขผู้รับของเราให้รองรับคําขอ LOAD
ที่อ้างอิงเนื้อหาสื่อที่ต้องการโดยคีย์ API แทนที่จะส่งผ่าน URL เนื้อหาที่เล่นได้
โดยปกติแล้ว แอปพลิเคชันจะดําเนินการเช่นนี้ได้ เนื่องจาก:
- ผู้ส่งอาจไม่ทราบ URL ของเนื้อหา
- แอปพลิเคชัน Cast ออกแบบมาเพื่อจัดการการตรวจสอบสิทธิ์ ตรรกะทางธุรกิจหรือการเรียก API อื่นๆ โดยตรงในเครื่องรับ
ฟังก์ชันนี้จะใช้งานได้ในเมธอด setMessageInterceptor()
ของ PlayerManager
เป็นหลัก วิธีนี้ช่วยให้คุณสกัดกั้นข้อความขาเข้าได้โดยพิมพ์และแก้ไขก่อนที่จะมาถึงเครื่องจัดการข้อความภายในของ SDK ในส่วนนี้ เรากําลังดําเนินการกับคําขอ LOAD
รายการที่เราจะดําเนินการต่อไปนี้
- อ่านคําขอ
LOAD
ขาเข้าและcontentId
ที่กําหนดเอง - เรียกใช้
GET
ไปยัง API ของเราเพื่อค้นหาเนื้อหาแบบสตรีมได้ภายในวันที่contentId
- แก้ไขคําขอ
LOAD
ด้วย URL ของสตรีม - แก้ไขออบเจ็กต์
MediaInformation
เพื่อตั้งค่าพารามิเตอร์ประเภทสตรีม - ส่งคําขอไปยัง SDK เพื่อเล่น หรือปฏิเสธคําสั่ง ถ้าเราไม่สามารถค้นหาสื่อที่ต้องการ
API ตัวอย่างที่มีให้จะแสดงเบ็ดของ SDK สําหรับการปรับแต่งงานทั่วไปของตัวรับสัญญาณ ในขณะที่ยังคงใช้ประสบการณ์ที่พร้อมใช้งานแทบทุกกรณี
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 ใน Promise()
ของอินเตอร์เซ็ปเตอร์ LOAD
...
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 ไว้ ประเภทคอนเทนเนอร์เริ่มต้นที่คาดไว้คือสตรีมการส่ง (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;
...
}
});
});
});
การทดสอบ
เปิดเครื่องมือควบคุมและการควบคุม (CaC) อีกครั้ง แล้วตั้งค่ารหัสแอปเป็นรหัสแอปของผู้รับ เลือกอุปกรณ์โดยใช้ปุ่ม "แคสต์"
ไปที่แท็บ "โหลดสื่อ" คราวนี้ลบข้อความในช่อง "URL เนื้อหา" ข้างปุ่ม "โหลดตามเนื้อหา" ซึ่งจะบังคับให้แอปพลิเคชันของเราส่งคําขอ LOAD
ที่มีเฉพาะการอ้างอิง contentId
ไปยังสื่อของเรา
สมมติว่าทุกอย่างทํางานได้ดีกับการแก้ไขของคุณในตัวรับ ตัวดักควรมีการกําหนดรูปร่าง MediaInfo
ให้เป็นวัตถุที่ SDK สามารถเล่นบนหน้าจอได้
คลิกปุ่ม "โหลดตามเนื้อหา" เพื่อดูว่าสื่อของคุณเล่นอย่างถูกต้องหรือไม่ คุณสามารถเปลี่ยน Content ID เป็นรหัสอื่นในไฟล์ content.json ได้
10. การเพิ่มประสิทธิภาพสําหรับ Smart Display
Smart Display คืออุปกรณ์ที่มีฟังก์ชันการแตะ ซึ่งช่วยให้แอปพลิเคชันตัวรับสัญญาณรองรับการควบคุมด้วยการสัมผัสได้
ส่วนนี้จะอธิบายวิธีเพิ่มประสิทธิภาพแอปพลิเคชันตัวรับสัญญาณเมื่อเปิดใช้บน Smart Display และวิธีปรับแต่งตัวควบคุมโปรแกรมเล่น
การเข้าถึงการควบคุม UI
คุณเข้าถึงออบเจ็กต์ตัวควบคุม UI สําหรับ Smart Display ได้โดยใช้ 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 สําหรับ Smart Display จะแสดงเป็นตัวอย่างด้านล่าง
--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 สําหรับ Smart Display จะแสดงดังนี้
--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
เลย์เอาต์การควบคุมเริ่มต้นจะแสดงดังนี้
เมื่อค่าของ SupportMediaCommands เท่ากับ PAUSE | QUEUE_PREV | QUEUE_NEXT
เลย์เอาต์การควบคุมเริ่มต้นจะแสดงดังนี้
เมื่อมีแทร็กข้อความ ปุ่มคําบรรยายจะแสดงที่ SLOT_1
เสมอ
หากต้องการเปลี่ยนค่า supportedMediaCommands
แบบไดนามิกหลังจากเริ่มใช้งานบริบทของผู้รับ คุณสามารถเรียกใช้ PlayerManager.setSupportedMediaCommands
เพื่อลบล้างค่าได้ นอกจากนี้ คุณสามารถเพิ่มคําสั่งใหม่โดยใช้ addSupportedMediaCommands
หรือนําคําสั่งที่มีอยู่ออกโดยใช้ removeSupportedMediaCommands
การปรับแต่งปุ่มควบคุม
คุณปรับแต่งการควบคุมได้โดยใช้ PlayerDataBinder
เพิ่มโค้ดต่อไปนี้ลงในไฟล์ js/receiver.js
ด้านล่าง TouchControl เพื่อตั้งค่าช่องการควบคุมแรกของคุณ:
...
// 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
การเรียกดูสื่อเป็นคุณลักษณะตัวรับสัญญาณ CAF ที่ผู้ใช้สามารถสํารวจเนื้อหาเพิ่มเติมบนอุปกรณ์ระบบสัมผัสได้ ในการใช้งาน คุณจะใช้ PlayerDataBinder
เพื่อตั้งค่า UI ของ BrowseContent
แล้วเติมข้อมูลด้วย BrowseItems
ตามเนื้อหาที่คุณต้องการแสดงได้
เรียกดูเนื้อหา
ด้านล่างนี้เป็นตัวอย่างของ UI และคุณสมบัติของ BrowseContent
BrowseContent.title
BrowseContent.items
สัดส่วนภาพ
ใช้ targetAspectRatio property
เพื่อเลือกสัดส่วนภาพที่ดีที่สุดสําหรับเนื้อหารูปภาพ CAF Receiver SDK รองรับสัดส่วนภาพ 3 รูปแบบ ได้แก่ SQUARE_1_TO_1
, PORTRAIT_2_TO_3
และ LANDSCAPE_16_TO_9
เรียกดูรายการ
ใช้ 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
เพิ่มโค้ดต่อไปนี้ที่สกัดกั้น LOAD
เพื่อแมป 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
}
บันทึกข้อความและแท็กที่กําหนดเอง
API ของ CastDebugLogger ช่วยให้คุณสร้างข้อความบันทึกที่จะปรากฏบนการวางซ้อนการแก้ไขข้อบกพร่องของผู้รับด้วยสีต่างๆ ได้ วิธีการบันทึกที่ใช้ได้มีดังนี้ โดยเรียงลําดับจากลําดับความสําคัญสูงสุดไปต่ําสุด
castDebugLogger.error(custom_tag, message);
castDebugLogger.warn(custom_tag, message);
castDebugLogger.info(custom_tag, message);
castDebugLogger.debug(custom_tag, message);
สําหรับวิธีบันทึกแต่ละวิธี พารามิเตอร์แรกคือแท็กที่กําหนดเอง ซึ่งอาจเป็นสตริงระบุตัวตนที่คุณคิดว่ามีความหมายก็ได้ CastDebugLogger
จะใช้แท็กเพื่อกรองบันทึก รายละเอียดการใช้แท็กมีคําอธิบายโดยละเอียดด้านล่าง พารามิเตอร์ที่สองคือข้อความบันทึก
หากต้องการแสดงบันทึกขณะใช้งาน ให้เพิ่มบันทึกไปยังสกัดกั้น 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
โปรดดูรายละเอียดเพิ่มเติมในคู่มือนักพัฒนาซอฟต์แวร์ตัวรับสัญญาณเว็บ