إضافة الميزات الأساسية إلى مستقبِل الويب المخصّص

تحتوي هذه الصفحة على مقتطفات رموز وأوصاف للميزات المتاحة لتطبيق "استقبال الويب المخصّص".

  1. يمثّل عنصر cast-media-player واجهة المستخدم الخاصة بالمشغّل المضمَّن والمتوفّر في أداة استقبال الويب.
  2. نمط مخصص يشبه CSS للعنصر cast-media-player لتصميم عناصر متنوعة لواجهة المستخدم، مثل background-image وsplash-image وfont-family.
  3. عنصر نص برمجي لتحميل إطار عمل جهاز استقبال الويب:
  4. رمز JavaScript لاعتراض الرسائل ومعالجة الأحداث
  5. قائمة انتظار التشغيل التلقائي.
  6. خيارات لإعداد التشغيل
  7. خيارات ضبط سياق "جهاز استقبال الويب"
  8. خيارات ضبط الأوامر المتوافقة مع تطبيق "جهاز استقبال الويب"
  9. إجراء طلب من JavaScript لتشغيل تطبيق "جهاز استقبال الويب"

إعدادات التطبيق وخياراته

إعداد التطبيق

CastReceiverContext هي الفئة الخارجية التي تظهر للمطوّر، وتدير تحميل المكتبات الأساسية وتعالج إعداد حزمة تطوير البرامج (SDK) لأجهزة استقبال الويب. توفّر حزمة SDK واجهات برمجة تطبيقات تسمح لمطوّري التطبيقات بإعداد حزمة SDK من خلال CastReceiverOptions. يتم تقييم عمليات الضبط هذه مرة واحدة لكل تشغيل للتطبيق ويتم تمريرها إلى حزمة تطوير البرامج (SDK) عند ضبط المَعلمة الاختيارية في الطلب إلى start.

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

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

إعداد المشغّل

عند تحميل المحتوى، توفّر حزمة تطوير البرامج (SDK) لمستلِم الويب طريقة لضبط متغيّرات التشغيل، مثل معلومات إدارة الحقوق الرقمية، وإعادة محاولة الضبط، ومعالجات الطلبات باستخدام cast.framework.PlaybackConfig. تتم معالجة هذه المعلومات من خلال PlayerManager ويتم تقييمها في وقت إنشاء اللاعبين. يتم إنشاء المشغلات في كل مرة يتم فيها تمرير تحميل جديد إلى حزمة تطوير البرامج (SDK) لاستقبال الويب. يتم تقييم التعديلات على PlaybackConfig بعد إنشاء المشغّل في عملية تحميل المحتوى التالية. توفِّر حزمة تطوير البرامج (SDK) الطرق التالية لتعديل PlaybackConfig.

  • CastReceiverOptions.playbackConfig لإلغاء خيارات الإعداد التلقائية عند إعداد CastReceiverContext.
  • PlayerManager.getPlaybackConfig() للحصول على الإعدادات الحالية.
  • PlayerManager.setPlaybackConfig() لإلغاء الإعدادات الحالية. يتم تطبيق هذا الإعداد على جميع عمليات التحميل اللاحقة أو إلى أن يتم إلغاء التحميل مرة أخرى.
  • PlayerManager.setMediaPlaybackInfoHandler() لتطبيق عمليات ضبط إضافية على عنصر الوسائط الذي يتم تحميله أعلى الإعدادات الحالية فقط. ويتم استدعاء المعالج قبل إنشاء اللاعب مباشرةً. إنّ التغييرات التي يتم إجراؤها هنا ليست دائمة ولا يتم تضمينها في طلبات البحث التي يتم إجراؤها على getPlaybackConfig(). عند تحميل عنصر الوسائط التالي، يتم استدعاء هذا المعالج مرة أخرى.

يوضح المثال أدناه كيفية ضبط PlaybackConfig عند إعداد CastReceiverContext. تلغي الإعدادات الطلبات الصادرة للحصول على البيانات. ويحدّد المعالِج أنّه يجب إجراء طلبات التحكّم في الوصول إلى بروتوكول CORS باستخدام بيانات اعتماد مثل ملفات تعريف الارتباط أو عناوين التفويض.

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

