إنشاء جهاز استقبال ويب مخصص

1. نظرة عامة

شعار Google Cast

ستعلّمك هذه الدورة التدريبية على إنشاء تطبيق "مُستلِم ويب مخصّص" لتشغيل المحتوى على الأجهزة المزوّدة بتقنية البث.

ما هي تكنولوجيا Google Cast؟

تتيح تكنولوجيا Google Cast للمستخدمين بث المحتوى من جهاز جوّال إلى التلفزيون. ويمكن للمستخدمين بعد ذلك استخدام متصفّح Chrome على أجهزتهم الجوّالة أو أجهزة الكمبيوتر المكتبي كجهاز تحكّم عن بُعد لتشغيل الوسائط على التلفزيون.

تتيح حزمة تطوير البرامج (SDK) لتكنولوجيا Google Cast لتطبيقك التحكّم في الأجهزة المزوّدة بتكنولوجيا Google Cast (مثل التلفزيون أو نظام الصوت). تزودك حزمة تطوير البرامج (SDK) بتكنولوجيا Google Cast بمكونات واجهة المستخدم اللازمة بناءً على قائمة التحقق من تصميم Google Cast.

يتم توفير قائمة التحقّق من تصميم Google Cast لجعل تجربة المستخدم في Cast بسيطة ويمكن توقّعها على جميع المنصات المتوافقة. مزيد من المعلومات

ما الذي سننشئه؟

عند الانتهاء من هذا الدليل التعليمي حول رموز الترميز، سيكون لديك تطبيق HTML5 يعمل كجهاز استقبال مخصّص خاص بك ويمكنه عرض محتوى الفيديو على الأجهزة المزوّدة بتقنية Cast.

المُعطيات

  • كيفية الإعداد لتطوير جهاز الاستقبال
  • أساسيات جهاز الاستقبال المتوافق مع Cast استنادًا إلى إطار عمل تطبيق Cast
  • كيفية تلقّي فيديو يتم بثّه
  • كيفية دمج مسجّل تصحيح الأخطاء
  • كيفية تحسين جهاز الاستقبال للتوافق مع الشاشات الذكية

المتطلبات

  • أحدث إصدار من متصفّح Google Chrome
  • خدمة استضافة HTTPS، مثل استضافة Firebase أو ngrok
  • جهاز Google Cast، مثل Chromecast أو Android TV تم ضبطه للوصول إلى الإنترنت
  • تلفزيون أو شاشة مزوَّدة بمصدر إدخال HDMI

تجربة الاستخدام

  • يجب أن تكون لديك معرفة سابقة بتطوير الويب.
  • كما ستحتاج أيضًا إلى معرفة سابقة بكيفية مشاهدة التلفزيون :)

كيف ستستخدم هذا الدليل التعليمي؟

قراءته فقط قراءته وإكمال التمارين

ما مدى رضاك عن تجربتك في إنشاء تطبيقات الويب؟

مبتدئ متوسط متقدّم

ما مدى رضاك عن تجربة مشاهدة التلفزيون؟

مبتدئ متوسط متقدّم

2. الحصول على نموذج الرمز

يمكنك تنزيل جميع الرموز النموذجية على جهاز الكمبيوتر...

وفك ضغط ملف ZIP الذي تم تنزيله.

3- نشر جهاز الاستقبال على الجهاز

لكي تتمكّن من استخدام مستقبل الويب مع جهاز Cast، يجب استضافته في مكان يمكن لجهاز Cast الوصول إليه. إذا كان لديك خادم متاح لك يتوافق مع https، تخطّى التعليمات التالية ودوِّن عنوان URL، لأنّك ستحتاج إليه في القسم التالي.

إذا لم يكن لديك خادم متاح للاستخدام، يمكنك استخدام استضافة Firebase أو ngrok.

تشغيل الخادم

بعد إعداد الخدمة التي تختارها، انتقِل إلى app-start وابدأ تشغيل الخادم.

