יצירת מקלט אינטרנט מותאם אישית

1. סקירה כללית

הלוגו של Google Cast

ב-codelab הזה נסביר איך ליצור אפליקציית מקלט אינטרנט בהתאמה אישית להפעלת תוכן במכשירים עם תמיכה ב-Cast.

מה זה Google Cast?

עם Google Cast, משתמשים יכולים להפעיל Cast של תוכן מנייד לטלוויזיה. לאחר מכן, המשתמשים יכולים להשתמש בנייד או בדפדפן Chrome במחשב בתור שלט רחוק להפעלת מדיה בטלוויזיה.

ערכת ה-SDK של Google Cast מאפשרת לאפליקציה שלכם לשלוט במכשירים שתומכים ב-Google Cast (לדוגמה, טלוויזיה או מערכת שמע). ערכת Cast SDK מספקת לכם את רכיבי ממשק המשתמש הנדרשים על סמך רשימת המשימות לעיצוב של Google Cast.

הכנו רשימת משימות לעיצוב Google Cast כדי שחוויית המשתמש תהיה פשוטה וצפויה בכל הפלטפורמות הנתמכות. מידע נוסף

מה אנחנו הולכים לבנות?

בסיום ה-codelab הזה, תהיה לכם אפליקציית HTML5 שתפעל כמקלט מותאם אישית משלכם, ותוכל להציג תוכן וידאו במכשירים עם תמיכה ב-Cast.

מה תלמדו

  • איך מתחילים לפתח מקלטים.
  • היסודות של מכשיר מקלט עם תמיכה ב-Cast שמבוסס על Cast Application Framework.
  • איך מקבלים סרטון שהופעל בו Cast.
  • איך משלבים את כלי הרישום של ניפוי הבאגים.
  • איך מבצעים אופטימיזציה של המקלט למסכים חכמים.

הדרישות

חוויה

  • צריך ידע קודם בפיתוח אתרים.
  • תצטרכו גם ידע קודם בצפייה בטלוויזיה :)

איך תשתמשו במדריך הזה?

רק לקרוא לקרוא ולבצע את התרגילים

מה מידת שביעות הרצון שלך מחוויית בניית אפליקציות אינטרנט?

מתחילים ביניים מומחים

איך היית מדרג את חוויית הצפייה בטלוויזיה?

מתחילים ביניים מומחים

2. קבלת קוד לדוגמה

אפשר להוריד את כל קוד הדוגמה למחשב...

ומחלצים את קובץ ה-ZIP שהורד.

3. פריסת המקלט באופן מקומי

כדי להשתמש במקלט האינטרנט עם מכשיר Cast, צריך לארח אותו במקום שמכשיר Cast יכול להגיע אליו. אם כבר יש לכם שרת שתומך ב-HTTPS, דלגו על ההוראות הבאות ורשמו את כתובת ה-URL, כי תצטרכו אותה בסעיף הבא.

אם אין לכם שרת זמין לשימוש, אתם יכולים להשתמש באירוח ב-Firebase או ב-ngrok.

הפעלת השרת

אחרי שמגדירים את השירות הרצוי, עוברים אל app-start ומפעילים את השרת.

רושמים את כתובת ה-URL של הנמען המתארח. תשתמשו בו בקטע הבא.

4. רישום אפליקציה ב-Cast Developer Console

כדי להפעיל במכשירי Chromecast מקלט בהתאמה אישית, כמו זה שמופיע במעבדת התכנות הזו, צריך לרשום את האפליקציה. אחרי שרושמים את האפליקציה, מקבלים מזהה אפליקציה שצריך להשתמש בו באפליקציית השולח כדי לבצע קריאות ל-API, למשל כדי להפעיל אפליקציית מקלט.

תמונה של Google Cast SDK Developer Console עם הלחצן 'Add New Application' (הוספת אפליקציה חדשה) מודגש

לוחצים על 'הוספת אפליקציה חדשה'.

