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

1. نظرة عامة

شعار Google Cast

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

ما المقصود بتكنولوجيا Google Cast؟

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

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

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

ما الذي سنبنيه؟

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

المُعطيات

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

المتطلبات

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

التجربة

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

كيف ستستخدم هذا البرنامج التعليمي؟

القراءة فقط اقرأها وأكمِل التمارين

كيف تقيّم تجربتك في إنشاء تطبيقات الويب؟

حديث متوسط بارع

كيف تقيّم تجربتك في مشاهدة التلفزيون؟

حديث متوسط بارع

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

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

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

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

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

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

تشغيل الخادم

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

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

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

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

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

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

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

اختَر "جهاز استقبال مخصّص" هذا ما نبنيه.

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

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

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

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

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

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

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

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

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

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

شعار Google Chrome

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

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

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

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

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

  1. الانتقال إلى "Load Media" (تحميل الوسائط) علامة التبويب في الجزء العلوي.

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

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

6- تجهيز مشروع البدء

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

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

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

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

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

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

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

يتكون التطبيق من طريقة عرض رئيسية واحدة تم تحديدها في 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>

أضِف الرمز التالي إلى <body> index.html قبل <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. بث المحتوى "أساسي" محتوى الفيديو

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

وجِّه متصفّح الويب إلى أداة الأوامر والتحكّم (CaC).

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

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

بث الوسائط

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

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

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

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

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

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

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

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

لذا، تعالج "حزمة تطوير البرامج (SDK) للمُستلِم" الميزات التالية:

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

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

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

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

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

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

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

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

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

نموذج لواجهة برمجة تطبيقات

انتقِل إلى 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.

اعتراض طلب التحميل

في هذه الخطوة، سننشئ أداة اعتراض التحميل باستخدام دالة ترسل طلب 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/reviewr.js في عنصر الاعتراض LOAD Promise():

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            ...
          }
        });
      });
    });

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

استخدام نموذج محتوى HLS في واجهة برمجة التطبيقات

يتضمن نموذج واجهة برمجة التطبيقات محتوى HLS بالإضافة إلى DASH. بالإضافة إلى ضبط contentType كما فعلنا في الخطوة السابقة، سيحتاج طلب التحميل إلى بعض السمات الإضافية لكي يستخدم نموذج عناوين URL لبروتوكول HLS في واجهة برمجة التطبيقات. عند ضبط الجهاز المُستلِم على تشغيل مجموعات بث HLS، يكون نوع الحاوية التلقائي المتوقَّع هو بث النقل (TS). نتيجةً لذلك، سيحاول المستلِم فتح نموذج مجموعات بث MP4 بتنسيق TS في حال تعديل السمة contentUrl فقط. في طلب التحميل، يجب تعديل الكائن MediaInformation باستخدام خصائص إضافية حتى يعرف المُستلِم أنّ المحتوى من النوع MP4 وليس من النوع TS. أضِف الرمز التالي إلى ملف js/Receivedr.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) واضبط رقم تعريف التطبيق على رقم تعريف التطبيق الخاص بالمستلِم. حدد جهازك باستخدام زر البث.

الانتقال إلى "Load Media" (تحميل الوسائط) . هذه المرة احذف النص في "عنوان URL للمحتوى" الحقل بجانب عمود "التحميل حسب المحتوى" الذي سيؤدي إلى إجبار تطبيقنا على إرسال طلب LOAD يحتوي على مرجع contentId فقط إلى الوسائط الخاصة بنا.

صورة لبرنامج Load Media علامة التبويب في أداة الأوامر والتحكّم (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. في هذا الدرس التطبيقي حول الترميز، نستخدم المفتاح <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

تعديل أوامر الوسائط المتوافقة

يستند عنصر "عناصر التحكّم في واجهة المستخدم" إلى MediaStatus.supportedMediaCommands لتحديد ما إذا كان سيتم عرض ControlsButton أم لا.

عندما تساوي قيمة 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; تم تفعيل الأزرار

عندما تساوي قيمة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 أسفل عناصر التحكّم باللمس لضبط الخانة الأولى من عناصر التحكّم:

...

// 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 وفي أداة معالجة الأحداث 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. تصحيح أخطاء تطبيقات المُستلِم

توفّر حزمة تطوير البرامج لجهاز الاستقبال خيارًا آخر للمطوّرين يمكنهم بسهولة تصحيح أخطاء تطبيقات الاستقبال باستخدام 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، واستخدام مستويات مختلفة من المسجِّل لتسجيل بيانات الأحداث. تستخدم إعدادات 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 بإنشاء رسائل سجل تظهر على تراكب تصحيح أخطاء المُستلِم بألوان مختلفة. تتوفّر طرق السجلّ التالية، بالترتيب من الأولوية القصوى إلى الأدنى:

  • 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.

لمزيد من التفاصيل، يُرجى الاطّلاع على دليل المطوِّر مستلِم الويب.