يعرض المثال أدناه كيفية إلغاء PlaybackConfig باستخدام دالة getter ودالة setter المقدَّمة في PlayerManager. يضبط الإعداد المشغّل لاستئناف تشغيل المحتوى بعد تحميل مقطع واحد.

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

يعرض المثال أدناه كيفية إلغاء PlaybackConfig لطلب تحميل معيّن باستخدام معالج معلومات تشغيل الوسائط. يستدعي المعالِج تطبيقًا تم تنفيذه على الطريقة getLicenseUrlForMedia للحصول على licenseUrl من contentId للعنصر الحالي.

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

أداة معالجة الحدث

تسمح "حزمة تطوير البرامج (SDK) لمستلِم الويب" لتطبيق Web المشغّل على الويب بمعالجة أحداث اللاعبين. تأخذ أداة معالجة الحدث معلَمة cast.framework.events.EventType (أو مصفوفة من هذه المَعلمات) تحدِّد الأحداث التي يجب أن تؤدي إلى تشغيل المستمع. ويمكن العثور في cast.framework.events.category على صفائف cast.framework.events.EventType مُعدّة مسبقًا ومفيدة لتصحيح الأخطاء. تقدّم مَعلمة الحدث معلومات إضافية عن الحدث.

على سبيل المثال، إذا كنت تريد معرفة وقت نشر تغيير على mediaStatus، يمكنك استخدام المنطق التالي للتعامل مع الحدث:

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

اعتراض الرسائل

تسمح "حزمة تطوير البرامج (SDK) لمستلِم الويب" لتطبيق "جهاز استقبال الويب" باعتراض الرسائل وتنفيذ رموز مخصّصة عليها. يأخذ اعتراض الرسائل معلَمة cast.framework.messages.MessageType التي تحدد نوع الرسالة التي يجب اعتراضها.

يجب أن يعرض المعترض الطلب المعدَّل أو الوعد الذي يتم حله مع قيمة الطلب المعدَّلة. سيؤدي عرض علامة null إلى منع استدعاء المعالج التلقائي للرسائل. راجِع تحميل الوسائط للاطّلاع على مزيد من التفاصيل.

على سبيل المثال، إذا كنت تريد تغيير بيانات طلب التحميل، يمكنك استخدام المنطق التالي لاعتراضها وتعديلها:

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

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

خطأ أثناء المعالجة

عند حدوث أخطاء في أداة اعتراض الرسائل، من المفترض أن يعرض تطبيق جهاز استقبال الويب cast.framework.messages.ErrorType وcast.framework.messages.ErrorReason بشكل مناسب.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

اعتراض الرسالة مقابل أداة معالجة الحدث

في ما يلي بعض الاختلافات الرئيسية بين اعتراض الرسالة وأداة معالجة الأحداث:

  • لا تسمح لك أداة معالجة الحدث بتعديل بيانات الطلب.
  • من الأفضل استخدام أداة معالجة الحدث لتشغيل الإحصاءات أو دالة مخصَّصة.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • تتيح لك ميزة اعتراض الرسائل الاستماع إلى رسالة واعتراضها وتعديل بيانات الطلب نفسها.
  • يمكن استخدام ميزة "اعتراض الرسائل" على أفضل نحو لمعالجة المنطق المخصّص في ما يتعلّق ببيانات الطلب.

جارٍ تحميل الوسائط

توفِّر MediaInformation العديد من السمات لتحميل الوسائط في رسالة cast.framework.messages.MessageType.LOAD، بما في ذلك entity وcontentUrl وcontentId.

  • entity هي السمة المقترَحة التي يمكنك استخدامها في عملية التنفيذ لكلّ من تطبيقات المرسِل والمستلِم. الموقع هو عنوان URL لرابط يؤدي إلى صفحة في التطبيق ويمكن أن يكون إما قائمة تشغيل أو محتوى وسائط. يجب على التطبيق تحليل عنوان URL هذا وملء حقل واحد على الأقل من الحقلين الآخرين.
  • يتوافق الرمز contentUrl مع عنوان URL القابل للتشغيل الذي سيستخدمه المشغّل لتحميل المحتوى. على سبيل المثال، يمكن أن يشير عنوان URL هذا إلى بيان DASH.
  • يمكن أن يكون contentId إما عنوان URL لمحتوى قابل للتشغيل (يشبه عنوان URL للسمة contentUrl) أو معرّفًا فريدًا للمحتوى أو قائمة التشغيل التي يتم تحميلها. في حال استخدام هذه السمة كمعرّف، يجب أن يملأ تطبيقك عنوان URL قابلاً للتشغيل في contentUrl.