תמונה של המסך 'New Receiver Application' (אפליקציית מקלט חדשה) עם הדגשה של האפשרות 'Custom Receiver' (מקלט בהתאמה אישית)

בוחרים באפשרות 'מקלט מותאם אישית'. זה מה שאנחנו יוצרים.

תמונה של המסך 'מקלט מותאם אישית חדש' שמוצגת בו כתובת URL שמישהו מקליד בשדה 'כתובת ה-URL של אפליקציית המקלט'

מזינים את הפרטים של הנמען החדש, וחשוב להשתמש בכתובת ה-URL שקיבלתם.

בקטע האחרון. רושמים את מזהה האפליקציה שהוקצה למקלט החדש.

בנוסף, צריך לרשום את מכשיר Cast כדי שיוכל לגשת לאפליקציית המקלט לפני שמפרסמים אותה. אחרי שמפרסמים את אפליקציית המקלט, היא זמינה לכל מכשירי Google Cast. לצורך ה-codelab הזה, מומלץ לעבוד עם אפליקציית מקלט לא גלויה.

תמונה של Google Cast SDK Developer Console עם הלחצן 'הוספת מכשיר חדש' מודגש

לוחצים על 'הוספת מכשיר חדש'.

תמונה של תיבת הדו-שיח 'הוספת מכשיר Cast לקליטה'

מזינים את המספר הסידורי שמודפס על גב מכשיר ה-Cast ונותנים לו שם תיאורי. אפשר גם למצוא את המספר הסידורי על ידי הפעלת Cast למסך ב-Chrome כשניגשים אל Google Cast SDK Developer Console

יחלפו 5-15 דקות עד שהמקלט והמכשיר יהיו מוכנים לבדיקה. אחרי שמחכים 5-15 דקות, צריך להפעיל מחדש את מכשיר ה-Cast.

5. הרצת האפליקציה לדוגמה

הלוגו של Google Chrome

בזמן שאנחנו מחכים שאפליקציית המקלט החדשה שלנו תהיה מוכנה לבדיקה, בואו נראה איך נראית אפליקציית מקלט לדוגמה שהושלמה. המקלט שנבנה יוכל להפעיל מדיה באמצעות שידור בקצב העברת נתונים משתנה (נשתמש בתוכן לדוגמה שמקודד לשידור דינמי שניתן להתאמה באמצעות HTTP‏ (DASH)).

פותחים את הכלי לניהול פקודות ושליטה (CaC) בדפדפן.

תמונה של הכרטיסייה Cast Connect & Logger Controls (שליטה ב-Cast Connect וברישום ביומן) בכלי Command and Control (פקודה ושליטה, CaC)

  1. אמור להופיע הכלי שלנו לחישוב עלות לרכישה.
  2. משתמשים במזהה ברירת המחדל של המקלט לדוגמה CC1AD845 ולוחצים על הלחצן Set App ID (הגדרת מזהה האפליקציה).
  3. לוחצים על הכפתור להפעלת Cast בפינה הימנית העליונה ובוחרים את מכשיר Cast.

תמונה של הכרטיסייה 'Cast Connect & Logger Controls' בכלי Command and Control (CaC) שמראה שהיא מחוברת לאפליקציית מקלט

  1. עוברים לכרטיסייה 'טעינת מדיה' בחלק העליון.

תמונה של הכרטיסייה 'טעינת מדיה' בכלי Command and Control (CaC)

  1. כדי להפעיל סרטון לאימון המודל, לוחצים על הלחצן Load by Content (טעינה לפי תוכן).
  2. הסרטון יתחיל לפעול במכשיר Google Cast כדי להראות איך נראית פונקציונליות בסיסית של מקלט באמצעות מקלט ברירת המחדל.

6. הכנת פרויקט ההתחלה

אנחנו צריכים להוסיף תמיכה ב-Google Cast לאפליקציית ההפעלה שהורדת. הנה כמה מונחים שקשורים ל-Google Cast שבהם נשתמש ב-codelab הזה:

  • אפליקציית השולח פועלת במכשיר נייד או במחשב נייד,
  • אפליקציית מקלט פועלת במכשיר Cast.

