إنشاء مستقبِل مخصّص للويب

1- نظرة عامة

شعار Google Cast

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

ما المقصود بـ Google Cast؟

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

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

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

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

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

ما ستتعرَّف عليه

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

المتطلبات

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

التجربة

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

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

قراءة فقط قراءة النموذج وإكمال التدريبات

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

نوفمبر متوسط خبير

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

نوفمبر متوسط محترف

2. الحصول على نموذج الشفرة

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

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

3- نشر جهاز الاستقبال محليًا

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

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

تشغيل الخادم

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

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

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

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

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

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

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

حدد "جهاز الاستقبال المخصص"، وهذا ما يتم إنشاؤه.

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

أدخِل تفاصيل المستلِم الجديد، وتأكَّد من استخدام عنوان URL الذي وصلت إليه في النهاية.

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

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

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

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

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

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

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

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

شعار Google Chrome

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

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

صورة لعلامة التبويب "Cast Connect & Logger Controls" (أدوات التحكم في الاتصال وتسجيل السجلات) في أداة Command and Control (CAC)

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

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

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

صورة لعلامة التبويب "تحميل الوسائط" في أداة Command and Control (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 واجهة المستخدم لتطبيق المُستلِم. إنه خالٍ الآن، وسنضيف إليه عبر مختبر الرموز.

pickupr.js

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

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> 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 Controls&quot; (أدوات التحكم في الاتصال وتسجيل السجلات) في أداة Command and Control (CAC)

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

بث الوسائط

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

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

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

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

سنعمل على توسيع نطاق المستلِم لتنفيذ إجراء كهذا في القسم التالي. في الوقت الحالي، انقر على رمز الإرسال وحدد جهازك لفتح جهاز الاستقبال.

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

انتقل إلى علامة التبويب "تحميل الوسائط" وانقر على الزر "تحميل المحتوى". من المفترض أن يبدأ المستلِم تشغيل نموذج المحتوى.

صورة لعلامة التبويب &quot;تحميل الوسائط&quot; في أداة Command and Control (CAC)

ولذلك، فإن مجموعة أدوات "المستلم" في حزمة SDK غير مباشرة:

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

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

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

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

عادةً ما تُجري التطبيقات هذا للأسباب التالية:

  • قد لا يعرف المُرسِل عنوان URL للمحتوى.
  • تم تصميم تطبيق Cast للتعامل مع المصادقة أو إجراءات الأنشطة التجارية الأخرى أو طلبات البيانات من واجهة برمجة التطبيقات مباشرةً على جهاز الاستقبال.

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

  • اقرأ طلب LOAD الوارد وcontentId المخصص له.
  • يمكنك استدعاء GET إلى واجهة برمجة التطبيقات للبحث عن مادة العرض القابلة للبث حسب contentId.
  • عدّل طلب LOAD باستخدام عنوان URL للبث.
  • عدِّل الكائن MediaInformation لضبط مَعلمات نوع البث.
  • مرّر الطلب إلى حزمة 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.

اعتراض طلب 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 في أداة اعتراض 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';
            ...
          }
        });
      });
    });

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

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

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

على افتراض أنّ كل شيء سار على ما يرام مع التعديلات على جهاز الاستقبال، يجب أن يعتني برنامج الاعتراض بتشكيل الكائن MediaInfo في شيء يمكن أن تُشغِّله حزمة تطوير البرامج (SDK) على الشاشة.

انقر على الزر "تحميل بحسب المحتوى" لمعرفة ما إذا كانت الوسائط تعمل بشكل صحيح أم لا. لا تتردد في تغيير معرّف المحتوى إلى معرّف آخر في ملف 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;

عندما تساوي قيمة أمر MediaMediaCommands 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 تتيح للمستخدمين استكشاف محتوى إضافي على الأجهزة التي تعمل باللمس. لتنفيذ هذا الإجراء، عليك استخدام PlayerDataBinder لضبط واجهة مستخدم BrowseContent. يمكنك بعد ذلك تعبئته بـ BrowseItems استنادًا إلى المحتوى الذي تريد عرضه.

تصفُّح المحتوى

في ما يلي مثال على واجهة مستخدم BrowseContent وخصائصها:

صورة لواجهة مستخدم تصفُّح المحتوى تعرض صورًا مصغَّرة للفيديو وجزءًا من جزء ثالث

  1. BrowseContent.title
  2. BrowseContent.items

نسبة العرض إلى الارتفاع

استخدِم targetAspectRatio property لاختيار أفضل نسبة عرض إلى ارتفاع لمواد عرض الصور. تتوفّر ثلاث نسب عرض إلى ارتفاع من خلال حزمة تطوير البرامج (SDK) الخاصة باستلام أجهزة CAF وهي: SQUARE_1_TO_1 وPORTRAIT_2_TO_3 وLANDSCAPE_16_TO_9.

تصفُّح العنصر

يمكنك استخدام BrowseItem لعرض العنوان والعنوان الفرعي والمدة والصورة لكل سلعة:

صورة لواجهة مستخدم تصفُّح المحتوى تعرض صورًا مصغَّرة للفيديو وجزءًا من جزء ثالث

  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 لجهاز استقبال Cast خيارًا آخر لمطوّري البرامج لتصحيح أخطاء تطبيقات جهاز الاستقبال بسهولة باستخدام واجهة برمجة تطبيقات CastDebugLogger وأداة Command و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، يمكنك بسهولة تسجيل أحداث المشغّل التي تم تنشيطها بواسطة حزمة تطوير البرامج لجهاز استقبال 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.

لمزيد من التفاصيل، راجع دليل مطوري برامج مستقبل الويب.