نقترح استخدام entity لتخزين المعرّف الحقيقي أو المعلَمات الأساسية، واستخدام contentUrl لعنوان URL للوسائط. يوضّح المقتطف التالي مثالاً على ذلك في المقتطف التالي، حيث يتم تضمين entity في طلب LOAD ويتم استرداد contentUrl القابل للتشغيل:

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

إمكانات الجهاز

توفّر الطريقة getDeviceCapabilities معلومات عن الجهاز على جهاز البث المتصل وجهاز الفيديو أو الصوت المتصل به. تقدّم طريقة getDeviceCapabilities معلومات الدعم لخدمة "مساعد Google" والبلوتوث وأجهزة العرض والصوت المتصلة.

تعرض هذه الطريقة كائنًا يمكنك الاستعلام عنه عن طريق تمرير أحد التعدادات المحددة للحصول على قدرة الجهاز لهذا التعداد. يتم تحديد التعداد في cast.framework.system.DeviceCapabilities.

يتحقّق هذا المثال مما إذا كان جهاز استقبال الويب قادرًا على تشغيل نطاق عالي الديناميكية (HDR) وDolbyVision (DV) باستخدام مفتاحَي IS_HDR_SUPPORTED وIS_DV_SUPPORTED على التوالي.

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

التعامل مع تفاعل المستخدم

يمكن للمستخدم التفاعل مع تطبيق "جهاز استقبال الويب" من خلال تطبيقات المرسِل (الويب وAndroid وiOS) والأوامر الصوتية على الأجهزة المزوّدة بخدمة "مساعد Google" وعناصر التحكم باللمس على الشاشات الذكية وعناصر التحكّم عن بُعد على أجهزة Android TV. توفّر حزمة تطوير البرامج (SDK) الخاصة بالبثّ واجهات برمجة تطبيقات متنوعة للسماح لتطبيق جهاز استقبال الويب بمعالجة هذه التفاعلات وتحديث واجهة مستخدم التطبيق من خلال حالات إجراءات المستخدم وإرسال التغييرات اختياريًا لتحديث أي من خدمات الخلفية.

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

يتم تحديد حالات عناصر التحكّم في واجهة المستخدم من خلال MediaStatus.supportedMediaCommands وحدات التحكّم الموسّعة وأجهزة الاستقبال والتحكّم عن بُعد التي يتم تشغيلها على الأجهزة التي تعمل باللمس وتطبيقات أجهزة الاستقبال على أجهزة Android TV للمرسلين على نظامَي التشغيل iOS وAndroid. عند تفعيل Command محدّد على مستوى البت في الموقع، يتم تفعيل الأزرار المرتبطة بهذا الإجراء. إذا لم يتم تعيين القيمة، فسيتم إيقاف الزر. يمكن تغيير هذه القيم على "جهاز استقبال الويب" من خلال:

  1. يمكن أن يؤدي استخدام PlayerManager.setSupportedMediaCommands لتعيين Commands
  2. إضافة طلب جديد باستخدام addSupportedMediaCommands
  3. إزالة طلب حالي باستخدام removeSupportedMediaCommands
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

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

لمزيد من المعلومات حول أوامر الوسائط المتوافقة والأجهزة التي تعمل باللمس، يُرجى الاطّلاع على دليل Accessing UI controls.

إدارة حالات إجراءات المستخدم

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

  • اضبط MediaInformation userActionStates مع الإعدادات المفضّلة للمستخدم عند تحميل عنصر وسائط.
  • اعتراض رسائل "USER_ACTION" وتحديد الإجراء المطلوب
  • يُرجى تعديل MediaInformation UserActionState لتعديل واجهة المستخدم.

