WWDC Quick Look 💓 By SwiftGGTeam
Coordinate media playback in Safari with Group Activities

Coordinate media playback in Safari with Group Activities

元の動画を見る

ハイライト

Safari 15 では、Media Session API と Coordinator 拡張機能を介して Web ページに SharePlay の同期再生機能が導入され、Mac ユーザーは App Store アプリをインストールせずに FaceTime で同じメディア再生に参加できるようになります。

主要内容

iPhone ビデオ アプリはすでにお持ちです。アプリはすでにグループ アクティビティに接続されているため、ユーザーは FaceTime で映画の予告編を一緒に見ることができます。

問題は Mac ユーザーにあります。

あなたのサービスには Web サイトもあります。 Mac ユーザーは Safari を開いたときに同じコンテンツを表示できますが、以前は Web ページはローカル再生のみを担当していました。 FaceTime に他の人がいることを認識せず、再生、一時停止、進行状況のドラッグなどのアクションを他のデバイスに同期させることもできません。

これにより、エクスペリエンスが切断される可能性があります。 iPhone を使用している人は Watch Together を起動しますが、Mac を使用している人は Web ページを検索し、映画ソースを見つけて、再生時間を手動で調整する必要があります。

Safari 15 では、このリンクが Web ページに追加されます。

最初のステップでは、ネイティブ アプリがグループ アクティビティのメタデータで提供されます。fallbackURL。この URL は、Web サイト上の特定のコンテンツを指します。 Mac ユーザーが招待を受け入れると、Safari はこの URL を開きます。

2 番目のステップでは、Web ページがメディア セッション API にアクセスします。これは、現在のメディアのタイトル、カバー、再生ステータス、進行状況を Safari に伝え、再生、一時停止、処理する Web ページへのジャンプなどのシステム コントロールを返します。

3 番目のステップでは、Safari は次のようになります。navigator.mediaSessionコーディネーターを追加します。 Web ページは、それを介して SharePlay セッションに参加し、ローカル ユーザーの再生意図を他のデバイスに送信し、他のデバイスから再生意図を受信します。

このようにして、iPhone から開始された共有再生を Safari Web ページにドロップできます。 Web ページは引き続き独自に再生されます<video>ただし、再生コマンドはコーディネーターによって調整されます。

詳細

Safariで開けるコンテンツURLを用意する

02:50

Safari は、何もないところからグループ アクティビティ セッションに参加することはできません。ネイティブ アプリが共有を開始するときは、アクティビティ メタデータで提供する必要がありますfallbackURL

この URL は、Web サイトのホームページのみを指すことはできません。特定のコンテンツをターゲットにして再生できる必要があります。スピーチの例は、次の URL を含む映画の予告編 Web サイトです。contentIdentifier

import Foundation
import GroupActivities

struct WatchTogether: GroupActivity {
    var contentIdentifier: String

    func metadata() async -> GroupActivityMetadata {
        var metadata = GroupActivityMetadata()
        metadata.fallbackURL = URL(string: "https://example.com/title/\(contentIdentifier)")
        return metadata
    }
}

キーポイント:

  • import GroupActivitiesSharePlay の背後にあるフレームワークを紹介します。
  • WatchTogether従うGroupActivity、共有可能な視聴イベントを表します。
  • contentIdentifier現在のメディア コンテンツの識別子を保存します。
  • metadata()この共有イベントのメタデータを返します。
  • fallbackURLWeb サイト上の特定のコンテンツ ページを指します。
  • Mac ユーザーが招待を受け入れると、Safari はこの URL をロードします。

このステップにより、入口の問題が解決されます。 Safari が正しい Web ページを開くことができたら、その Web ページは現在何が再生されているかをブラウザーに理解させる必要もあります。

メディア セッションを使用して再生ステータスとシステム コントロールを公開する

05:29

メディア セッションは標準の Web API です。 Web ページはこれを使用して、タイトル、カバー、再生ステータス、再生時間、現在のメディアの進行状況をブラウザーに伝えます。

Safari がこの情報を取得すると、それをシステムの Now Playing に渡すことができます。ユーザーが macOS メニュー バーで再生または一時停止をクリックすると、Safari は Web ページに登録されているハンドラーを呼び出します。

const video = document.querySelector('video');
const myPlayer = {
  titleString: 'The Mosquito Coast — Trailer',
  artworkURL: '/artwork/trailer.jpg'
};

