实现 Co-Watching API

这一页介绍了如何使用 Co-Watching API 来支持 一起看的场景

初始设置

要准备库以供使用,实时共享应用应初始化 CoWatchingClient 对象,该对象表示一起观看的会话。

要使用 Meet 实时共享 SDK,请调用 AddonClientFactory.getClient 方法。这将返回一个 AddonClient 作为“一起看”会话的入口点

要使用客户端,请调用 newSessionBuilder AddonClient 方法返回新 AddonSessionnewSessionBuilder 会实现 AddonSessionHandler 用于处理由 API 提供的 插件

要开始会话,请添加 withCoWatching 添加到构建器上。

以下代码示例展示了“一起看”客户端的基本初始化 对象:

Java

class AwesomeVideoAddonSessionHandler implements AddonSessionHandler {}

// For sample implementation, see the "Manage remote state" section below.
class AwesomeVideoCoWatchingHandler implements CoWatchingHandler {}

public ListenableFuture<AddonSession> initialSetup() {
  AddonClient meetClient = AddonClientFactory.getClient();
  return meetClient
      .newSessionBuilder(
          new AwesomeVideoAddonSessionHandler())
      .withCoWatching(new AwesomeVideoCoWatchingHandler())
      .begin();
}

在用户操作时发送通知

当本地用户执行操作(例如暂停或搜索媒体)时 播放 - 必须告知该库,以便执行这些操作 镜像到“一起看”体验中的其他参与者有关 有关如何针对多个状态通知库,请参阅获取 开始

您可以使用以下方法控制“一起看”状态:

以下代码示例展示了如何通知用户:

Java

public void onVideoPaused(Duration currentTimestamp) {
  // Use Meet to broadcast the pause state to ensure other participants also pause.
  this.session.getCoWatching().notifyPauseState(/* paused= */ true, currentTimestamp);
};

管理远程状态

如要应用远程参与者收到的更新,您必须提供 了解如何使用 该 CoWatchingHandler.onCoWatchingStateChanged() 回调。

Meet 还需要检索媒体的当前位置 调用 CoWatchingHandler.onStateQuery() 回调。此方法会定期调用,因此编写时应保证其高性能 (例如,<100 毫秒)。

以下代码示例展示了 CoWatchingHandler

Java

class AwesomeVideoCoWatchingHandler implements CoWatchingHandler {
  /** Applies incoming playback state to the local video. */
  public void onCoWatchingStateChanged(CoWatchingState newState) {
    // Handle transition to new video.
    if (!newState.mediaId().equals(this.videoPlayer.videoUrl)) {
      this.videoPlayer.loadVideo(newState.mediaId());
    }

    // Only adjust the local video playout if it's sufficiently diverged from the timestamp in the
    // applied update.
    if (newState
            .mediaPlayoutPosition()
            .minus(this.videoPlayer.videoTimestamp)
            .compareTo(Duration.ofMillis(500))
        > 0) {
      this.videoPlayer.seek(newState.mediaPlayoutPosition());
    }

    // Update pause state, if necessary.
    if (newState.playbackState().equals(PLAY) && this.videoPlayer.isPaused) {
      this.videoPlayer.unpause();
    } else if (newState.playbackState().equals(PAUSE) && !this.videoPlayer.isPaused) {
      this.videoPlayer.pause();
    }
  }

  /** Returns local video playback state. */
  public Optional<QueriedCoWatchingState> onStateQuery() {
    return Optional.of(QueriedCoWatchingState.of(
      /* mediaPlayoutPosition= */ this.videoPlayer.videoTimestamp));
  }
}