دوِّن عنوان URL لجهاز الاستقبال المستضاف. ستستخدمه في القسم التالي.

4. تسجيل تطبيق في Cast Developer Console

عليك تسجيل تطبيقك لتتمكّن من تشغيل جهاز استقبال مخصّص، كما هو موضّح في هذا الدرس التطبيقي، على أجهزة Chromecast. بعد تسجيل تطبيقك، ستتلقّى معرّف تطبيق يجب أن يستخدمه تطبيق المُرسِل لإجراء طلبات البيانات من واجهة برمجة التطبيقات، مثل تشغيل تطبيق المُستلِم.

صورة لـ Google Cast SDK Developer Console مع تمييز الزر "إضافة تطبيق جديد"

انقر على "إضافة تطبيق جديد".

صورة لشاشة "تطبيق مستلِم جديد" مع تمييز الخيار "مستلِم مخصّص"

اختَر "مستقبل مخصّص"، وهو ما سننشئه.

صورة لشاشة "جهاز استقبال مخصَّص جديد" يظهر فيها عنوان URL يكتبه أحد الأشخاص في الحقل "عنوان URL لتطبيق جهاز الاستقبال"

أدخِل تفاصيل جهاز الاستقبال الجديد، واحرص على استخدام عنوان URL الذي حصلت عليه.

في القسم الأخير. دوِّن رقم تعريف التطبيق الذي تمّ تعيينه لجهاز الاستقبال الجديد.

عليك أيضًا تسجيل جهاز Google Cast ليتمكّن من الوصول إلى تطبيق المُستلِم قبل نشره. بعد نشر تطبيق جهاز الاستقبال، سيكون متاحًا لجميع أجهزة Google Cast. لأغراض هذا الدرس التطبيقي حول الترميز، ننصحك بالعمل مع تطبيق مستقبل لم يتم نشره.

صورة لوحدة تحكّم المطوّر في Google Cast SDK مع تمييز الزر "إضافة جهاز جديد"

انقروا على "إضافة جهاز جديد"

صورة لمربّع الحوار "إضافة جهاز استقبال بث"

أدخِل الرقم التسلسلي المطبوع على الجهة الخلفية من جهاز البث وأضِف إليه اسمًا وصفيًا. يمكنك أيضًا العثور على الرقم التسلسلي من خلال بث الشاشة في Chrome عند الوصول إلى Play Console لـ Google Cast SDK.

ستستغرق عملية تجهيز جهاز الاستقبال والجهاز للاختبار مدة تتراوح بين 5 و15 دقيقة. بعد الانتظار لمدة تتراوح بين 5 و15 دقيقة، عليك إعادة تشغيل جهاز البث.

5- تشغيل نموذج التطبيق

شعار Google Chrome

في حين ننتظر أن يصبح تطبيق المُستلِم الجديد جاهزًا للاختبار، لنلقِ نظرة على شكل نموذج تطبيق مُستلِم مكتمل. سيكون جهاز الاستقبال الذي سننشئه قادرًا على تشغيل الوسائط باستخدام بث معدل نقل البيانات التكيُّفي (سنستخدم نموذج محتوى تم ترميزه للبث الديناميكي التكيُّفي عبر HTTP (DASH)).

في المتصفّح، افتح أداة "التحكّم والتوجيه" (CaC).

صورة علامة التبويب "عناصر تحكُّم الاتصال وأداة التسجيل" في أداة الأوامر والتحكّم (CaC)

  1. من المفترض أن تظهر لك أداة CaC.
  2. استخدِم معرّف المستلِم التلقائي "CC1AD845" وانقر على الزر "ضبط معرّف التطبيق".
  3. انقر على زر البث في أعلى يمين الشاشة واختَر جهاز Google Cast.