if (navigator.mediaSession) {
  navigator.mediaSession.setActionHandler('play', () => video.play());
  navigator.mediaSession.setActionHandler('pause', () => video.pause());
  navigator.mediaSession.setActionHandler('seekto', details => {
    video.currentTime = details.seekTime;
  });
}

let updateMediaSessionState = function() {
  if (!navigator.mediaSession) {
    return;
  }

  let playbackState = video.paused ? 'paused' : 'playing';
  navigator.mediaSession.playbackState = playbackState;

  let positionState = {
    duration: video.duration,
    playbackRate: video.playbackRate,
    position: video.currentTime
  };
  navigator.mediaSession.setPositionState(positionState);
};

for (let event of ['playing', 'pause', 'durationchange', 'ratechange', 'timeupdate']) {
  video.addEventListener(event, updateMediaSessionState);
}

if (navigator.mediaSession) {
  navigator.mediaSession.metadata = new MediaMetadata({
    title: myPlayer.titleString,
    artwork: [{ src: myPlayer.artworkURL }]
  });
}

キーポイント:

  • document.querySelector('video')ページ上でビデオ要素を見つけます。
  • navigator.mediaSessionブラウザがメディア セッションをサポートしているかどうかを判断するために使用されます。
  • setActionHandler('play', ...)システムの再生ボタンを次のように接続します。video.play()
  • setActionHandler('pause', ...)システムの一時停止ボタンを次の場所に接続します。video.pause()
  • setActionHandler('seekto', ...)システムから渡されたジャンプ時間を受信し、更新します。video.currentTime
  • playbackStateWeb ページの再生または一時停止ステータスをブラウザと同期します。
  • setPositionState()再生時間、再生速度、現在位置をブラウザと同期します。
  • MediaMetadataNow Playing 表示のタイトルとカバーを指定します。

このステップにより、Web ページがシステムによって制御されるようになります。次のステップでは、これらのコントロールを同じ SharePlay セッション内の他のデバイスに拡張します。

Coordinator を使用して SharePlay に参加し、同期再生を行う

09:32

Safari 15 はメディアセッションに新機能を追加しますcoordinator。これは、Web ページが既存のセッションに参加し、再生インテントを送信し、他のデバイスから再生ステータスの変更を受信するために使用されます。

プレゼンテーションでは 3 つの限界が強調されました。

まず、Coordinator はまだ実験的な Web API であり、インターフェイスは変更される可能性があります。次に、当時は Safari にのみ実装されていました。 3 番目に、Web ページは既存のセッションに参加できますが、GroupSession は iPhone、iPad、または macOS アプリから開始する必要があります。

const video = document.querySelector('video');
const controls = {
  inSessionIcon: document.querySelector('#in-session-icon'),
  playButton: document.querySelector('#play-button'),
  pauseButton: document.querySelector('#pause-button'),
  timeline: document.querySelector('#timeline')
};

navigator.mediaSession.addEventListener('coordinatorchange', () => {
  let coordinator = navigator.mediaSession.coordinator;

  if (coordinator) {
    coordinator.join();
  }

  controls.inSessionIcon.hidden = !coordinator;
});

controls.inSessionIcon.addEventListener('click', () => {
  let coordinator = navigator.mediaSession.coordinator;

  if (coordinator && coordinator.state === 'joined') {
    coordinator.leave();
  }
});

controls.playButton.addEventListener('click', () => {
  let coordinator = navigator.mediaSession.coordinator;

  if (coordinator) {
    coordinator.play();
  } else {
    video.play();
  }
});

controls.pauseButton.addEventListener('click', () => {
  let coordinator = navigator.mediaSession.coordinator;

  if (coordinator) {
    coordinator.pause();
  } else {
    video.pause();
  }
});

controls.timeline.addEventListener('change', event => {
  let coordinator = navigator.mediaSession.coordinator;

  if (coordinator) {
    coordinator.seekTo(event.target.value);
  } else {
    video.currentTime = event.target.value;
  }
});

キーポイント:

  • coordinatorchangeコーディネーターの利用可能なステータスが変化するとトリガーされます。
  • navigator.mediaSession.coordinator現在のコーディネーターを取得します。
  • coordinator.join()Web ページをこの共有再生セッションに参加させます。
  • controls.inSessionIcon.hiddenセッション中かどうかに応じてステータス アイコンを表示します。
  • セッションアイコンをクリックしたときのステータスがjoined、 電話leave()やめる。
  • 再生ボタン優先通話coordinator.play()、コーディネーターはすべてのデバイスに再生を開始するように通知します。
  • 一時停止ボタンが最初に呼び出されますcoordinator.pause()、コーディネーターはすべてのデバイスに一時停止するように通知します。
  • プログレスバーが変化したときに最初に呼び出されますcoordinator.seekTo()、ジャンプの意図をセッションに同期します。
  • コーディネーターが存在しない場合、コードはローカルにフォールバックします。videoコントロール。

