ハイライト
tvOS ピクチャ イン ピクチャを使用すると、Apple TV アプリで全画面ビデオと PiP ビデオを同時に再生でき、AVPlayerViewController または AVPictureInPictureController を使用してプロセスの開始、交換、停止、再開を処理できます。
主要内容
Apple TV 上のビデオ アプリの一般的なシナリオは、閲覧ページに複数のコンテンツが存在することです。つまり、ゲームがプレイ中で、ユーザーが別のビデオを開こうとしているということです。以前は、このタイプのエクスペリエンスは、アプリ自体に依存して複雑なプレーヤーの切り替えを実行することしかできませんでした。 tvOS のピクチャー イン ピクチャー (PiP) はこれをシステムに任せ、一方のビデオが PiP ウィンドウに留まり、もう一方のビデオが全画面再生になることを許可します。
このセッションの主な違いは「交換」です。 tvOS は iPadOS の PiP エクスペリエンスを維持し、同時に 2 つのビデオを再生する機能を追加します。ユーザーは全画面コンテンツを PiP コンテンツと交換できますが、プレーヤーが PiP に入り、PiP から再開し、アプリ間で交換するときに表と裏を切り替えることができるようにアプリを準備する必要があります。
実装パスは 2 つのカテゴリに分類されます。アプリが標準を使用している場合AVPlayerViewController、プロジェクトとオーディオ セッションを構成した後、システムは PiP ボタンを表示し、デリゲートを介して開始、停止、再開を通知します。カスタムプレーヤーは使用する必要がありますAVPictureInPictureController、によるとcanStopPictureInPictureインターフェースに「Start」、「Swap」、「Stop」のいずれを表示するかを決定します。
既存の Apple TV ビデオ アプリにも、チェックすべき 2 つの古いデザインがあります。初め、AVPlayerViewControllerスワイプアップ ジェスチャは PiP コントロール領域に到達するためにすでに使用されており、インタラクティブ オーバーレイを移行する必要があります。customOverlayViewController。第 2 に、PiP 中もユーザーはアプリ内を移動でき、プレーヤー デリゲートは破棄されるビュー階層に関連付けることができません。
詳細
プロジェクトの機能と音声セッション
(01:45) プレーヤー ロジックの作成を開始する前に、プロジェクトは Xcode 12 の署名と機能にバックグラウンド モードを追加し、ピクチャ イン ピクチャをチェックする必要があります。次にアプリを入れますAVAudioSessionカテゴリはに設定されていますplayback。 Session 氏は、この手順は iPadOS の PiP 構成と一致していると説明しています。
(02:13) 公式の例では、共有オーディオ セッションを取得して、再生カテゴリを設定するという 1 つのことだけを実行します。
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback)
} catch {
print("Setting category to AVAudioSessionCategoryPlayback failed.")
}
キーポイント:
AVAudioSession.sharedInstance()現在のアプリの共有オーディオ セッションを取得します。 -setCategory(.playback)これは再生メディア アプリであり、PiP にはこのタイプのオーディオ構成が必要であることをシステムに伝えます。 -do/catchサイレント障害後の予測不能な PiP 動作を回避するために、設定障害の処理パスを保持します。
標準プレーヤーの PiP ライフサイクル
(02:26) アプリがAVPlayerViewController, プロジェクトの構成が完了すると、標準の再生 UI に PiP アフォーダンスが自動的に表示されます。アプリが注目する必要があるのは、PiP の開始、PiP の停止、PiP からの UI の復元といったデリゲートのライフサイクルです。
(03:14) ここで最も問題となるのは、UI の復元です。システムは、プレーヤーに対応できる状態にインターフェースを復元する機会をアプリに与えます。セッションは、高速再開とアニメーションの回避を明示的に推奨します。再開が遅すぎると、再開したプレーヤーは終了します。
プレーヤーの開始、切り替え、停止をカスタマイズする
(04:10) 使用するカスタム再生 UIAVPictureInPictureController。 tvOS の新しい主要な状態は次のとおりです。canStopPictureInPicture:そうですfalse、インターフェイスに「PiP の開始」と表示されるはずです。それはですtrue、インターフェイスにスワップと停止が表示されるはずです。
(04:52) ユーザーが「開始」をクリックすると呼び出されますstartPictureInPicture。ユーザーが「交換」をクリックしたときにも呼び出されますstartPictureInPicture、全画面プレーヤーの観点からもPiPに入っているためです。ユーザーが明示的に停止を選択した場合にのみ、全画面プレーヤーに対応するコントローラーが呼び出されます。stopPictureInPicture。
(05:57)canStopPictureInPictureたとえば、ユーザーが PiP ウィンドウから直接再生を停止した場合など、いつでも変更できます。カスタム UI は、このプロパティを監視し、ボタンを更新する必要があります。
_ = pipController.observe(\.canStopPictureInPicture) { controller, change in
// Update your UI
if controller.canStopPictureInPicture {
pipActions = [.swap, .stop]
} else {
pipActions = [.start]
}
}
キーポイント:
pipController.observe(\.canStopPictureInPicture)KVO を使用して PiP ステータスの変化を監視します。 -controller.canStopPictureInPictureのためにtrue、現在の全画面プレーヤーは、既存の PiP を交換または停止できます。 -pipActions = [.swap, .stop]カスタム UI がスワップと停止を公開する必要があることを示します。 -pipActions = [.start]現在のインターフェイスが開始 PiP を提供するだけでよいことを示します。
複数の再生中の情報ソース
(06:26) tvOS 14 では、複数の Now Playing 情報センターを公開できます。 2 つのビデオを同時に再生する場合、全画面コンテンツと PiP コンテンツの両方に独自の再生中情報が必要です。アプローチは次のとおりですAVPlayerバインドするMPNowPlayingSession。
(06:54) tvOS で PiP を使用する場合は、次のように渡します。AVPictureInPictureController同じプレーヤーにバインドする必要がありますMPNowPlayingSession。セッションでは次のことも思い出させます:MPNowPlayingSessionその後、システムは古い共有ファイルを無視します。MPNowPlayingInfoCenter更新すると、アプリ全体が新しい公開方法に移行される必要があります。
(07:06) カスタム プレーヤー コントローラーの構造は次のとおりです。
final class CustomPlayerViewController: UIViewController {
init(player: AVPlayer) {
let playerLayer = AVPlayerLayer(player: player)
pictureInPictureController = AVPictureInPictureController(playerLayer: playerLayer)
nowPlayingSession = MPNowPlayingSession(players: [player])
}
private func publishNowPlayingMetadata() {
nowPlayingSession.nowPlayingInfoCenter.nowPlayingInfo = // Your Now Playing info
nowPlayingSession.becomeActiveIfPossible()
}
}
キーポイント:
init(player: AVPlayer)プレーヤー コントローラーへの入力として同じプレーヤーを使用します。 -AVPlayerLayer(player: player)PiP コントローラーで使用する画面出力レイヤーを作成します。 -AVPictureInPictureController(playerLayer: playerLayer)このプレーヤーの PiP を管理します。 -MPNowPlayingSession(players: [player])同じプレーヤーを別の Now Playing セッションにバインドします。 -nowPlayingInfoCenter.nowPlayingInfo現在のビデオのメタデータを書き込みます。 -becomeActiveIfPossible()このセッションが Now Playing 情報の公開を開始するように要求します。
交換のためのインターフェイスとアーキテクチャの要件
(08:23) 同じアプリ内で交換する場合、PiP に入るプレーヤーが最初に will-start を受け取り、PiP から出るプレーヤーはアプリに UI を復元するように依頼し、その後 will-stop をトリガーします。アニメーションが完了すると、2 人のプレーヤーは Did-start と Did-stop を受け取ります。
(09:19)アプリ間の交換は 2 方向で行われます。現在のアプリの全画面コンテンツが PiP に入ると、アプリはアニメーションの後にバックグラウンドに入ります。現在のアプリの PiP コンテンツが全画面に戻ると、アプリはまずフォアグラウンドに表示され、すぐに UI に戻り、PiP will-stop と Did-stop を受信します。
(12:15) 既存AVPlayerViewControllerこのアプリはインタラクティブなオーバーレイも処理します。 tvOS 13 以降、スワイプアップ ジェスチャは標準プレーヤーによって予約されており、ユーザーが PiP コントロールにアクセスできるようにするために使用されます。カスタム チャンネル リスト、おすすめコンテンツ、またはその他のスライドアップ コントロールは、内部に配置する必要があります。customOverlayViewController。
(14:41) デリゲートのアーキテクチャも調整する必要があります。 PiP の間、ユーザーはアプリ内での移動を続けることができますが、元の表示ビュー コントローラーがインターフェイス階層に存在しない可能性があります。 Session では、ビデオが PiP の場合でも引き続き AVKit イベントを受信できるように、デリゲートを独立したオブジェクトにすることをお勧めします。
重要ポイント
- スポーツマルチスクリーン視聴モードを作成
何をすべきか: ユーザーがメインの試合を全画面表示のままにして、別の試合を PiP に入れ、重要な瞬間に 2 つのフィードを交換できるようにします。
実行する価値がある理由: セッションでは、tvOS 固有の同時再生とスワップを示します。startPictureInPicture通常のスタート動作と交換動作の両方をカバーできます。
開始方法: まずチャンネルごとに独立したビデオを準備しますAVPlayer、標準プレーヤーが優先されますAVPlayerViewController;コントロール バーをカスタマイズする必要がある場合は、プレーヤーごとにコントロール バーを作成しますAVPictureInPictureController、観察してくださいcanStopPictureInPicture更新ボタン。
- 再生を中断しないビデオ アプリのチャンネル ナビゲーションを提供します
機能: ユーザーが番組を視聴しているときに、上にスクロールしてチャンネル リストまたはおすすめコンテンツを開きます。PiP コントロールとカスタム オーバーレイはそれぞれ独自の方法で表示されます。
実行する価値がある理由: セッションでは、上にスワイプ ジェスチャが行われたことを明示的に示しています。AVPlayerViewControllerPiP コントロールの場合、カスタム オーバーレイを移行する必要があります。customOverlayViewController。
開始方法: 元々カスタム スワイプアップ認識エンジンに依存していたオーバーレイを次の場所に移動します。AVPlayerViewController.customOverlayViewControllerをクリックし、PiP コントロール、トランスポート バー、オーバーレイ ボタンのフォーカス順序を確認します。
- 複数のライブ ブロードキャストの独立した Now Playing 情報を公開
対処方法: 全画面ライブ ブロードキャストと PiP ライブ ブロードキャストでは、それぞれタイトル、チャンネル、進行状況などのメタデータが表示されるため、システム UI がいつでも正しい情報ソースに切り替えることができます。
価値がある理由: tvOS 14 は複数の機能をサポートしていますMPNowPlayingSession、PiP で使用されるプレーヤーは、対応するセッションにバインドされている必要があります。
開始方法: それぞれAVPlayer確立するMPNowPlayingSession(players:)、古い共有を置きますMPNowPlayingInfoCenterセッションへの移行を更新するnowPlayingInfoCenter、プレイアイテムが変更されたときにメタデータを公開し続けます。
- ビュー コントローラーからプレーヤー イベント処理を削除します
やるべきこと: PiP ライフサイクル、回復 UI、アプリ間交換処理を独立したコーディネーターが管理できるようにします。
実行する価値がある理由: PiP 中に、ユーザーはプレーヤー ページを離れてアプリの閲覧を続けることができ、ビュー階層にハングしているデリゲートが早期に解放される可能性があります。
開始方法: 存続期間の長いプレイヤー コーディネーターを作成し、保持させます。AVPlayerViewControllerDelegateまたは PiP デリゲート関連のロジック。 UI を復元するときは、必要なナビゲーションとプレーヤーの配置のみを実行し、アニメーションは避けてください。
関連セッション
- tvOS 用の SwiftUI アプリを構築する — Apple TV ビデオ ホームページのデザインに適した、tvOS ボタン スタイル、フォーカス API、水平シェルフについて説明します。
- Apple TV の検索候補を見つける — Apple TV の検索インターフェイスと
UISearchController, これでビデオアプリの発見入り口を完了できます。 - tvOS アプリで複数のユーザーをサポート — Apple TV のマルチユーザー プロファイルと切り替えについて説明しており、メディアの再生ステータスやユーザー プロファイルと合わせて計画するのに適しています。
- HLS をオフラインでダウンロードして再生する方法を確認する — AVFoundation による HLS コンテンツのダウンロードとオフライン再生について説明し、ビデオ再生リンクを補完します。
- AVFoundation を使用した HDR ビデオの編集と再生 — ビデオ再生機能をさらに深化させるのに適した AVFoundation HDR の再生と編集について説明します。
コメント
GitHub Issues · utterances