עכשיו אפשר להשתמש בפרויקט המתחיל כבסיס ולבנות עליו באמצעות כלי לעריכת טקסט המועדף:

  1. בוחרים את ספריית סמל תיקייהapp-start מתוך קובץ קוד לדוגמה שהורדתם.
  2. פתיחה של js/receiver.js ושל index.html

הערה: במהלך העבודה עם ה-codelab הזה, המערכת http-server אמורה לזהות את השינויים שתבצעו. אם אתם מבחינים שהיא לא מופיעה, נסו להפסיק את הפעולה של http-server ולהפעיל אותה מחדש.

עיצוב אפליקציות

אפליקציית המקלט מאתחלת את סשן ה-Cast ותמתין עד שתגיע בקשת LOAD (כלומר, הפקודה להפעלה חוזרת של קטע מדיה) מהשולח.

האפליקציה מורכבת מתצוגה ראשית אחת, שמוגדרת בקובץ index.html, ומקובץ JavaScript אחד בשם js/receiver.js שמכיל את כל הלוגיקה שדרושה כדי שהמקלט יעבוד.

index.html

קובץ ה-HTML הזה יכיל את ממשק המשתמש של אפליקציית המקלט שלנו. בשלב הזה הוא ריק, ואנחנו נוסיף לו תוכן במהלך שיעור ה-Lab.

receiver.js

הסקריפט הזה ינהל את כל הלוגיקה של אפליקציית המקלט שלנו. כרגע זה רק קובץ ריק, אבל בקטע הבא נהפוך אותו למקלט Cast שמתפקד באופן מלא, עם כמה שורות קוד בלבד.

7. מקלט Cast בסיסי

מקלט Cast בסיסי יאתחל את סשן ה-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 של המקלט מקום להצגת ממשק המשתמש של המקלט שמוגדר כברירת מחדל, שמגיע עם הסקריפט שהוספתם זה עתה.

<cast-media-player></cast-media-player>

עכשיו צריך להפעיל את ה-SDK בקובץ js/receiver.js, שכולל:

  • קבלת הפניה אל CastReceiverContext, נקודת הכניסה הראשית לכל Receiver SDK
  • אחסון הפניה אל PlayerManager, האובייקט שמטפל בהפעלה ומספק לכם את כל ה-hooks שאתם צריכים כדי להוסיף את הלוגיקה המותאמת אישית שלכם
  • אתחול ה-SDK על ידי קריאה ל-start() ב-CastReceiverContext

מוסיפים את הטקסט הבא לקובץ js/receiver.js:

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

context.start();

8. העברה (cast) של תוכן וידאו 'בסיסי'

לצורך ה-Codelab הזה, משתמשים בכלי CaC כדי לנסות את המקלט החדש.

מפנים את דפדפן האינטרנט אל כלי Command and Control (CaC).

תמונה של הכרטיסייה Cast Connect & Logger Controls (שליטה ב-Cast Connect וברישום ביומן) בכלי Command and Control (פקודה ושליטה, CaC)

חשוב להחליף את מזהה האפליקציה שלכם במזהה שרשמתם קודם בשדה וללחוץ על 'הגדרת מזהה האפליקציה'. ההוראה הזו אומרת לכלי להשתמש במקלט שלכם כשמתחילים את סשן ה-Cast.

הפעלת Cast של מדיה

באופן כללי, כדי להפעיל מדיה במכשיר Cast צריך לבצע את הפעולות הבאות:

  1. השולח יוצר אובייקט MediaInfo JSON מ-Cast SDK שמדמה פריט מדיה.
  2. השולח מתחבר למכשיר Cast כדי להפעיל את אפליקציית המקלט.
  3. המקבל טוען את אובייקט MediaInfo באמצעות בקשת LOAD להפעלת התוכן.
  4. המקבל עוקב אחרי סטטוס המדיה.
  5. השולח שולח פקודות הפעלה למקלט כדי לשלוט בהפעלה על סמך אינטראקציות של המשתמש עם אפליקציית השולח.