コーディネーターはセッション内の他のデバイスと通信し、再生状態の変更を処理し、競合を解決して、全員の準備が整うのを待ちます。準備が完了すると、以前に登録されたメディア セッション アクション ハンドラーを呼び出して、ローカル再生を開始または一時停止します。

最小アクセス順序

07:32

このセッションのアクセス パスは非常に短いですが、順序を間違えることはできません。

まずネイティブ アプリにfallbackURL共有アクティビティ。次に、Web ページでメディア セッションを使用して状態とコントロールを Safari に公開します。最後に、コーディネーターを使用して Web ボタンを同期再生ボタンに変換します。

function playFromControl() {
  let coordinator = navigator.mediaSession && navigator.mediaSession.coordinator;

  if (coordinator) {
    coordinator.play();
    return;
  }

  video.play();
}

キーポイント:

  • navigator.mediaSession && navigator.mediaSession.coordinatorメディアセッションとコーディネーターの両方をチェックします。
  • コーディネーターが存在する場合、ユーザーの再生アクションは共有セッションに入ります。
  • コーディネーターがない場合、再生アクションはローカル Web ページにのみ影響します。
  • このブランチにより、同じ Web コントロールのセットが通常の再生と SharePlay 再生の両方に対応できるようになります。

重要ポイント

1. Web 側の SharePlay 入口をビデオ アプリに追加します

  • 何をすべきか: ユーザーは iPhone アプリで一緒に視聴を開始し、Mac ユーザーは招待を受け入れて Safari に直接入って同じエピソードを再生します。
  • 実行する価値がある理由: セッション中fallbackURLとコーディネーターを使用すると、Web ページがネイティブ アプリによって開始されたセッションに参加できるようになります。
  • 開始方法:GroupActivityMetadataコンテンツ詳細ページへのリンクを設定するfallbackURL、Webページへのアクセスnavigator.mediaSessionそしてnavigator.mediaSession.coordinator

2. トレーラーを作成してリストを一緒に見る

  • やるべきこと: 友達は FaceTime で映画の予告編を一緒に見ます。一方が進行状況をドラッグまたは一時停止すると、もう一方の写真も同時に変化します。
  • 価値がある理由: コーディネーターのサポートplay()pause()seekTo()このタイプの再生インテントは同期されます。
  • 開始方法: まず、各トレーラーを安定した URL にし、Web プレーヤーのボタン イベントで最初にコーディネーター メソッドを呼び出します。

3. Now Playing コントロールをオーディオ Web サイトに追加します

  • 内容: ポッドキャストまたは音楽 Web ページには、タイトル、カバー アートが表示され、macOS メニュー バーの再生中の再生一時停止に応答します。
  • 実行する価値がある理由: メディア セッションは、再生状態、位置状態、およびメタデータを公開できます。
  • 開始方法:playpauseseekto登録するsetActionHandler()、オーディオ要素イベントをリッスンした後に呼び出されますsetPositionState()

4. SharePlay ステータス プロンプトを Web プレーヤーに追加します

  • 対処方法: プレーヤーが共有セッションに入ると、セッション アイコンが表示され、ユーザーはクリックしてセッションを終了します。
  • 実行する価値がある理由: セッションで例を使用するcoordinatorchangeアイコンの表示と使用を制御するleave()やめる。
  • 開始方法: モニタリングnavigator.mediaSessioncoordinatorchangeイベントに基づいてcoordinator切り替えUIの有無。

5. 同じプレーヤーのセットがローカル再生と共有再生の両方をサポートします

  • 対処方法: 一般のユーザーが再生をクリックすると、ローカルで再生されます。 SharePlay ユーザーが再生をクリックすると、全員に同期されます。
  • 実行する価値がある理由: Web ページはイベント ハンドラーでチェックできます。navigator.mediaSession.coordinator、セッション状態に応じて制御パスを選択します。
  • 開始方法: 再生、一時停止、プログレス バー イベントを統合し、ブランチで最初に呼び出します。coordinator.play()coordinator.pause()coordinator.seekTo()、それ以外の場合は操作します<video>

関連セッション

コメント

GitHub Issues · utterances