1. ภาพรวม
Codelab นี้จะสอนวิธีสร้างแอปตัวรับเว็บที่กําหนดเองเพื่อเล่นเนื้อหาบนอุปกรณ์ที่พร้อมใช้งาน Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยังทีวีได้ ผู้ใช้สามารถใช้อุปกรณ์เคลื่อนที่หรือเบราว์เซอร์ Chrome บนเดสก์ท็อปเป็นรีโมตคอนโทรลสําหรับการเล่นสื่อบนทีวีได้
Google Cast SDK อนุญาตให้แอปควบคุมอุปกรณ์ที่พร้อมใช้งาน Google Cast (เช่น ทีวีหรือระบบเสียง) Cast SDK มีคอมโพเนนต์ UI ที่จําเป็นโดยอิงจากรายการตรวจสอบการออกแบบ Google Cast
รายการตรวจสอบการออกแบบ Google Cast มีไว้เพื่อช่วยให้ผู้ใช้ได้รับประสบการณ์การแคสต์ที่ใช้งานง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ ดูเพิ่มเติมที่นี่
สิ่งที่เรากําลังสร้าง
เมื่อ Codelab เสร็จสิ้น คุณจะมีแอป HTML5 ที่ทําหน้าที่เป็นตัวรับที่กําหนดเองซึ่งสามารถแสดงเนื้อหาวิดีโอในอุปกรณ์ที่พร้อมใช้งาน Cast
สิ่งที่คุณจะได้เรียนรู้
- วิธีตั้งค่าการพัฒนาผู้รับ
- พื้นฐานของตัวรับที่พร้อมใช้งาน Cast ตามเฟรมเวิร์กแอปพลิเคชันแคสต์
- วิธีรับวิดีโอที่แคสต์
- วิธีผสานรวมบันทึกการแก้ไขข้อบกพร่อง
- วิธีเพิ่มประสิทธิภาพตัวรับสําหรับจอแสดงผลอัจฉริยะ
สิ่งที่ต้องมี
- เบราว์เซอร์ล่าสุดใน Google Chrome
- บริการโฮสติ้ง HTTPS เช่น Firebase Hosting หรือ ngrok
- อุปกรณ์ Google Cast เช่น Chromecast หรือ Android TV ที่กําหนดค่าด้วยการเข้าถึงอินเทอร์เน็ต
- ทีวีหรือจอภาพที่มีอินพุต HDMI
ประสบการณ์การใช้งาน
- คุณจะต้องมีความรู้เกี่ยวกับการพัฒนาเว็บมาก่อน
- และคุณก็ต้องมีความรู้เกี่ยวกับการดูทีวีด้วยนะ :)
คุณจะใช้บทแนะนํานี้อย่างไร
คุณจะให้คะแนนประสบการณ์ในการสร้างเว็บแอปอย่างไร
คุณจะให้คะแนนประสบการณ์ในการรับชมทีวีอย่างไร
2. รับโค้ดตัวอย่าง
คุณสามารถดาวน์โหลดโค้ดตัวอย่างทั้งหมดลงในคอมพิวเตอร์...
และแตกไฟล์ ZIP ที่ดาวน์โหลด
3. ทําให้ผู้รับใช้งานได้ในเครื่อง
หากต้องการใช้อุปกรณ์รับเว็บกับอุปกรณ์แคสต์ คุณต้องโฮสต์อุปกรณ์ดังกล่าวไว้ที่ใดที่อุปกรณ์แคสต์สามารถเข้าถึงอุปกรณ์ได้ หากมีเซิร์ฟเวอร์ที่รองรับ https อยู่แล้ว ให้ข้ามวิธีการต่อไปนี้และจดบันทึก URL ไว้ เนื่องจากคุณจะต้องใช้ข้อมูลนี้ในส่วนถัดไป
หากไม่มีเซิร์ฟเวอร์ที่ใช้งานได้ ให้ใช้ Firebase Hosting หรือ ngrok
เรียกใช้เซิร์ฟเวอร์
เมื่อคุณตั้งค่าบริการที่ต้องการแล้ว ให้ไปที่ app-start
และเริ่มเซิร์ฟเวอร์
จดบันทึก URL สําหรับผู้รับที่โฮสต์ไว้ ซึ่งจะใช้ในส่วนถัดไป
4. ลงทะเบียนแอปพลิเคชันใน Cast Developer Console
คุณต้องลงทะเบียนแอปพลิเคชันเพื่อให้อุปกรณ์รับสัญญาณที่กําหนดเองทํางานดังที่ปรากฏใน Codelab นี้บนอุปกรณ์ Chromecast หลังจากลงทะเบียนแอปพลิเคชันแล้ว คุณจะได้รับรหัสแอปพลิเคชันซึ่งแอปพลิเคชันผู้ส่งต้องใช้ในการเรียกใช้ API เช่น ในการเปิดแอปพลิเคชันตัวรับ
คลิก "เพิ่มแอปพลิเคชันใหม่"
เลือก "ผู้รับที่กําหนดเอง" นี่คือสิ่งที่เรากําลังสร้าง
ป้อนรายละเอียดผู้รับใหม่ อย่าลืมใช้ URL ที่คุณไปถึง
ในส่วนสุดท้าย จดบันทึกรหัสแอปพลิเคชันที่กําหนดให้กับผู้รับรายใหม่
นอกจากนี้ คุณยังต้องลงทะเบียนอุปกรณ์ Google Cast เพื่อให้เข้าถึงแอปพลิเคชันผู้รับได้ก่อนที่จะเผยแพร่เครื่อง เมื่อคุณเผยแพร่แอปพลิเคชันตัวรับสัญญาณแล้ว แอปพลิเคชันจะใช้งานได้กับอุปกรณ์ Google Cast ทั้งหมด เพื่อวัตถุประสงค์ของ Codelab นี้ ขอแนะนําให้ทํางานกับแอปพลิเคชันตัวรับที่ไม่ได้เผยแพร่
คลิก "เพิ่มอุปกรณ์ใหม่"
ป้อนหมายเลขซีเรียลที่พิมพ์ไว้ด้านหลังอุปกรณ์แคสต์และตั้งชื่อที่สื่อความหมาย คุณยังดูหมายเลขซีเรียลได้โดยแคสต์หน้าจอใน Chrome เมื่อเข้าถึงคอนโซลของนักพัฒนาซอฟต์แวร์ของ Google Cast SDK
อาจใช้เวลา 5-15 นาทีก่อนที่ผู้รับและอุปกรณ์จะพร้อมทดสอบ หลังจากรอ 5-15 นาที คุณต้องรีบูตอุปกรณ์แคสต์
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
การออกแบบแอป
แอปผู้รับจะเริ่มต้นเซสชันการแคสต์และสแตนด์บายจนกว่าจะมีการคําขอ LOAD (หรือคําสั่งให้เล่นสื่อ 1 ชิ้น) จากผู้ส่งมาถึง
แอปประกอบด้วยข้อมูลพร็อพเพอร์ตี้หลัก 1 รายการ ที่กําหนดไว้ใน index.html
และไฟล์ JavaScript 1 รายการชื่อ js/receiver.js
ซึ่งมีตรรกะทั้งหมดที่ทําให้ผู้รับใช้งานได้
index.html
ไฟล์ HTML นี้จะมี UI ของแอปตัวรับของเรา สําหรับตอนนี้ข้อมูลจะว่างเปล่าและเราจะเพิ่มไปยัง UI ตลอดห้องทดลองโค้ด
Receiver.js
สคริปต์นี้จะจัดการตรรกะทั้งหมดสําหรับแอปตัวรับของเรา แต่ตอนนี้นี่เป็นเพียงไฟล์ว่าง แต่เราจะเปลี่ยนให้ตัวรับการแคสต์ทํางานได้อย่างสมบูรณ์พร้อมโค้ดเพียงไม่กี่บรรทัดในส่วนถัดไป
7. ตัวรับการแคสต์พื้นฐาน
ตัวรับการแคสต์พื้นฐานจะเริ่มเซสชันการแคสต์เมื่อเริ่มต้นใช้งาน ขั้นตอนนี้จําเป็นสําหรับการแจ้งแอปพลิเคชันผู้ส่งที่เชื่อมต่อทั้งหมดว่าการนําตัวรับสําเร็จ นอกจากนี้ SDK ใหม่ยังได้รับการกําหนดค่าไว้ล่วงหน้าเพื่อจัดการสื่อสตรีมมิงแบบอัตราบิตที่ปรับเปลี่ยนได้ (โดยใช้ DASH, HLS และสตรีมมิงที่ราบรื่น) และไฟล์ 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)
จะแทนที่รหัสแอปของคุณเองตามที่ได้ลงทะเบียนไว้ก่อนหน้านี้ในช่อง แล้วคลิก "ตั้งค่ารหัสแอป" เครื่องมือนี้สั่งให้เครื่องมือใช้ตัวรับสัญญาณเมื่อเริ่มต้นเซสชันการแคสต์
การแคสต์สื่อ
ในระดับสูง หากต้องการเล่นสื่อในอุปกรณ์แคสต์ คุณต้องดําเนินการต่อไปนี้
- ผู้ส่งสร้างออบเจ็กต์
JSON
ของMediaInfo
จาก Cast SDK ซึ่งจําลองรายการสื่อ - ผู้ส่งเชื่อมต่อกับอุปกรณ์แคสต์เพื่อเปิดแอปพลิเคชันตัวรับ
- ผู้รับจะโหลดออบเจ็กต์
MediaInfo
ผ่านคําขอLOAD
ที่จะเปิดเนื้อหา - ผู้รับจะตรวจสอบและติดตามสถานะสื่อ
- ผู้ส่งจะส่งคําสั่งการเล่นไปยังผู้รับเพื่อควบคุมการเล่นตามการโต้ตอบของผู้ใช้กับแอปของผู้ส่ง
ในความพยายามพื้นฐานครั้งแรกนี้ เราจะป้อน MediaInfo
ด้วย URL เนื้อหาที่เล่นได้ (จัดเก็บอยู่ใน MediaInfo.contentUrl
)
ผู้ส่งในชีวิตจริงจะใช้ตัวระบุสื่อเฉพาะแอปพลิเคชันใน MediaInfo.contentId
ผู้รับจะใช้ contentId
เป็นตัวระบุเพื่อเรียกใช้ API แบ็กเอนด์ที่เหมาะสมเพื่อแก้ไข URL ของชิ้นงานจริงและตั้งค่าเป็น MediaInfo.contentUrl.
ซึ่งผู้รับจะจัดการกับงานต่างๆ เช่น การซื้อใบอนุญาต DRM หรือการแทรกข้อมูลเกี่ยวกับช่วงพักโฆษณาด้วย
เราจะขยายการใช้งานผู้รับของคุณเพื่อดําเนินการในลักษณะดังกล่าวในส่วนถัดไป สําหรับตอนนี้ ให้คลิกไอคอนแคสต์แล้วเลือกอุปกรณ์เพื่อเปิดผู้รับ
ไปที่แท็บ "โหลดสื่อ" แล้วคลิกปุ่ม "โหลดตามเนื้อหา" ผู้รับควรเริ่มเล่นเนื้อหาตัวอย่าง
ดังนั้น 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 และวิธีปรับแต่งตัวควบคุมโปรแกรมเล่น
การเข้าถึงการควบคุม 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 สําหรับ 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. การใช้การเรียกดูสื่อบนจออัจฉริยะ
การเรียกดูสื่อเป็นฟีเจอร์ตัวรับสัญญาณ CAF ที่ช่วยให้ผู้ใช้สํารวจเนื้อหาเพิ่มเติมในอุปกรณ์ระบบสัมผัสได้ ในการดําเนินการดังกล่าว คุณจะต้องใช้ PlayerDataBinder
เพื่อตั้งค่า UI ของ BrowseContent
จากนั้น คุณป้อนข้อมูล BrowseItems
ได้โดยอิงตามเนื้อหาที่ต้องการแสดง
เรียกดูเนื้อหา
ด้านล่างนี้เป็นตัวอย่างของ UI และพร็อพเพอร์ตี้ BrowseContent
BrowseContent.title
BrowseContent.items
อัตราส่วน
ใช้ targetAspectRatio property
เพื่อเลือกสัดส่วนภาพที่ดีที่สุดสําหรับชิ้นงานรูปภาพ อัตราส่วน CAF Receiver ที่รองรับคือ 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
เพื่อตั้งค่ารายการเรียกดูที่ใช้ชื่อ "Next Next"
// 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. การแก้ไขข้อบกพร่องของแอปตัวรับ
SDK อุปกรณ์รับการแคสต์เป็นอีกตัวเลือกหนึ่งสําหรับนักพัฒนาแอปในการแก้ไขข้อบกพร่องของแอปตัวรับได้ง่ายโดยใช้ CastDebugLogger API และเครื่องมือคําสั่งและการควบคุม (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
คุณจะบันทึกเหตุการณ์ของโปรแกรมเล่นที่ SDK ผู้รับ CA เริ่มทํางานได้โดยง่าย และใช้ระดับการบันทึกต่างๆ เพื่อบันทึกข้อมูลเหตุการณ์ การกําหนดค่า 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,
};
แก้ปัญหาการวางซ้อน
เครื่องบันทึกการแก้ไขข้อบกพร่องของแคสต์จะมีการวางซ้อนการแก้ไขข้อบกพร่องบนตัวรับเพื่อแสดงข้อความบันทึกที่กําหนดเองในอุปกรณ์แคสต์ ใช้ 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. ขอแสดงความยินดี
ตอนนี้คุณรู้วิธีสร้างแอปพลิเคชันตัวรับสัญญาณที่กําหนดเองบนเว็บแล้วโดยใช้ SDK ตัวรับสัญญาณบนเว็บ
โปรดดูรายละเอียดเพิ่มเติมในคู่มือนักพัฒนาแอปเว็บตัวรับ