בניסיון הבסיסי הראשון הזה נאכלס את MediaInfo בכתובת URL של נכס שאפשר להפעיל (מאוחסן ב-MediaInfo.contentUrl).

שולח בעולם האמיתי משתמש במזהה מדיה ספציפי לאפליקציה ב-MediaInfo.contentId. מקבל התוכן משתמש ב-contentId כמזהה כדי לבצע קריאות מתאימות לממשקי API של ה-Backend, כדי לפתור את כתובת ה-URL של הנכס בפועל ולהגדיר אותה ל-MediaInfo.contentUrl. מקבל התוכן יטפל גם במשימות כמו קבלת רישיון DRM או הוספת מידע על הפסקות פרסומיות.

בקטע הבא נרחיב את מקלט הנתונים כדי שיבצע פעולה דומה. בשלב הזה, לוחצים על סמל ההפעלה של Cast ובוחרים את המכשיר כדי לפתוח את המקלט.

תמונה של הכרטיסייה &#39;Cast Connect & Logger Controls&#39; בכלי Command and Control (CaC) שמראה שהיא מחוברת לאפליקציית מקלט

עוברים לכרטיסייה 'טעינת מדיה' ולוחצים על הלחצן 'טעינה לפי תוכן'. התוכן לדוגמה אמור להתחיל לפעול במכשיר המקלט.

תמונה של הכרטיסייה &#39;טעינת מדיה&#39; בכלי Command and Control (CaC)

לכן, ערכת ה-SDK של מקלט מטפלת ב:

  • אתחול של סשן Cast
  • טיפול בבקשות נכנסות LOAD משולחים שמכילות נכסים שניתן להפעיל
  • ממשק משתמש בסיסי של נגן שמוכן להצגה במסך גדול.

מומלץ לעיין בכלי CaC ובקוד שלו לפני שממשיכים לקטע הבא, שבו נרחיב את המקלט כדי שיוכל לתקשר עם API פשוט לדוגמה, במטרה למלא בקשות נכנסות של LOAD מהשולחים.

9. שילוב עם API חיצוני

בהתאם לאופן שבו רוב המפתחים יוצרים אינטראקציה עם Cast Receivers באפליקציות בעולם האמיתי, אנחנו הולכים לשנות את ה-Receiver שלנו כך שיטפל בבקשות LOAD שמפנות לתוכן המדיה המיועד באמצעות מפתח ה-API שלו, במקום לשלוח כתובת URL של נכס שניתן להפעלה.

אפליקציות עושות את זה בדרך כלל כי:

  • יכול להיות שהשולח לא יודע מהי כתובת ה-URL של התוכן.
  • אפליקציית Cast מיועדת לטפל באימות, בלוגיקה עסקית אחרת או בקריאות ל-API ישירות במקלט.

הפונקציונליות הזו מיושמת בעיקר בשיטה PlayerManager setMessageInterceptor(). כך תוכלו ליירט הודעות נכנסות לפי סוג ולשנות אותן לפני שהן מגיעות למטפל הפנימי בהודעות של ה-SDK. בקטע הזה נתייחס לבקשות LOAD שבהן נבצע את הפעולות הבאות:

  • קוראים את הבקשה הנכנסת LOAD ואת המאפיין המותאם אישית שלה contentId.
  • שולחים GET קריאה ל-API שלנו כדי לחפש את הנכס שאפשר להזרים לפי contentId.
  • משנים את בקשת LOAD באמצעות כתובת ה-URL של השידור.
  • משנים את האובייקט MediaInformation כדי להגדיר את הפרמטרים של סוג הסטרימינג.
  • העברת הבקשה אל ה-SDK להפעלה, או דחיית הפקודה אם אין לנו אפשרות לחפש את המדיה המבוקשת.