يعترض المقتطف التالي طلب LOAD ويملأ MediaInformation لـ LoadRequestData. في هذه الحالة، يحب المستخدم المحتوى الذي يتم تحميله.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

يعترض المقتطف التالي رسالة USER_ACTION ويعالج استدعاء الخلفية بالتغيير المطلوب. يُجري الجهاز بعد ذلك مكالمة لتعديل UserActionState على جهاز الاستقبال.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

يحاكي المقتطف التالي طلب خدمة خلفية. تتحقّق الدالة من UserActionRequestData لمعرفة نوع التغيير الذي طلبه المستخدم، ولا تجري اتصالاً بالشبكة إلا إذا كانت الخلفية تتيح الإجراء.

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

يحصل المقتطف التالي على UserActionRequestData ويضيف إما UserActionState أو يُزيلها من MediaInformation. يؤدي تعديل UserActionState في MediaInformation إلى تغيير حالة الزر المرتبط بالإجراء المطلوب. ويظهر هذا التغيير في واجهة المستخدم لعناصر التحكّم في الشاشة الذكية، وتطبيق التحكّم عن بُعد، وواجهة مستخدم Android TV. ويتم أيضًا بثّه من خلال رسائل MediaStatus الصادرة لتعديل واجهة المستخدم الخاصة بوحدة التحكّم الموسّعة الخاصة بمرسلي iOS وAndroid.

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

الطلبات الصوتية

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

Command الوصف
Play تشغيل أو استئناف التشغيل من حالة الإيقاف المؤقت
إيقاف مؤقت إيقاف المحتوى الذي يتم تشغيله حاليًا مؤقتًا
السابق يمكنك التخطّي إلى عنصر الوسائط السابق في قائمة انتظار الوسائط.
التالي يمكنك التخطي إلى عنصر الوسائط التالي في قائمة انتظار الوسائط.
إيقاف إيقاف الوسائط التي يتم تشغيلها حاليًا
عدم التكرار يمكنك إيقاف تكرار عناصر الوسائط في قائمة المحتوى التالي بعد انتهاء تشغيل العنصر الأخير في قائمة المحتوى التالي.
تكرار الأغنية المنفردة تكرار الوسائط التي يتم تشغيلها حاليًا إلى أجل غير مسمى
تكرار الكل تكرار جميع العناصر في قائمة الانتظار بعد تشغيل العنصر الأخير في قائمة الانتظار.
تكرار الكل والترتيب العشوائي وبعد انتهاء تشغيل آخر عنصر في قائمة الانتظار، يمكنك ترتيب قائمة الانتظار عشوائيًا وتكرار جميع العناصر فيها.
ترتيب عشوائي ترتيب عناصر الوسائط عشوائيًا في قائمة المحتوى التالي.
ميزة "الترجمة والشرح" مفعَّلة أو غير مفعّلة تفعيل / إيقاف الترجمة النصية للوسائط. تفعيل / إيقاف متوفر أيضًا حسب اللغة.
للانتقال إلى الوقت المطلق للانتقال إلى الوقت المطلق المحدد.
البحث عن الوقت بالنسبة إلى الوقت الانتقال للأمام أو للخلف حسب الفترة الزمنية المحددة بالنسبة إلى وقت التشغيل الحالي.
اللعب مرة أخرى أعِد تشغيل الوسائط قيد التشغيل حاليًا أو شغِّل آخر عنصر تم تشغيله إذا لم يكن هناك أي وسائط قيد التشغيل حاليًا.
ضبط سرعة التشغيل تنويع معدل تشغيل الوسائط ستتم معالجة هذا الأمر بشكل تلقائي. يمكنك استخدام اعتراض الرسائل في SET_PLAYBACK_RATE لإلغاء طلبات السعر الواردة.

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

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

على سبيل المثال، في حال السماح بـ PAUSE من تطبيقات المُرسِلين والأجهزة التي تعمل باللمس، يجب أيضًا ضبط جهاز الاستقبال ليعكس هذه الإعدادات. عند تهيئة هذه الميزة، سيتم تجاهل أي أوامر صوتية واردة إذا لم يتم تضمينها في قائمة الأوامر المتوافقة.