صورة لعلامة التبويب "عناصر التحكّم في Cast Connect وLogger " ضمن أداة "التحكّم والتوجيه" (CaC) تشير إلى أنّها مرتبطة بتطبيق مستقبل

  1. انتقِل إلى علامة التبويب "تحميل الوسائط" في أعلى الصفحة.

صورة لعلامة التبويب "تحميل الوسائط" في أداة "القيادة والتحكّم"

  1. انقر على الزر "التحميل حسب المحتوى" لتشغيل عيّنة فيديو.
  2. سيبدأ تشغيل الفيديو على جهاز Google Cast لإظهار وظائف جهاز الاستقبال الأساسية باستخدام "جهاز الاستقبال التلقائي".

6- إعداد مشروع البدء

يجب إضافة ميزة التوافق مع Google Cast إلى تطبيق البدء الذي نزّلته. في ما يلي بعض المصطلحات المتعلّقة بخدمة Google Cast التي سنستخدمها في هذا الدليل التعليمي حول البرمجة:

  • تطبيق مُرسِل يعمل على جهاز جوّال أو كمبيوتر محمول
  • تطبيق استقبال يعمل على جهاز Google Cast

أنت الآن جاهز لتطوير المشروع الأساسي باستخدام محرِّر النصوص المفضّل لديك:

  1. اختَر الدليل رمز المجلدapp-start من ملف نموذج الرمز الذي نزّلته.
  2. فتح js/receiver.js وindex.html

يُرجى العلم أنّه أثناء العمل على هذا الدرس التطبيقي حول الترميز، من المفترض أن ينفّذ "http-server" التغييرات التي تجريها. إذا لاحظت عدم حدوث ذلك، جرِّب إغلاق http-server وإعادة تشغيله.

تصميم التطبيق

يُنشئ تطبيق المُستلِم جلسة البث وسيظل في وضع الاستعداد إلى أن يصل طلب LOAD (بمعنى آخر، الأمر بتشغيل قطعة من الوسائط) من المُرسِل.

يتألف التطبيق من عرض رئيسي واحد محدّد في index.html وملف JavaScript واحد باسم js/receiver.js يحتوي على كل المنطق الذي يُشغِّل جهاز الاستقبال.

index.html

سيحتوي ملف html هذا على واجهة المستخدم لتطبيق المُستلِم. وهو فارغ في الوقت الحالي، وسنضيف إليه المزيد من خلال ورشة رموز التطبيقات.

receiver.js

سيدير هذا النص البرمجي جميع منطق تطبيق الاستقبال. وهو الآن ملف فارغ، لكننا سنحوّله إلى مستقبِل Cast يعمل بكامل وظائفه مع إضافة بضعة أسطر من الرموز فقط في القسم التالي.

7- جهاز استقبال بث أساسي

سيعمل مستقبِل البث الأساسي على إعداد جلسة البث عند بدء التشغيل. هذا ضروري لإبلاغ جميع تطبيقات المُرسِلين المتصلين بأنّ عرض المُستلِم تمت بنجاح. بالإضافة إلى ذلك، تأتي حزمة 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، نقطة الدخول الأساسية إلى حزمة تطوير البرامج (SDK) الخاصة بجهاز الاستقبال بالكامل
  • تخزين إشارة إلى PlayerManager، وهو العنصر الذي يعالج التشغيل ويقدّم لك كلّ العناصر التي تحتاج إليها لربط منطقك المخصّص
  • جارٍ إعداد حزمة تطوير البرامج (SDK) من خلال طلب الرقم start() في CastReceiverContext

أضِف ما يلي إلى js/receiver.js.

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

context.start();

8. بث محتوى الفيديو "الأساسي"

لأغراض هذا الدرس التطبيقي حول الترميز، استخدِم أداة CaC لتجربة المستلِم الجديد.

اضبط متصفح الويب على أداة التحكّم والمراقبة (CaC).

صورة لعلامة التبويب &quot;عناصر التحكّم في Cast Connect وLogger&quot; ضمن أداة &quot;التحكّم والتوجيه&quot; (CaC)

