加入队列

概览

Web Receiver SDK 支持使用 SDK 提供的默认队列排队,方法是使用 QueueDataQueueManager,或使用自定义队列(实现 cast.framework.QueueBase 并使用 QueueManager 进行更新)。

Queueing API 允许应用通过提供以下功能来与 Cast 更好地集成:

  • 支持 Google 及合作伙伴的云端队列实现,因此外部存储和创建的队列可以直接加载到投放设备中。
  • 支持对队列中的项进行分页的机制,而不是一次性加载所有内容。
  • 支持新的消息传递,例如转到下一项、上一项、提取窗口以及获取与一组队列项相关的媒体信息。
  • QueueManager,用于管理队列项的插入、移除和更新。

默认队列

Web Receiver SDK 以默认队列的形式为开箱提供有限的队列支持。

如需使用默认队列,请在发件人端加载的 LoadRequestData 中提供 queueData,或使用 PlayerManager#load 发送本地加载请求。另请参阅加载媒体

在接收器端,加载初始媒体后可以使用 QueueManager 修改队列。

自定义队列

如果默认队列未提供您的应用所需的排队功能,则可以创建自定义队列,从而获得更多功能和灵活性。

应用开发者可以通过实现 cast.framework.QueueBase 来创建 Web 接收器端队列。

下面是一个基本示例,其中简单的 initialize 调用会被替换,然后队列内容列表及队列说明会提供给 Cast 设备。

另请参阅加载媒体

// Creates a simple queue with a combination of contents.
const DemoQueue = class extends cast.framework.QueueBase {
 constructor() {
   super();

   /**
    * List of media urls.
    * @private @const {!Array<string>}
    */
   this.myMediaUrls_ = [...];
 }
 /**
  * Provide a list of items.
  * @param {!cast.framework.messages.LoadRequestData} loadRequestData
  * @return {!cast.framework.messages.QueueData}
  */
 initialize(loadRequestData) {
   const items = [];
   for (const mediaUrl of this.myMediaUrls_) {
     const item = new cast.framework.messages.QueueItem();
     item.media = new cast.framework.messages.MediaInformation();
     item.media.contentId = mediaUrl;
     items.push(item);
   }
   let queueData = loadRequestData.queueData;
   // Create a new queue with media from the load request if one doesn't exist.
   if (!queueData) {
     queueData = new cast.framework.messages.QueueData();
     queueData.name = 'Your Queue Name';
     queueData.description = 'Your Queue Description';
     queueData.items = items;
     // Start with the first item in the playlist.
     queueData.startIndex = 0;
     // Start from 10 seconds into the first item.
     queueData.currentTime = 10;
   }
   return queueData;
 }
};

在此示例中,initialize 调用中的项列表在提供方的 QueueBase 构造函数调用中提供。不过,对于云队列实现,自定义 Web 接收器逻辑可以从外部提取项,然后将其作为初始化调用的一部分返回。

为了更全面地展示队列 API 的用法,下面是一个实现大多数 QueueBase 类的演示队列。

const DemoQueue = class extends cast.framework.QueueBase {
 constructor() {
   /** @private {} */
   super();
   YourServer.onSomeEvent = this.updateEntireQueue_;
 }

 /**
  * Initializes the queue.
  * @param {!cast.framework.messages.LoadRequestData} loadRequestData
  * @return {!cast.framework.messages.QueueData}
  */
 initialize(loadRequestData) {
   let queueData = loadRequestData.queueData;
   // Create a new queue with media from the load request if one doesn't exist.
   if (!queueData) {
     queueData = new cast.framework.messages.QueueData();
     queueData.name = 'Your Queue Name';
     queueData.description = 'Your Queue Description';
     // Put the first set of items into the queue
     const items = this.nextItems();
     queueData.items = items;
     // Start with the first item in the playlist.
     queueData.startIndex = 0;
     // Start from 10 seconds into the first item.
     queueData.currentTime = 10;
   }
   return queueData;
 }

 /**
  * Picks a set of items from remote server after the reference item id and
  * return as the next items to be inserted into the queue. When
  * referenceItemId is omitted, items are simply appended to the end of the
  * queue.
  * @param {number} referenceItemId
  * @return {!Array<cast.framework.QueueItem>}
  */
 nextItems(referenceItemId) {
   // Assume your media has a itemId and the media url
   return this.constructQueueList_(YourServer.getNextMedias(referenceItemId));
 }

 /**
  * Picks a set of items from remote server before the reference item id and
  * return as the items to be inserted into the queue. When
  * referenceItemId is omitted, items are simply appended to beginning of the
  * queue.
  * @param {number} referenceItemId
  * @return {!Array<cast.framework.QueueItem>}
  */
 prevItems(referenceItemId) {
   return this.constructQueueList_(YourServer.getPrevMedias(referenceItemId));
 }

 /**
  * Constructs a list of QueueItems based on the media information containing
  * the item id and the media url.
  * @param {number} referenceItemId
  * @return {!Array<cast.framework.QueueItem>}
  */
 constructQueueList_(medias) {
   const items = [];
   for (media of medias) {
     const item = new cast.framework.messages.QueueItem(media.itemId);
     item.media = new cast.framework.messages.MediaInformation();
     item.media.contentId = media.url;
     items.push(item);
   }
   return items;
 }

 /**
  * Logs the currently playing item.
  * @param {number} itemId The unique id for the item.
  * @export
  */
 onCurrentItemIdChanged(itemId) {
   console.log('We are now playing video ' + itemId);
   YourServer.trackUsage(itemId);
 }
};