דוגמת ה-API שסיפקנו מדגימה את ה-hooks של ה-SDK להתאמה אישית של משימות נפוצות של מקלטים, תוך הסתמכות על חוויה מוכנה מראש.

Sample API

פותחים את כתובת ה-URL 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.

יירוט של בקשת הטעינה

בשלב הזה ניצור interceptor לטעינה עם פונקציה ששולחת בקשת 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.

שימוש בתוכן לדוגמה של API DASH

אחרי שהכנו את הכלי ליירוט טעינה, נציין את סוג התוכן לנמען. המידע הזה יספק למקבל את כתובת ה-URL של הפלייליסט הראשי ואת סוג ה-MIME של הסטרימינג. מוסיפים את הקוד הבא לקובץ js/receiver.js ב-LOAD interceptor's 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';
            ...
          }
        });
      });
    });

אחרי שתסיימו את השלב הזה, תוכלו להמשיך אל Testing It Out (בדיקה) כדי לנסות טעינה עם תוכן DASH. אם רוצים לבדוק טעינה עם תוכן HLS, אפשר לעבור לשלב הבא.

שימוש בתוכן לדוגמה של HLS API

ה-API לדוגמה כולל תוכן HLS וגם תוכן DASH. בנוסף להגדרת contentType כמו בשלב הקודם, בקשת הטעינה תצטרך כמה מאפיינים נוספים כדי להשתמש בכתובות ה-URL של HLS של ה-API לדוגמה. כשמקלט מוגדר להפעלה של סטרימינג HLS, סוג ברירת המחדל של הקונטיינר שצפוי הוא transport stream (TS). כתוצאה מכך, המקלט ינסה לפתוח את זרמי ה-MP4 לדוגמה בפורמט TS אם רק המאפיין contentUrl ישתנה. בבקשת הטעינה, צריך לשנות את האובייקט MediaInformation ולהוסיף לו מאפיינים נוספים כדי שהמקבל ידע שהתוכן הוא מסוג MP4 ולא TS. מוסיפים את הקוד הבא לקובץ js/receiver.js ב-load interceptor כדי לשנות את המאפיינים 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) ומגדירים את מזהה האפליקציה למזהה האפליקציה של המקלט. לוחצים על הכפתור להפעלת Cast כדי לבחור את המכשיר.

עוברים לכרטיסייה 'טעינת מדיה'. הפעם מוחקים את הטקסט בשדה 'כתובת URL של התוכן' לצד הלחצן 'טעינה לפי תוכן'. כך המערכת שלנו תיאלץ לשלוח בקשת LOAD שתכיל רק את ההפניה contentId למדיה שלנו.

תמונה של הכרטיסייה &#39;טעינת מדיה&#39; בכלי Command and Control (CaC)

בהנחה שהשינויים שביצעתם ב-receiver פעלו בצורה תקינה, ה-interceptor אמור לעצב את אובייקט MediaInfo כך שערכת ה-SDK תוכל להפעיל אותו במסך.

לוחצים על הלחצן 'טעינה לפי תוכן' כדי לבדוק אם המדיה פועלת בצורה תקינה. אפשר לשנות את Content ID למזהה אחר בקובץ content.json.

10. אופטימיזציה למסכים חכמים

מסכים חכמים הם מכשירים עם פונקציונליות של מגע, שמאפשרת לאפליקציות של מקלטים לתמוך באמצעי בקרה שמופעלים באמצעות מגע.

בקטע הזה מוסבר איך לבצע אופטימיזציה של אפליקציית המקלט כשמפעילים אותה בתצוגות חכמות, ואיך להתאים אישית את כפתורי הנגן.

גישה לרכיבי אינטראקטיביים

אפשר לגשת לאובייקט UI Controls של מסכים חכמים באמצעות 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, אובייקט הפקדים של ממשק המשתמש למסכים חכמים יוצג כמו בדוגמה שלמטה.