احرص على استبدال رقم تعريف التطبيق الخاص بك كما سجّلته سابقًا في الحقل، ثم انقر على "ضبط رقم تعريف التطبيق". يوجّه هذا الإجراء الأداة إلى استخدام جهاز الاستقبال عند بدء جلسة البث.

بث الوسائط

على مستوى عالٍ، يجب تنفيذ ما يلي لتشغيل الوسائط على جهاز بث الوسائط:

  1. ينشئ المُرسِل عنصر MediaInfo JSON من حزمة تطوير البرامج (SDK) لتطبيق Cast الذي يمثّل عنصر وسائط.
  2. يتصل المُرسِل بجهاز البث لتشغيل تطبيق المُستلِم.
  3. يحمّل المستلِم عنصر MediaInfo من خلال طلب LOAD لتشغيل المحتوى.
  4. يرصد جهاز الاستقبال حالة الوسائط ويتتبّعها.
  5. يرسل المُرسِل أوامر التشغيل إلى المُستلِم للتحكّم في التشغيل استنادًا إلى تفاعلات المستخدم مع تطبيق المُرسِل.

في هذه المحاولة الأساسية الأولى، سنعبئ MediaInfo بعنوان URL لمادة عرض قابلة للتشغيل (مخزّنة في MediaInfo.contentUrl).

يستخدم المرسِل الفعلي معرّف وسائط خاصًا بالتطبيق في MediaInfo.contentId. يستخدم المستلِم contentId كمعرّف لإجراء طلبات البيانات المناسبة لواجهة برمجة التطبيقات في الخلفية لتحديد عنوان URL الفعلي للمادة وضبطه على MediaInfo.contentUrl.. سيتولّى المستلِم أيضًا مهامًا مثل الحصول على ترخيص إدارة الحقوق الرقمية أو إدراج معلومات عن الفواصل الإعلانية.

سنوسّع نطاق جهاز الاستقبال لإجراء إجراء مماثل في القسم التالي. في الوقت الحالي، انقر على رمز البث واختَر جهازك لفتح جهاز الاستقبال.

صورة لعلامة التبويب &quot;عناصر التحكّم في Cast Connect وLogger &quot; ضمن أداة &quot;التحكّم والتوجيه&quot; (CaC) تشير إلى أنّها مرتبطة بتطبيق مستقبل

انتقل إلى علامة التبويب "Load Media" (تحميل الوسائط) وانقر على الزر "Load by Content" (تحميل حسب المحتوى). من المفترض أن يبدأ جهاز الاستقبال في تشغيل عيّنة المحتوى.

صورة لعلامة التبويب &quot;تحميل الوسائط&quot; في أداة &quot;القيادة والتحكّم&quot;

وبالتالي، تعالج حزمة تطوير البرامج (SDK) لجهاز الاستقبال ما يلي:

  • جارٍ إعداد جلسة البث
  • معالجة طلبات "LOAD" الواردة من المُرسِلين الذين لديهم مواد عرض قابلة للتشغيل
  • يجب توفير واجهة مستخدم أساسية لتشغيل المحتوى تكون جاهزة للعرض على الشاشة الكبيرة.

يمكنك استكشاف "أداة ربط المحتوى" ورمزها قبل الانتقال إلى القسم التالي، حيث سنوسّع نطاق المستلِم للتواصل مع نموذج بسيط لواجهة برمجة التطبيقات من أجل تلبية طلبات LOAD الواردة من المُرسِلين.

9. الدمج مع واجهة برمجة تطبيقات خارجية

بما يتوافق مع طريقة تفاعل معظم المطوّرين مع أجهزة استقبال البث في التطبيقات في الحياة الواقعية، سنعدّل جهاز الاستقبال لمعالجة طلبات LOAD التي تشير إلى محتوى الوسائط المقصود باستخدام مفتاح واجهة برمجة التطبيقات بدلاً من إرسال عنوان URL لمادة عرض قابلة للتشغيل.