في المثال أدناه، نقدّم السمة CastReceiverOptions عند بدء CastReceiverContext. لقد أضفنا إمكانية استخدام الأمر PAUSE وفرضنا على المشغّل تنفيذ هذا الأمر فقط. والآن، إذا طلب طلب صوتي عملية أخرى مثل SEEK، سيتم رفضها. سيتم إعلام المستخدم بأن الأمر غير معتمد بعد.

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

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

ويمكنك تطبيق منطق منفصل لكل أمر تريد تقييده. عليك إزالة العلامة enforceSupportedCommands. ولكل أمر تريد تقييده، يمكنك اعتراض الرسالة الواردة. نعترض هنا الطلب الذي تقدّمه حزمة تطوير البرامج (SDK) لكي لا تؤدي أوامر SEEK الصادرة للأجهزة المزوّدة بخدمة "مساعد Google" إلى تنفيذ طلب في تطبيق "جهاز استقبال الويب".

بالنسبة إلى أوامر الوسائط التي لا يتوافق معها تطبيقك، يمكنك عرض سبب خطأ مناسب، مثل NOT_SUPPORTED.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

تشغيل المحتوى الصوتي في الخلفية

إذا خلفت منصة Google Cast صوت تطبيقك بسبب نشاط "مساعد Google"، مثل الاستماع إلى كلام المستخدم أو التحدث إليه، يتم إرسال رسالة FocusState الخاصة بـ NOT_IN_FOCUS إلى تطبيق مستقبِل الويب عند بدء النشاط. يتم إرسال رسالة أخرى مع "IN_FOCUS" عند انتهاء النشاط. بناءً على التطبيق والوسائط التي يتم تشغيلها، قد تحتاج إلى إيقاف الوسائط مؤقتًا عندما تكون قيمة FocusState هي NOT_IN_FOCUS من خلال اعتراض نوع الرسالة FOCUS_STATE.

على سبيل المثال، من المفيد إيقاف تشغيل الكتب المسموعة مؤقتًا إذا كان "مساعد Google" يستجيب لطلب بحث المستخدم.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

لغة الترجمة المحددة بالصوت

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

على سبيل المثال، يتم ضبط isSuggestedLanguage على true للأمر "OK Google، أريد تفعيل الشرح" لأنّ اللغة التي تم نطق الأمر بها قد تم استنتاجها. إذا كانت اللغة مطلوبة صراحةً، مثل "OK Google، فعِّل الشرح باللغة الإنجليزية"، سيتم ضبط isSuggestedLanguage على false.

البيانات الوصفية والبث الصوتي

بينما يتعامل "مستلِم الويب" مع الأوامر الصوتية بشكل تلقائي، عليك التأكّد من أنّ البيانات الوصفية للمحتوى كاملة ودقيقة. ويضمن ذلك معالجة "مساعد Google" للأوامر الصوتية بشكل صحيح وظهور البيانات الوصفية بشكل صحيح على مختلف أنواع الواجهات الجديدة، مثل تطبيق Google Home والشاشات الذكية، مثل Google Home Hub.

نقل البث

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

في ما يلي خطوات نقل الحدث:

  1. على الجهاز المصدر:
    1. يتوقف تشغيل الوسائط.
    2. يتلقى تطبيق "جهاز استقبال الويب" أمرًا لحفظ حالة الوسائط الحالية.
    3. يتم إيقاف تطبيق "جهاز استقبال الويب".
  2. على الجهاز الوجهة:
    1. يتم تحميل تطبيق "جهاز استقبال الويب".
    2. يتلقى تطبيق "جهاز استقبال الويب" أمرًا لاستعادة حالة الوسائط المحفوظة.
    3. يتم استئناف تشغيل الوسائط.

تشمل عناصر حالة الوسائط ما يلي:

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

جارٍ تفعيل عملية نقل البث

لتنفيذ نقل البث لجهاز استقبال الويب:

  1. عدِّل supportedMediaCommands باستخدام الأمر STREAM_TRANSFER:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. يمكنك اختياريًا إلغاء أدوات اعتراض الرسائل SESSION_STATE وRESUME_SESSION على النحو الموضَّح في حفظ حالة الجلسة. لا يمكنك إلغاء هذه إلا إذا كانت البيانات المخصصة بحاجة إلى تخزينها كجزء من لقطة الجلسة. بخلاف ذلك، سيوفّر التنفيذ التلقائي للحفاظ على حالات الجلسة إمكانية نقل البث.

