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

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

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

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

ضبط التطبيق

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

يوضّح المثال أدناه كيفية إلغاء الإعداد التلقائي لرصد ما إذا كان اتصال المرسِل لا يزال نشطًا. عندما يتعذّر على جهاز الاستقبال على الويب التواصل مع جهاز الإرسال لمدة maxInactivity ثانية، يتم إرسال حدث SENDER_DISCONNECTED. الإعدادات أدناه تلغي هذه المهلة. يمكن أن يكون ذلك مفيدًا عند تصحيح الأخطاء لأنّه يمنع تطبيق Web Receiver من إغلاق جلسة "تصحيح الأخطاء عن بُعد في 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 بعد إنشاء المشغّل في عملية تحميل المحتوى التالية. توفّر حزمة تطوير البرامج الطرق التالية لتعديل PlaybackConfig.

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

يوضّح المثال أدناه كيفية ضبط PlaybackConfig عند إعداد CastReceiverContext. تلغي الإعدادات الطلبات الصادرة للحصول على ملفات البيان. يحدّد المعالج أنّه يجب تقديم طلبات Access-Control في 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) لجهاز الاستقبال على الويب لتطبيق جهاز الاستقبال على الويب بمعالجة أحداث اللاعب. يأخذ متتبِّع الأحداث مَعلمة 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
});

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

تسمح حزمة تطوير البرامج (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();

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

عند حدوث أخطاء في معترِض الرسائل، من المفترض أن يعرض تطبيق Web Receiver 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 لتخزين مستند تعريف REAL أو المَعلمات الرئيسية، واستخدام 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();

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

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

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

يتم تحديد حالات عناصر التحكّم في واجهة المستخدم من خلال 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) لبرنامج Web Receiver للأجهزة المزوّدة بخدمة "مساعد Google". يمكن العثور على عمليات التنفيذ التلقائية لهذه الأوامر في cast.framework.PlayerManager.

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

الطلبات الصوتية المتوافقة للتحكّم في الوسائط

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

بالنسبة إلى أوامر الوسائط التي لا يتيحها تطبيقك، يجب عرض سبب خطأ مناسب، مثل 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 إلى تطبيق Web Receiver عند بدء النشاط. يتم إرسال رسالة أخرى تتضمّن 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.

البيانات الوصفية واختيار الأصوات

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

إعادة توجيه البث

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

في ما يلي تسلسل أحداث إعادة توجيه البث:

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

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

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

تفعيل ميزة "إعادة توجيه البث"

لتنفيذ ميزة "إعادة توجيه البث" في تطبيق Web Receiver، اتّبِع الخطوات التالية:

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

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

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

يمكن إلغاء طلب التحميل الذي أنشأه تطبيق Web Receiver في معترِض الرسائل 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;
    });

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

يتيح Web Receiver التحميل المُسبَق لملفات الوسائط بعد تشغيل الملف الحالي في قائمة الانتظار.

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

سيعمل التحميل المُسبق تلقائيًا مع محتوى البث الذي يستخدم بروتوكولات HLS وDASH وSmooth.

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

رسائل مخصصة

يُعدّ تبادل الرسائل طريقة التفاعل الرئيسية لتطبيقات Web Receiver.

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

قد يختار تطبيق Web Receiver الاستماع إلى الرسائل في مساحة اسم محدّدة. وبناءً على ذلك، يُقال إنّ تطبيق Web Receiver يتوافق مع بروتوكول مساحة الاسم هذا. ويعود الأمر بعد ذلك إلى أي مُرسِلين متصلين يرغبون في التواصل على مساحة الاسم هذه لاستخدام البروتوكول المناسب.

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

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

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();

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

Cast لأجهزة الصوت

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

Android TV

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

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

يترجم تطبيق Google Web Receiver الذي يعمل على جهاز 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 وسيطة. انتقِل إلى صفحة اختبار Qualsys SSL للتحقّق مما يلي: إذا كان مسار الشهادة الموثوقة لموقعك الإلكتروني يتضمّن شهادة مرجع تصديق تحمل التصنيف "تنزيل إضافي"، قد لا يتم تحميلها على الأنظمة الأساسية المستندة إلى Android.
  • While Chromecast displays the receiver page on a 720p graphics plane, other Cast platforms including Android TV may display the page up to 1080p. تأكَّد من أنّ صفحة الاستقبال تتناسب بشكل جيد مع درجات الدقة المختلفة.