תמונה של סרטון שמופעל עם שכבת-על של לחצני ממשק משתמש

  1. --playback-logo-image
  2. MediaMetadata.subtitle
  3. MediaMetadata.title
  4. MediaStatus.currentTime
  5. MediaInformation.duration
  6. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.QUEUE_PREV
  7. ControlsSlot.SLOT_PRIMARY_1: ‏ControlsButton.SEEK_BACKWARD_30
  8. PLAY/PAUSE
  9. ControlsSlot.SLOT_PRIMARY_2: ‏ControlsButton.SEEK_FORWARD_30
  10. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.QUEUE_NEXT

בקרות אודיו

ב-MetadataType.MUSIC_TRACK, אובייקט אמצעי הבקרה בממשק המשתמש של מסכים חכמים יוצג כמו בדוגמה הבאה:

תמונה של מוזיקה שמתנגנת עם אמצעי בקרה של ממשק המשתמש שמוצגים מעל

  1. --playback-logo-image
  2. MusicTrackMediaMetadata.albumName
  3. MusicTrackMediaMetadata.title
  4. MusicTrackMediaMetadata.albumArtist
  5. MusicTrackMediaMetadata.images[0]
  6. MediaStatus.currentTime
  7. MediaInformation.duration
  8. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.NO_BUTTON
  9. ControlsSlot.SLOT_PRIMARY_1: ‏ControlsButton.QUEUE_PREV
  10. PLAY/PAUSE
  11. ControlsSlot.SLOT_PRIMARY_2: ‏ControlsButton.QUEUE_NEXT
  12. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.NO_BUTTON

עדכון של פקודות מדיה נתמכות

אובייקט אמצעי הבקרה של ממשק המשתמש קובע גם אם מוצג ControlsButton או לא, על סמך MediaStatus.supportedMediaCommands.

אם הערך של supportedMediaCommands שווה ל-ALL_BASIC_MEDIA, פריסת אמצעי הבקרה שמוגדרת כברירת מחדל תוצג כמו בתמונה הבאה:

תמונה של כפתורי הנגן: סרגל התקדמות, לחצן &#39;הפעלה&#39;, לחצנים &#39;דילוג קדימה&#39; ו &#39;דילוג אחורה&#39; מופעלים

אם הערך של supportedMediaCommands שווה ל-ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT, פריסת אמצעי הבקרה שמוגדרת כברירת מחדל תוצג כמו בתמונה הבאה:

תמונה של כפתורי הנגן: סרגל התקדמות, כפתור &#39;הפעלה&#39;, כפתורי &#39;דילוג קדימה&#39; ו&#39;דילוג אחורה&#39;, וכפתורי &#39;הוספה לתור הקודם&#39; ו&#39;הוספה לתור הבא&#39; שמופעלים

אם הערך של supportedMediaCommands שווה ל-PAUSE | QUEUE_PREV | QUEUE_NEXT, פריסת ברירת המחדל של אמצעי הבקרה תוצג כמו בדוגמה הבאה:

תמונה של כפתורי הנגן: סרגל התקדמות, לחצן &#39;הפעלה&#39; ולחצנים &#39;הוספה לתור של הקודם&#39; ו &#39;הוספה לתור של הבא&#39; שמופעלים

כשכתוביות זמינות, כפתור הכתוביות מוצג תמיד במיקום SLOT_1.

תמונה של כפתורי הנגן: סרגל התקדמות, כפתור &#39;הפעלה&#39;, כפתורי &#39;דילוג קדימה&#39; ו &#39;דילוג אחורה&#39;, כפתורי &#39;הוספה לתור הקודם&#39; ו &#39;הוספה לתור הבא&#39;, וכפתורי &#39;כתוביות סמויות&#39; שמופעלים

כדי לשנות באופן דינמי את הערך של 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. הטמעה של דפדוף במדיה במסכים חכמים

התכונה 'חיפוש מדיה' היא תכונה של CAF Receiver שמאפשרת למשתמשים לחפש תוכן נוסף במכשירי מגע. כדי להטמיע את זה, תשתמשו ב-PlayerDataBinder כדי להגדיר את ממשק המשתמש של BrowseContent. לאחר מכן תוכלו לאכלס אותו בBrowseItems על סמך התוכן שאתם רוצים להציג.