وعادةً ما تفعل التطبيقات ذلك للأسباب التالية:

  • قد لا يعرف المُرسِل عنوان URL للمحتوى.
  • صُمِّم تطبيق البث لمعالجة المصادقة وغيرها من منطق الأنشطة التجارية أو طلبات البيانات من واجهة برمجة التطبيقات على المستلِم مباشرةً.

يتم تنفيذ هذه الوظيفة بشكل أساسي من خلال طريقة setMessageInterceptor() PlayerManager. ويتيح لك ذلك اعتراض الرسائل الواردة حسب نوعها وتعديلها قبل وصولها إلى معالج الرسائل الداخلي في حزمة تطوير البرامج (SDK). في هذا القسم، نتعامل مع LOAD طلبًا سننفّذ ما يلي بشأنها:

  • اقرأ طلب LOAD الواردة وcontentId المخصّصة.
  • يمكنك إجراء طلب GET إلى واجهة برمجة التطبيقات للبحث عن مادة العرض القابلة للبث حسب contentId.
  • عدِّل طلب LOAD باستخدام عنوان URL للبث.
  • عدِّل العنصر MediaInformation لضبط مَعلمات نوع مصدر البيانات.
  • يمكنك تمرير الطلب إلى حزمة تطوير البرامج (SDK) للتشغيل، أو رفض الأمر إذا لم نتمكّن من البحث عن الوسائط المطلوبة.

يعرض نموذج واجهة برمجة التطبيقات المقدَّم عناصر الربط لحزمة SDK لتخصيص مهام المُستلِم الشائعة، مع الاستمرار في الاعتماد على تجربة جاهزة في معظم الأحيان.

Sample 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 في واجهة برمجة التطبيقات

بعد أن أعددنا معرّف تحميل البيانات، سنحدّد نوع المحتوى للمستلِم. ستوفّر هذه المعلومات للمستلِم عنوان 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';
            ...
          }
        });
      });
    });

بعد إكمال هذه الخطوة، يمكنك المتابعة إلى Testing It Out لمحاولة تحميل محتوى DASH. إذا أردت اختبار التحميل باستخدام محتوى HLS بدلاً من ذلك، اطّلِع على الخطوة التالية.

استخدام محتوى HLS في Sample API

يتضمّن نموذج واجهة برمجة التطبيقات محتوى HLS بالإضافة إلى DASH. بالإضافة إلى ضبط contentType كما فعلنا في الخطوة السابقة، سيحتاج طلب التحميل إلى بعض السمات الإضافية لاستخدام عناوين URL لبروتوكول HLS في نموذج واجهة برمجة التطبيقات. عند ضبط جهاز الاستقبال لتشغيل أحداث HLS، يكون نوع الحاوية التلقائي المتوقّع هو بث النقل (TS). نتيجةً لذلك، سيحاول جهاز الاستقبال فتح عيّنة أحداث البث بتنسيق MP4 بتنسيق TS إذا تم تعديل السمة contentUrl فقط. في طلب التحميل، يجب تعديل عنصر MediaInformation باستخدام سمات إضافية حتى يعرف المستلِم أنّ نوع المحتوى هو MP4 وليس TS. أضِف الرمز التالي إلى ملف js/reviewr.js في عنصر اعتراض التحميل لتعديل السمتَين contentUrl وcontentType. أضِف أيضًا السمتَين HlsSegmentFormat وHlsVideoSegmentFormat.

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.hls;
            request.media.contentType = 'application/x-mpegurl';
            request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
            request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
            ...
          }
        });
      });
    });

اختبار التطبيق

مرة أخرى، افتح أداة الأوامر والتحكّم (CaC) واضبط رقم تعريف التطبيق على رقم تعريف التطبيق الخاص بالمستلِم. اختَر جهازك باستخدام زر البث.