الحفاظ على حالة الجلسة

توفّر حزمة تطوير البرامج (SDK) الخاصة بجهاز استقبال الويب تنفيذًا تلقائيًا لتطبيقات جهاز استقبال الويب للاحتفاظ بحالات الجلسة من خلال أخذ لقطة من حالة الوسائط الحالية وتحويل الحالة إلى طلب تحميل واستئناف الجلسة بطلب التحميل.

يمكن إلغاء طلب التحميل الذي ينشئه "مستلِم الويب" في اعتراض الرسائل باستخدام SESSION_STATE إذا لزم الأمر. إذا كنت تريد إضافة بيانات مخصّصة في طلب التحميل، نقترح وضعها في loadRequestData.customData.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

يمكن استرداد البيانات المُخصّصة من loadRequestData.customData في اعتراض الرسائل RESUME_SESSION.

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

التحميل المُسبق للمحتوى

يتيح جهاز استقبال الويب التحميل المُسبق لعناصر الوسائط بعد عنصر التشغيل الحالي في قائمة الانتظار.

في عملية التحميل المسبق، يتم تنزيل عدة مقاطع من العناصر القادمة مسبقًا. تتم المواصفات على قيمة preloadTime في الكائن QueueItem (القيمة التلقائية هي 20 ثانية إذا لم يتم توفيرها). ويتم التعبير عن الوقت بالثواني، بالنسبة إلى نهاية العنصر قيد التشغيل حاليًا . القيم الموجبة فقط هي الصالحة. على سبيل المثال، إذا كانت القيمة 10 ثوانٍ، سيتم تحميل هذا العنصر مسبقًا قبل 10 ثوانٍ من انتهاء العنصر السابق. إذا كان وقت التحميل المُسبق أعلى من الوقت المتبقّي للعنصر الحالي، سيتمّ تنفيذ عملية التحميل المُسبق في أقرب وقت ممكن. ولذلك، إذا تم تحديد قيمة كبيرة جدًا من التحميل المسبق في قائمة الانتظار، يمكن للمرء أن يحقق تأثير كل مرة نشغل فيها العنصر الحالي، فإننا نحمّل العنصر التالي مسبقًا. ومع ذلك، نترك الإعداد والاختيار للمطوِّر لأن هذه القيمة يمكن أن تؤثر في معدل نقل البيانات وأداء البث للعنصر قيد التشغيل الحالي.

يتوافق التحميل المُسبق مع البث المباشر وفق بروتوكول HTTP وDASH وبث المحتوى السلس تلقائيًا.

ولن يتم تحميل ملفات الفيديو والصوت العادية بتنسيق MP4، مثل ملفات MP3 مسبقًا، لأنّ أجهزة البث تدعم عنصر وسائط واحدًا فقط، ولا يمكن استخدامها للتحميل المُسبق أثناء تشغيل محتوى حالي.

الرسائل المخصّصة

تبادل الرسائل هو طريقة التفاعل الرئيسية لتطبيقات أجهزة استقبال الويب.

يصدر المرسِل الرسائل إلى جهاز استقبال الويب باستخدام واجهات برمجة تطبيقات المرسِل في النظام الأساسي الذي يعمل به المرسِل (Android أو iOS أو Web). يتضمّن كائن الحدث (وهو مظهر الرسالة) الذي يتم تمريره إلى أدوات معالجة الأحداث عنصر بيانات (event.data) حيث تأخذ البيانات سمات نوع الحدث المحدّد.

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

يتم تحديد جميع مساحات الاسم من خلال سلسلة، ويجب أن تبدأ بـ "urn:x-cast:" متبوعة بأي سلسلة. على سبيل المثال، "urn:x-cast:com.example.cast.mynamespace".

إليك مقتطف رمز لـ "مستلِم الويب" للاستماع إلى رسائل مخصّصة من المرسِلين المتصلين:

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

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