BrowseContent

למטה מופיעה דוגמה לממשק המשתמש של BrowseContent ולמאפיינים שלו:

תמונה של ממשק המשתמש BrowseContent עם שתי תמונות ממוזערות של סרטונים וחלק מתמונה ממוזערת שלישית

  1. BrowseContent.title
  2. BrowseContent.items

יחס גובה-רוחב

משתמשים בלחצן targetAspectRatio property כדי לבחור את יחס הגובה-רוחב הטוב ביותר לנכסי התמונות. ‫CAF Receiver SDK תומך בשלושה יחסי גובה-רוחב: SQUARE_1_TO_1,‏ PORTRAIT_2_TO_3 ו-LANDSCAPE_16_TO_9.

BrowseItem

משתמשים ב-BrowseItem כדי להציג את שם הפריט, כותרת המשנה, משך הזמן והתמונה של כל פריט:

תמונה של ממשק המשתמש BrowseContent עם שתי תמונות ממוזערות של סרטונים וחלק מתמונה ממוזערת שלישית

  1. BrowseItem.image
  2. BrowseItem.duration
  3. BrowseItem.title
  4. BrowseItem.subtitle

הגדרת נתוני עיון במדיה

אתם יכולים לספק רשימה של תוכן מדיה כדי לעיין בה על ידי התקשרות אל setBrowseContent. מוסיפים את הקוד הבא לקובץ js/receiver.js מתחת ל-playerDataBinder וב-event listener של MEDIA_CHANGED כדי להגדיר את הפריטים שמוצגים עם הכותרת Up 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 interceptor. מוסיפים את הקוד הבא ל-interceptor של 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 כדי להסיר את ממשק המשתמש של דפדוף במדיה.

12. ניפוי באגים באפליקציות של מקלט

ערכת Cast Receiver SDK מספקת למפתחים אפשרות נוספת לניפוי באגים באפליקציות של מקלטים בקלות, באמצעות CastDebugLogger API וכלי נלווה של Command and Control (CaC) לתיעוד יומנים.

אתחול

כדי לשלב את ה-API, מוסיפים את סקריפט המקור CastDebugLogger לקובץ index.html. צריך להצהיר על המקור בתג <head> אחרי ההצהרה על Cast Receiver 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 תוצג במכשיר המקבל.

תמונה של סרטון שמופעל עם ההודעה &#39;מצב ניפוי באגים&#39; שמופיעה על רקע אדום בפינה הימנית העליונה של הפריים

רישום אירועים ביומן של נגן

באמצעות CastDebugLogger אפשר בקלות לתעד אירועים של נגנים שמופעלים על ידי CAF Receiver SDK ולהשתמש ברמות שונות של רישום ביומן כדי לתעד את נתוני האירועים. התג loggerLevelByEvents config משתמש ב-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 משתמש בתגים כדי לסנן את היומנים. הסבר מפורט על השימוש בתגים מופיע בהמשך. הפרמטר השני הוא הודעת היומן.

כדי לראות את היומנים בפעולה, מוסיפים אותם ל-interceptor של 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, יוצגו כל ההודעות שנוספו עם הודעות יומן מסוג error, ‏ warn, ‏ info ו-debug. אם מפעילים תג מותאם אישית ברמה WARNING, יוצגו רק הודעות שגיאה ואזהרה ביומן.

ההגדרה loggerLevelByTags היא אופציונלית. אם לא מוגדר תג מותאם אישית לרמת היומן שלו, כל הודעות היומן יוצגו בשכבת העל של ניפוי הבאגים.

מוסיפים את הקוד הבא מתחת ל-CORE event logger:

// 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 Debug Logger מספק שכבת-על לניפוי באגים במקלט כדי להציג את הודעות היומן המותאמות אישית במכשיר 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.