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

وتتضمّن هذه الصفحة مقتطفات من الرموز وأوصاف الميزات المتاحة لتطبيق Custom WebRecipient.

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

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

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

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) استلام الويب" طريقة لضبط متغيّرات التشغيل، مثل معلومات DRM، وإعادة محاولة الإعدادات، ومعالجات الطلبات باستخدام 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) الخاصة باستقبال الويب تسمح لتطبيق WebRecipient بمعالجة أحداث المشغّل. تأخذ أداة معالجة الأحداث مَعلمة cast.framework.events.EventType (أو مصفوفة من هذه المَعلمات) تحدّد الأحداث التي يجب أن تؤدي إلى تشغيل المستمع. يمكن العثور على صفائف cast.framework.events.EventType التي تم ضبطها مسبقًا، والمفيدة لتصحيح الأخطاء، في cast.framework.events.category. توفّر مَعلمة الحدث معلومات إضافية عن الحدث.

على سبيل المثال، إذا كنت تريد معرفة وقت بث تغيير في 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
});

اعتراض الرسالة

تسمح حزمة "حزمة تطوير برامج الويب لجهاز الاستقبال" لتطبيق WebRecipient باعتراض الرسائل وتنفيذ رمز مخصّص على تلك الرسائل. يستخدم اعتراض الرسالة معلَمة 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 للمحتوى القابل للتشغيل (مشابهًا للسمة 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) لتكنولوجيا Cast واجهات برمجة تطبيقات متنوعة للسماح لتطبيق "جهاز استقبال الويب" بمعالجة هذه التفاعلات وتعديل واجهة مستخدم التطبيق من خلال حالات إجراءات المستخدم وإرسال التغييرات بشكل اختياري لتحديث أي خدمات خلفية.

طلبات الوسائط المتوافقة

تستنِد حالات عناصر التحكّم في واجهة المستخدم إلى MediaStatus.supportedMediaCommands وحدات التحكّم الموسّعة الخاصة بمرسلي أجهزة iOS وAndroid، وتطبيقات أجهزة الاستقبال والتحكّم عن بُعد، التي تعمل على الأجهزة التي تعمل باللمس، وتطبيقات أجهزة الاستقبال على أجهزة Android TV. عند تفعيل 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 وتحديد الإجراء المطلوب.
  • يُرجى تحديث UserActionState في MediaInformation لتحديث واجهة المستخدم.

يعترض المقتطف التالي طلب 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. ستتغير واجهة المستخدم في أجهزة مُرسِلي حزمة تطوير البرامج (SDK) لتقنية Google Cast والأجهزة التي تعمل باللمس لتعكس هذه الإعدادات. إذا لم يتم تفعيل العلامة، سيتم تنفيذ الأوامر الصوتية الواردة.

على سبيل المثال، في حال السماح بالوصول إلى 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" إلى تشغيل طلب في تطبيق WebRecipient.

بالنسبة إلى أوامر الوسائط التي لا يتوافق معها تطبيقك، يمكنك عرض سبب خطأ مناسب، مثل 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;
  });

الخلفية استنادًا إلى النشاط الصوتي

إذا كانت منصة 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. إيقاف تشغيل تطبيق WebRecipient.
  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 ثوانٍ من انتهاء العنصر السابق. إذا كان وقت التحميل المسبق أعلى من الوقت المتبقي على العنصر الحالي، فستتم عملية التحميل المسبق في أسرع وقت ممكن. لذا، إذا تم تحديد قيمة كبيرة جدًا للحمل المسبق في عنصر playlist، يمكن أن تحقّق قيمة واحدة تأثير هذا العنصر عندما نشغّل العنصر الحالي، فإننا نحمّل العنصر التالي مسبقًا. ومع ذلك، لا نترك الإعداد والاختيار في هذه الإعدادات لمطوّر البرامج، لأنّ هذه القيمة يمكن أن تؤثر في معدّل نقل البيانات وأداء البث للعنصر الحالي قيد التشغيل.

تتوافق ميزة التحميل المُسبق مع البث المباشر وفق بروتوكول HTTP (HLS) وDASH وSmooth (السلاسة) تلقائيًا.

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

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

يُعد تبادل الرسائل طريقة التفاعل الرئيسية لتطبيقات مستقبل الويب.

يُصدر المُرسِل رسائل إلى مُستلِم الويب باستخدام واجهات برمجة التطبيقات للمرسِل للنظام الأساسي الذي يستخدمه المُرسِل (Android وiOS والويب). يحتوي كائن الحدث (وهو بيان رسالة) الذي يتم تمريره إلى أدوات معالجة الأحداث على عنصر البيانات (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. تأكد من تغيير حجم صفحة المُستلِم بشكل سلس بدرجات دقة مختلفة.