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

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

הלוגו של Google Cast

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

מה זה Google Cast?

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

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

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

מה אנחנו הולכים ליצור?

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

מה תלמדו

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

מה נדרש

ניסיון

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

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

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

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

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

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

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

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

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

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

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

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

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

הפעלת השרת

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

הלוגו של Google Chrome

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

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

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

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

תמונה של 'Cast Connect' פקדי יומן רישום של כלי 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 הזה יכיל את ממשק המשתמש של אפליקציית המקבל. כרגע הוא ריק, ואנחנו נוסיף לו אותו במהלך שיעור ה-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> הטעינה של 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 ו-Logger&#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 & Logger Controls&#39; בכלי לניהול (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(). כך תוכלו ליירט הודעות נכנסות לפי סוג ולשנות אותן לפני שהן מגיעות למטפל ההודעות הפנימי של ה-SDK. בקטע הזה נדון בבקשות LOAD, שבהן נעשה את הפעולות הבאות:

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

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

Sample API

אפשר להיכנס לכתובת https://storage.googleapis.com/cpe-sample-media/content.json ולעיין בקטלוג הסרטונים לדוגמה שלנו. התוכן כולל כתובות URL של תמונות פוסטרים בפורמט png וגם סטרימינג של DASH ו-HLS. השידורים של DASH ו-HLS מפנים למקורות וידאו ואודיו שעברו ניתוק קודק (demux) ונשמרים במאגרי 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, סוג ברירת המחדל של מאגר הנתונים הצפוי הוא transport stream‏ (TS). כתוצאה מכך, אם רק המאפיין contentUrl ישתנה, המקלט ינסה לפתוח את זרמי ה-MP4 לדוגמה בפורמט TS. בבקשת הטעינה, צריך לשנות את האובייקט 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) ומגדירים את מזהה האפליקציה כמזהה האפליקציה של המקבל. בוחרים את המכשיר באמצעות לחצן ההעברה.

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

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; מופעלים

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

// 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 וכלי בקרה ובקרה (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 אפשר לתעד בקלות אירועי נגן שמופעל על ידי ה-SDK של CAF Receiver, ולהשתמש ברמות שונות של יומן כדי לתעד את נתוני האירוע. קובץ התצורה 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.

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