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

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

הלוגו של Google Cast

בשיעור הזה תלמדו איך ליצור אפליקציה מותאמת אישית של Web Receiver כדי להפעיל תוכן במכשירים שתומכים בהעברה (cast).

מה זה Google Cast?

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

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

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

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

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

מה תלמדו

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

מה הדרישות כדי להצטרף לתוכנית?

ניסיון

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

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

קריאה בלבד קריאה והשלמה של התרגילים

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

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

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

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

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

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

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

3. פריסה מקומית של הנמען

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

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

הפעלת השרת

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

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

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

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

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

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

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

בוחרים באפשרות 'Custom Receiver', זה מה שאנחנו יוצרים.

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

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

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

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

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

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

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

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

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

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

הלוגו של Google Chrome

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

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

תמונה של הכרטיסייה 'Cast Connect & Logger' של כלי הפקודה והבקרה (CaC)

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

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

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

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

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

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

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

index.html

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

receiver.js

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

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

מקלט העברה בסיסי יאתחל את פעילות ההעברה בזמן ההפעלה. פעולה זו נדרשת כדי להודיע לכל אפליקציות השולח המחוברות שמעלות את המקבל בהצלחה. בנוסף, ערכת ה-SDK החדשה מוגדרת מראש לטיפול במדיה בסטרימינג בקצב העברת נתונים דינמי (באמצעות DASH, HLS ו-Smooth Streaming) וקובצי MP4 רגילים לאחר הוצאת האריזה. בואו ננסה את זה.

אתחול

מוסיפים את הקוד הבא ל-index.html בכותרת:

<head>
  ...

  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>

צריך להוסיף את הקוד הבא אל index.html <body> לפני <footer> טעינה של receiver.js, כדי לספק ל-SDK של המקבל מקום כדי להציג את ממשק המשתמש של המקבל שמוגדר כברירת מחדל שנשלח עם הסקריפט החדש.

<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 כדי לנסות את המקלט החדש שלך.

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

תמונה של הכרטיסייה &#39;Cast Connect & Logger&#39; של כלי הפקודה והבקרה (CaC)

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

העברה (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 או החדרת מידע על הפסקות למודעות.

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

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

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

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

כך שה-SDK של המקבל מטפל באופן ייחודי:

  • מאתחל את סשן ההעברה
  • טיפול בבקשות 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 לדוגמה שסופק מציג את הפתקים של ה-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. כדי לשנות את המאפיינים 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;
            ...
          }
        });
      });
    });

שווה לנסות

שוב, פותחים את כלי Command and Control (CaC) ומגדירים את מזהה האפליקציה כמזהה האפליקציה של המקבל. בוחרים את המכשיר באמצעות לחצן הפעלת Cast.

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

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

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

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

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

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

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

גישה לפקדים בממשק המשתמש

אפשר לגשת לאובייקט בממשק המשתמש עבור מסכים חכמים באמצעות 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 });

לחצני הבקרה שמוגדרים כברירת מחדל מוקצים לכל יחידת קיבולת (Slot) על סמך 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 שמתחת לפקדי המגע:

...

// 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 ולמאפיינים שלו:

תמונה של ממשק המשתמש של ExploreContent שבו מוצגות שתי תמונות ממוזערות של סרטון וחלק של סרטון

  1. BrowseContent.title
  2. BrowseContent.items

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

אפשר להשתמש במאפיין targetAspectRatio property כדי לבחור את יחס הגובה-רוחב הטוב ביותר לנכסי התמונות. ערכת ה-SDK של המקבל ב-CAF תומכת בשלושה יחסי גובה-רוחב: SQUARE_1_TO_1, PORTRAIT_2_TO_3, LANDSCAPE_16_TO_9.

BrowseItem

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

תמונה של ממשק המשתמש של ExploreContent שבו מוצגות שתי תמונות ממוזערות של סרטון וחלק של סרטון

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

הגדרת נתוני דפדוף במדיה

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

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 במכשיר המקבל.

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

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

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