انتقِل إلى علامة التبويب "تحميل الوسائط". هذه المرة احذف النص الموجود في الحقل "عنوان URL للمحتوى" بجانب الزر "تحميل حسب المحتوى"، ما سيؤدي إلى إجبار تطبيقنا على إرسال طلب LOAD يحتوي على مرجع contentId فقط إلى وسائطنا.

صورة لعلامة التبويب &quot;تحميل الوسائط&quot; في أداة &quot;القيادة والتحكّم&quot;

على افتراض أنّ التعديلات التي أجريتها على المستلِم سارت على ما يرام، يجب أن يتولى عنصر الاعتراض تشكيل الكائن 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. في هذا الدرس التطبيقي حول الترميز، نستخدم العنصر <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، سيتم عرض تنسيق التحكّم التلقائي على النحو التالي:

صورة لعناصر التحكّم في مشغّل الوسائط: شريط التقدّم وزر &quot;تشغيل&quot; وزرَّا &quot;التخطي إلى الأمام&quot; و&quot;التخطي إلى الخلف&quot; مفعَّلان

عندما تكون قيمة supportedMediaCommands مساوية لـ ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT، سيتم عرض تنسيق التحكّم التلقائي على النحو التالي:

صورة لعناصر التحكّم في مشغّل الوسائط: شريط التقدّم وزر &quot;تشغيل&quot; وزرَا &quot;التقديم السريع&quot; و&quot;الترجيع السريع&quot; وزرَا &quot;إضافة إلى &quot;قائمة المحتوى التالي&quot; و&quot;إضافة إلى &quot;قائمة المحتوى السابق&quot; مفعَّلان

عندما تساوي قيمةsupportedMediaCommands PAUSE | QUEUE_PREV | QUEUE_NEXT، سيظهر تنسيق عنصر التحكّم التلقائي على النحو التالي:

صورة عناصر التحكّم في مشغّل الوسائط: تم تفعيل شريط التقدّم والزر &quot;تشغيل&quot; وزرَي &quot;قائمة المحتوى التالي السابق&quot; و&quot;قائمة المحتوى التالي&quot;

عندما تكون مسارات النص متاحة، سيظهر زر الترجمة والشرح دائمًا في SLOT_1.

صورة عناصر التحكّم في مشغّل الوسائط: شريط التقدّم، وزر &quot;تشغيل&quot;، وأزرار &quot;التخطّي إلى الأمام&quot; و&quot;التخطّي إلى الخلف&quot;، وأزرار &quot;قائمة المحتوى التالي السابقة&quot; و&quot;قائمة المحتوى التالي&quot; التي تم تفعيلها، وأزرار &quot;الترجمة والشرح&quot;

لتغيير قيمة 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 لاختيار أفضل نسبة عرض إلى ارتفاع لمواد عرض الصور. تتيح حزمة تطوير البرامج (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 وفي أداة معالجة الحدث 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) لأجهزة استقبال البث عبر الأجهزة الجوّالة خيارًا آخر للمطوّرين لتصحيح أخطاء تطبيقات أجهزة الاستقبال بسهولة باستخدام CastDebugLogger API وأداة التحكّم والمراقبة (CaC) المصاحبة لتسجيل السجلات.

الإعداد

لدمج واجهة برمجة التطبيقات، أضِف نص المصدر 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 على جهاز الاستقبال.

صورة لفيديو يتم تشغيله مع ظهور رسالة &quot;وضع تصحيح الأخطاء&quot; على خلفية حمراء في أعلى يمين الإطار

تسجيل أحداث المشغّل

باستخدام 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,
};

تراكب تصحيح الأخطاء

يقدّم "مُسجِّل تصحيح الأخطاء في البث" تداخل تصحيح الأخطاء على جهاز الاستقبال لعرض رسائل السجلّ المخصّصة على جهاز البث. استخدِم 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 Receiver.