在上面的示例中,YourServer 是您的云队列服务器,并且具有有关如何提取某些媒体项的逻辑。

如需使用由 QueueBase 实现的队列,需要在 CastReceiverContext 中设置队列选项:

const context = cast.framework.CastReceiverContext.getInstance();
context.start({queue: new DemoQueue()});

管理队列

通过提供访问当前存储的队列项列表以及当前播放项的方法,QueueManager 让开发者可以灵活地开发其排队解决方案。它还提供插入、移除和更新队列项等操作。以下代码段展示了如何访问 QueueManager 的实例:

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

默认队列管理

初始队列加载完成后,QueueManager 可用于执行各种操作,例如检索当前项、检索队列中的所有项,以及使用 insertItemsremoveItemsupdateItems 更新队列中的项。

自定义队列管理

下面是一个自定义队列实现示例,该实现使用基于某个事件的插入和移除方法。该示例还演示了 updateItems 的使用情形,开发者可以修改现有队列中的队列项,例如移除广告插播时间点。

const DemoQueue = class extends cast.framework.QueueBase {
  constructor() {
    super();

    /** @private @const {!cast.framework.QueueManager} */
    this.queueManager_ = context.getPlayerManager().getQueueManager();
  }

  /**
   * Provide a list of items.
   * @param {!cast.framework.messages.LoadRequestData} loadRequestData
   * @return {!cast.framework.messages.QueueData}
   */
  initialize(loadRequestData) {
    // Your normal initialization; see examples above.
    return queueData;
  }

  /** Inserts items to the queue. */
  onSomeEventTriggeringInsertionToQueue() {
    const twoMoreUrls = ['http://url1', 'http://url2'];
    const items = [];
    for (const mediaUrl of twoMoreUrls) {
      const item = new cast.framework.QueueItem();
      item.media = new cast.framework.messages.MediaInformation();
      item.media.contentId = mediaUrl;
      items.push(item);
    }
    // Insert two more items after the current playing item.
    const allItems = this.queueManager_.getItems();
    const currentItemIndex = this.queueManager_.getCurrentItemIndex();
    const nextItemIndex = currentItemIndex + 1;
    let insertBefore = undefined;
    if (currentItemIndex >= 0 &&
        currentItemIndex < allItems.length - 1) {
      insertBefore = allItems[nextItemIndex].itemId;
    }
    this.queueManager_.insertItems(items, insertBefore);
  }

  /** Removes a particular item from the queue. */
  onSomeEventTriggeringRemovalFromQueue() {
    this.queueManager_.removeItems([2]);
  }

  /** Removes all the ads from all the items across the entire queue. */
  onUserBoughtAdFreeVersion() {
    const items = this.queueManager_.getItems();
    this.queueManager_.updateItems(items.map(item => {
      item.media.breaks = undefined;
      return item;
    }));
  }
};

传入和传出的消息

为了全面支持将接收器端队列提取作为可信来源,CAF 接收器 SDK 引入了并处理以下额外的排队消息:

收到的消息 参数 传出响应消息 返回
下一步 无需参数。 媒体状态 接收器将(在必要时通过 NextItems() 提取)并开始播放下一项内容。
上一页 无需参数。 媒体状态 网络接收器将(通过 prevItems() 提取,如有必要)并开始播放上一项内容。
FETCH_ITEMS FetchItemsRequestData QUEUE_CHANGE 一个 cast.framework.messages.QueueChange。例如,对于插入情形,JSON 中的 items 字段将包含所提取的新项的列表。
GET_ITEMS_INFO 包含 itemIds 的 GetItemsInfoRequestData:数组<number> ITEMS_INFO 包含队列项信息的 cast.framework.messages.ItemsInfo。
GET_QUEUE_IDS 无需参数。 QUEUE_IDS cast.framework.messages.QueueIds。

对于 NEXT/PREVIOUS,如果 Web 接收器上的现有队列表示没有更多项,系统会自动调用 QueueBase.nextItems()QueueBase.prevItems() 来接收更多项。

对于 FETCH_ITEM,系统会为 Cloud 队列调用 QueueBase 实现中的相应函数 fetchItems,该函数会检索要返回给 Web 接收器以存储的相关数据。

每当提取更多项时,系统都会触发新的消息类型 QUEUE_CHANGE,并将其发送回发送者。查看各种类型的队列更改

对于 GET_ITEMS_INFOQueueBase 的实现不会被触发,并且 Web 接收器会返回 ID 列表已知的媒体信息。

随机播放队列

如需设置要随机播放队列中的项,请在将项加载到队列中时将 QueueDatashuffle 标志设置为 true

如果您使用的是 QueueBase 的实现,请使用 shuffle 方法返回已打乱顺序的项列表。

如需打乱现有队列,请使用 QUEUE_UPDATE MessageTypeshuffle 标志,而不是 QUEUE_SHUFFLE 命令。如需了解详情,请参阅 QueueUpdateRequestData

重复模式

如需将队列中的项设置为重复项,请在将项加载到队列中时将 QueueDatarepeatMode 属性设置为所需的 RepeatMode

如需更改现有队列的 RepeatMode,请使用 QueueUpdateRequestDatarepeatMode 属性,该属性使用 QUEUE_UPDATEMessageType