وبالمثل، يمكن لتطبيقات جهاز استقبال الويب إبقاء المُرسِلين على اطّلاع بحالة مستلِم الويب من خلال إرسال رسائل إلى المرسِلين المتصلين. يمكن لتطبيق "جهاز استقبال الويب" إرسال الرسائل باستخدام sendCustomMessage(namespace, senderId, message) على CastReceiverContext. يمكن لمستلم الويب إرسال رسائل إلى مُرسِل فردي، إما ردًا على رسالة مستلمة أو بسبب تغيير في حالة التطبيق. بالإضافة إلى المراسلة من نقطة إلى نقطة (بحد أقصى 64 كيلوبايت)، يمكن أيضًا لـ "مستلم الويب" بث الرسائل إلى جميع المرسلين المتصلين.

البثّ على الأجهزة الصوتية

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

Android TV

يناقش هذا القسم كيفية استخدام جهاز استقبال الويب من Google لمدخلاتك كتشغيل، ومدى التوافق مع Android TV.

دمج التطبيق مع وحدة التحكّم عن بُعد

يعمل جهاز استقبال الويب Google الذي يعمل على جهاز Android TV على ترجمة الإدخال من إدخالات التحكّم في الجهاز (أي وحدة التحكّم عن بُعد باليد) كرسائل تشغيل الوسائط المحدّدة لمساحة الاسم urn:x-cast:com.google.cast.media، على النحو الموضّح في رسائل تشغيل الوسائط. يجب أن يتيح التطبيق إتاحة هذه الرسائل للتحكم في تشغيل وسائط التطبيق للسماح بالتحكم الأساسي في التشغيل من إدخالات عناصر التحكم في Android TV.

إرشادات التوافق مع Android TV

في ما يلي بعض الاقتراحات والمخاطر الشائعة التي يجب تجنُّبها لضمان توافق التطبيق مع Android TV:

  • يُرجى الانتباه إلى أنّ سلسلة وكيل المستخدم تحتوي على كل من Android وCrKey، لأنّ بعض المواقع الإلكترونية قد تعيد التوجيه إلى موقع إلكتروني للأجهزة الجوّالة فقط لأنّها تكتشف تصنيف "Android". لا تفترض أنّ كلمة "Android" في سلسلة وكيل المستخدم تشير دائمًا إلى استخدام الأجهزة الجوّالة.
  • قد تستخدم حزمة وسائط Android ملف GZIP الشفاف لجلب البيانات. تأكَّد من أنّ بيانات الوسائط يمكنها الردّ على Accept-Encoding: gzip.
  • قد يتم بدء أحداث وسائط HTML5 على Android TV في توقيتات مختلفة عن توقيت Chromecast، وقد يكشف ذلك عن مشاكل تم إخفاؤها على Chromecast.
  • عند تعديل الوسائط، استخدِم الأحداث ذات الصلة بالوسائط التي تنشطها عناصر <audio>/<video>، مثل timeupdate وpause وwaiting. تجنَّب استخدام أحداث ذات صلة بالشبكات مثل progress وsuspend وstalled، لأنّها عادةً ما تعتمد على المنصة. يمكنك الاطّلاع على الأحداث الإعلامية للحصول على مزيد من المعلومات حول التعامل مع أحداث الوسائط في جهاز الاستقبال.
  • عند ضبط شهادات HTTPS للموقع الإلكتروني للمستلِم، تأكَّد من تضمين شهادات CA المتوسطة. راجِع صفحة اختبار طبقة المقابس الآمنة (SSL) في Qualsys للتحقق مما يلي: إذا كان مسار الشهادة الموثوق بها لموقعك الإلكتروني يتضمّن شهادة CA تحمل التصنيف "تنزيل إضافي"، قد لا يتم تحميلها على الأنظمة الأساسية المستندة إلى Android.
  • على الرغم من أنّ جهاز Chromecast يعرض صفحة جهاز الاستقبال على مستوى رسومات بدقة 720p، قد تعرض منصات البث الأخرى، بما في ذلك Android TV، الصفحة بدقة تصل إلى 1080p. تأكَّد من ضبط حجم صفحة المُستلِم على نحو مريح وبدرجات دقة مختلفة.