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

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

הלוגו של Google Cast

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

מה זה Google Cast?

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

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

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

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

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

מה תלמדו

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

מה נדרש

ניסיון

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

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

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

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

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

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

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

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

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

ופורקים את קובץ ה-ZIP שהורדתם.

3. פריסה מקומית של המקבל

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

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

הפעלת השרת

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

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

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

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

תמונה של מסוף המפתחים של Google Cast SDK עם האפשרות 'הוספת אפליקציה חדשה' הלחצן מודגש

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

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

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

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

צריך להזין את הפרטים של המקבל החדש ולהשתמש בכתובת ה-URL שאליה הגעת

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

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

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

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

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

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

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

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

הלוגו של Google Chrome

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

בדפדפן, פותחים את כלי Command and Control (CaC).

תמונה של 'Cast Connect' פקדי יומן רישום של הכלי Command and Control (CaC)

  1. אתם אמורים לראות את הכלי שלנו ליצירת קובצי CaC.
  2. שימוש בברירת המחדל CC1AD845 מזהה מקלט לדוגמה ולוחצים על 'הגדרת מזהה אפליקציה' לחצן.
  3. לוחצים על הלחצן להפעלת Cast בפינה הימנית העליונה ובוחרים את מכשיר ה-Google Cast.

תמונה של 'Cast Connect' פקדי יומן רישום של כלי Command and Control (CaC), שמציינת שהוא מחובר לאפליקציה של המקבל

  1. עוברים אל 'טעינת מדיה'. למעלה.

תמונה של 'Load Media' של הכלי Command and Control (CaC)

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

6. מכינים את הפרויקט לתחילת העבודה

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

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

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

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

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

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

אפליקציית המקבל תתחיל את סשן ההעברה ותישאר במצב המתנה עד לבקשת LOAD (במילים אחרות, הפקודה להשמעת קטע מדיה) מהשולח.

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

index.html

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

receiver.js

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

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

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

עכשיו עלינו לאתחל את ה-SDK ב-js/receiver.js, והוא כולל:

  • מתקבלת הפניה אל CastReceiverContext, נקודת הכניסה הראשית שלך לכל ה-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).

תמונה של &#39;Cast Connect&#39; פקדי יומן רישום של הכלי 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 בקצה העורפי כדי לפענח את כתובת ה-URL של הנכס בפועל ולהגדיר אותה לערך MediaInfo.contentUrl. המקבל יטפל גם במשימות כמו רכישה של רישיון DRM או החדרת מידע על הפסקות למודעות.

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

תמונה של &#39;Cast Connect&#39; פקדי יומן רישום של כלי Command and Control (CaC), שמציינת שהוא מחובר לאפליקציה של המקבל

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

תמונה של &#39;Load Media&#39; של הכלי Command and Control (CaC)

לאחר מכן, ה-SDK של המקלט מטפל בנושאים הבאים:

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

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

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

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

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

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

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

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

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

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

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

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

תמונה של &#39;Load Media&#39; של הכלי Command and Control (CaC)

בהנחה שהכול עובד כמו שצריך עם השינויים במקלט, המיירט צריך לעצב את האובייקט 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-נגן> צריך להגדיר את touchScreenOptimizedApp ב-CastReceiverOptions. ב-Codelab הזה אנחנו משתמשים ברכיב <cast-media-נגן> לרכיב מסוים.

context.start({ touchScreenOptimizedApp: true });

לחצני הבקרה שמוגדרים כברירת מחדל מוקצים לכל משבצת לפי MetadataType ו-MediaStatus.supportedMediaCommands.

פקדי סרטונים

ב-MetadataType.MOVIE, ב-MetadataType.TV_SHOW וב-MetadataType.GENERIC, האובייקט של UI Controls במסכים חכמים יוצג כמו בדוגמה שבהמשך.

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

  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, האובייקט של UI Controls במסכים חכמים יוצג כך:

תמונה של מוזיקה שמתנגנת עם פקדים בממשק המשתמש מעל שכבת-על

  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

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

האובייקט של UI Controls גם קובע אם 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;הבאים בתור&#39; הלחצנים מופעלים

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

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

כשיש רצועות טקסט זמינות, לחצן הכתוביות תמיד מוצג ב-SLOT_1.

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

כדי לשנות באופן דינמי את הערך של supportedMediaCommands אחרי הפעלת הקשר של המקבל, אפשר להפעיל את PlayerManager.setSupportedMediaCommands כדי לשנות את הערך. אפשר גם להוסיף פקודה חדשה באמצעות addSupportedMediaCommands, או להסיר פקודה קיימת באמצעות removeSupportedMediaCommands.

התאמה אישית של לחצני הבקרה

אפשר להתאים אישית את אמצעי הבקרה באמצעות PlayerDataBinder. כדי להגדיר את המיקום הראשון של הפקדים, צריך להוסיף את הקוד הבא לקובץ js/receiver.js מתחת לפקדי המגע:

...

// 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 שמאפשרת למשתמשים לגלות תוכן נוסף במכשירי מגע. כדי ליישם את זה, צריך להגדיר את ממשק המשתמש של BrowseContent באמצעות PlayerDataBinder. אפשר לאכלס אותו ב-BrowseItems בהתאם לתוכן שרוצים להציג.

BrowseContent

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

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

  1. BrowseContent.title
  2. BrowseContent.items

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

יש להשתמש בtargetAspectRatio property כדי לבחור את יחס הגובה-רוחב הטוב ביותר לנכסי התמונות. ה-SDK של מקלט CAF תומך בשלושה יחסי גובה-רוחב: 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 כדי להגדיר את פריטי העיון עם הכותרת '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 כדי להסיר את ממשק המשתמש של עיון במדיה.

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

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

אתחול

כדי לשלב את ה-API, צריך להוסיף את סקריפט המקור CastDebugLogger בקובץ index.html. יש להצהיר על המקור דרך <head> לאחר הצהרת ה-SDK של מקלט שממנו רוצים להפעיל Cast.

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

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

עכשיו אתם יודעים איך ליצור אפליקציה מותאמת אישית של מקלט אינטרנט באמצעות ערכת ה-SDK של Cast WebReceiver.

לפרטים נוספים אפשר לעיין במדריך למפתחים של Web להתאיםr.