實作 Co-Watching API

本頁面說明如何使用 Co-Watching API 支援 共同觀看情境

初始設定

為了準備程式庫使用,即時分享應用程式應將 CoWatchingClient敬上 物件,代表共同觀看工作階段。

如要使用 Meet 即時分享 SDK,請呼叫 AddonClientFactory.getClient敬上 方法。這會傳回 AddonClient敬上 做為共同觀看工作階段的進入點

如要使用用戶端,請呼叫 newSessionBuilder敬上 從 AddonClient 的 方法,為新的 AddonSessionnewSessionBuilder 會導入 AddonSessionHandler 介面,處理 外掛程式

如要開始練習,請在 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));
  }
}