Picture-in-Picture (PiP) は、他のアプリケーションの上にフローティングウィンドウで動画を表示する再生モードです。アプリを最小化したり、プログラムを切り替えたりしても、ユーザーは視聴を続けることができます。PiPウィンドウは自動的に画面の隅に配置され、ユーザーが移動できます。Apple AVPictureInPictureController ドキュメント (2026) によると、PiPモードは iOS バージョン 14 以降、Android バージョン 8.0 以降でサポートされています。
重要なポイント
Picture-in-Picture (PiP) は、他のすべてのウィンドウやアプリケーションの上に表示される小さなフローティングウィンドウで動画コンテンツを表示するモードです。ユーザーはPiPウィンドウを画面上で移動したり、サイズを変更したり(一部のプラットフォーム)、他のアプリケーションで作業しながらコンテンツを視聴し続けることができます。
PiPの概念はテレビから来ています:1990年代にはすでにテレビが画面の隅に第2チャンネルを表示できていました。モバイルデバイスでは、PiPは最初にiPadのiOS 9(2015年)でSafari動画向けに登場し、アプリ向けの完全なシステムPiPはiOS 14(2020年)で利用可能になりました。AndroidでのPiPサポートはより早く登場しました — バージョン8.0 Oreo(2017年)ですが、動画のみで、Android 12以降はすべての種類のコンテンツに対応しています。
PiPはバックグラウンド再生とは異なり、動画がオーディオストリームだけでなく画面上にも表示され続けます。バックグラウンドオーディオ再生は両方のプラットフォームで利用可能ですが、PiPはユーザーにコンテンツの視覚的制御を提供します:フレームを見たり、一時停止したり、巻き戻したり、ウィンドウを閉じたりできます。これは、視覚コンテンツがオーディオと同様に重要なビデオチュートリアル、ストリーム、ビデオ通話で特に重要です。
アーキテクチャ的には、PiPは低い表示優先度を持つ別のウィンドウを作成するシステムウィンドウマネージャーを介して実装されます。アプリは動画出力をシステムサービスに委任し、アプリがバックグラウンドに移動したり最小化されたりした後も動画のレンダリングを続けます。
プロセスは、ユーザーがアクティブな動画を含むアプリを最小化するか、PiPボタンを押すか(iOS)、またはシステムが自動的にActivityをPiPモードに移行する(Android)ことから始まります。システムウィンドウマネージャーが動画ストリームをキャプチャし、固定比率のフローティングウィンドウを作成します。ウィンドウのサイズは元の動画のアスペクト比とプラットフォームの制約に依存します:iOSではPiPウィンドウは画面幅の約1/6〜1/4を占め、Androidではモバイルデバイスの場合、幅108dp以上、高さ240dp以上です。
PiPウィンドウがアクティブなとき、アプリは3つの状態のいずれかになります:バックグラウンド(最小化)、アクティブ状態(ユーザーがアプリに戻った)、または待機状態(システムがリソース不足でPiPを一時停止した)。PiPへの移行時、アプリは不要なUI操作(アニメーション、インターフェースのレンダリング)を一時停止し、メモリを解放する必要があります。マルチタスクモードではシステムリソースがより厳しく割り当てられるためです。iOSは自動的にアプリにAVPictureInPictureControllerWillStartNotificationを送信し、AndroidはonPictureInPictureModeChangedコールバックを送信します。
PiPウィンドウには重要な制限があります:標準的なUI制御要素(一時停止ボタン、プログレスバー)を表示できません — 基本的なコントロール(再生/一時停止、閉じる、全画面に拡大)のみの最小限のシステムオーバーレイのみです。システムPiP UIはiOSでは一時停止ボタンと閉じるボタンを含み、Androidでは同じ要素に加えて追加の設定ボタンを含みます。PiP内のコンテンツとの操作(巻き戻し、字幕の選択)は不可能です — そのためにはアプリを全画面に拡大する必要があります。
iOSでは、PiPはAVKitフレームワークとAVPictureInPictureControllerクラスを介して実装されます。このAPIはiPhoneおよびiPadのiOS 14+で利用可能ですが、要件が異なります:iPadではPiPはAVPlayerLayerを介して動作し、iPhoneではAVPlayerViewControllerを介してのみ動作します。
iOSでPiPを動作させるには、いくつかの条件を満たす必要があります:アプリは動画再生にAVPlayerを使用する必要があり、オーディオセッションを.playbackまたは.playAndRecordカテゴリに設定し、アプリにはバックグラウンドオーディオのエンタイトルメント(UIBackgroundModes = audio)が必要です。これらの設定がないと、PiPは開始されません — システムはバックグラウンド移行後の正しい再生を保証できないため、PiPセッション要求を拒否します。
iOSでは、動画がアクティブに再生されており、ユーザーが設定でこの機能を無効にしていない場合、アプリを最小化するとPiPウィンドウが自動的に表示されます。ユーザーはAVPlayerViewControllerのボタンから手動で動画をPiPに最小化することもできます。iOSのPiPウィンドウのサイズは固定されており、システムによって決定されます — 開発者は変更できません。PiPウィンドウのアスペクト比は元の動画の比率に一致しますが、最大サイズはiPhoneで画面幅の1/4、iPadで1/3に制限されています。
iOSでのPiPの主な制限:PiPウィンドウ内のカスタムUIは不可、同時に1つのPiPストリームのみ、PiP動作にはアクティブなAVPlayerが必要。マルチPiP — 複数のPiPウィンドウの同時再生 — はiOSではサポートされていません。2つ目のPiPを開始しようとすると、最初のPiPは自動的に閉じられます。これはハードウェアの制限です:DMAとビデオメモリの制約のため、ビデオプロセッサは2つの独立したPiPチャンネルを同時に処理できません。
もう1つの重要な制限は、バックグラウンド再生の持続時間です。ユーザーがPiPウィンドウを操作しない場合、システムは電力節約のためにしばらくすると再生を一時停止する可能性があります。iOSでの自動PiP一時停止は、アプリがバックグラウンドタスクによるキープアライブ機構を実装していない場合、10〜15分の非アクティブ状態の後に発生します。ビデオ通話やストリームには、この制限を回避するPushKitとVoIP証明書の使用が推奨されます。
Androidでは、PiPはenterPictureInPictureModeメソッドを介してアクティブ化される組み込みのActivityモードとして実装されています。Android 8.0(API 26)以降、任意のActivityがPiPモードに入ることができ、Android 12(API 31)以降、MediaCodecを使用せずにSurfaceViewとTextureViewのPiPサポートが利用可能です。
AndroidマニフェストでPiPをサポートするには、
Androidでは、PiPウィンドウにはデフォルトでコントロール要素がありません。開発者はsetPictureInPictureParamsメソッドでRemoteActionを介してカスタムアクションを追加できます。最大3つのアクションが利用可能です(例:一時停止/再生、巻き戻し/早送り、閉じる)。各アクションはシステムPiPオーバーレイにアイコンとして表示されます。すべてのUI要素が厳密に固定されているiOSとは異なり、Androidは基本的なコントロールに対してより柔軟性を提供します。
AndroidのPiPはOSバージョンによって異なる機能を持ちます。Android 8.0〜8.1では、PiPはSurfaceViewを使用したMediaPlayerまたはMediaCodecを介して再生される動画でのみ利用可能です。Android 9以降では、PictureInPictureArgs.Builderを使用してPiPウィンドウのアスペクト比を設定できます。Android 12では、カスタムSurfaceViewとTextureViewのPiPサポート、および全画面モードとPiPモード間の改善されたトランジションが追加されました。Android 13+では、アプリに適切な権限があれば、ロック画面でもPiPウィンドウを表示できます。
| Android バージョン | PiP 機能 | API |
|---|---|---|
| 8.0–8.1 | MediaPlayer/MediaCodec の基本 PiP | 26–27 |
| 9–11 | アスペクト比設定、カスタムアクション | 28–30 |
| 12 | SurfaceView/TextureView PiP サポート | 31 |
| 13+ | ロック画面の PiP、改善されたアニメーション | 33+ |
Android PiP の主な違いはiOSに対するマルチPiP機能です。Android 12+では、アプリがサポートし、デバイスのパフォーマンスが許せば、システムは複数のPiPウィンドウを同時に表示できます。ただし実際には、マルチPiPはSoCの能力によって制限されます:ほとんどのデバイスはハードウェアデコーダの制限により1つのPiPウィンドウのみをサポートします。各PiPウィンドウには独自の動画ストリームと個別のデコードセッションが必要だからです。
最新のAPI変更を考慮して、両方のモバイルプラットフォームでのPiPの実装例を見てみましょう。
import AVKit
import AVFoundation
class VideoPlayerViewController: UIViewController {
var player: AVPlayer!
var pipController: AVPictureInPictureController?
override func viewDidLoad() {
super.viewDidLoad()
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = .resizeAspect
view.layer.addSublayer(playerLayer)
guard AVPictureInPictureController.isPictureInPictureSupported()
else { return }
pipController = AVPictureInPictureController(playerLayer: playerLayer)
pipController?.delegate = self
}
@IBAction func startPiPTapped() {
pipController?.startPictureInPicture()
}
}
extension VideoPlayerViewController: AVPictureInPictureControllerDelegate {
func pictureInPictureControllerWillStart(
_ pictureInPictureController: AVPictureInPictureController
) {
// UI要素を非表示にし、メモリを解放
}
func pictureInPictureControllerDidStop(
_ pictureInPictureController: AVPictureInPictureController
) {
// UIを復元し、レンダリングを再開
}
}
この例では、isPictureInPictureSupportedを確認した後、AVPictureInPictureControllerがplayerLayerで初期化されます(PiPはiPhone SE第1世代および十分なメモリがない一部のiPadではサポートされていません)。デリゲートはアプリにPiPの開始と終了を通知します — これらのコールバックでUI要素を非表示にし、復元する必要があります。PiPモードではアプリのインターフェースは表示されないためです。PiPに移行する際は、すべてのアニメーションを停止し、プレーヤーコントロールを非表示にし、未使用のメモリを解放して、システムによるアプリの強制アンロードを防ぐことを推奨します。
class PipVideoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupVideoPlayer()
}
private fun enterPipMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val aspectRatio = Rational(16, 9)
val pipParams = PictureInPictureParams.Builder()
.setAspectRatio(aspectRatio)
.setAutoEnterEnabled(true)
.build()
enterPictureInPictureMode(pipParams)
}
}
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration
) {
if (isInPictureInPictureMode) {
// UIを非表示にし、メディアのみにフォーカス
binding.controlsGroup.visibility = View.GONE
} else {
// UIを復元
binding.controlsGroup.visibility = View.VISIBLE
}
}
}
Kotlinの例では、PiPを設定するためにPictureInPictureParams.Builderを使用しています。setAspectRatioメソッドはPiPウィンドウのアスペクト比を設定します(一般的な動画では16:9)。setAutoEnterEnabled(true)はアプリを最小化したときに自動的にPiPに移行するようにします。onPictureInPictureModeChangedコールバックはPiPに入った時と出た時に呼び出され、ここでUI要素を非表示または表示します。SurfaceViewの動画の場合、PiPモード移行時のActivity再作成を防ぐために、マニフェストにandroid:configChanges="screenSize|smallestScreenSize"を追加して追加の設定処理が必要です。
PiPは、他のタスクに切り替えてもコンテンツが関連性を保つアプリにおいて、ユーザーエクスペリエンスを向上させる強力なツールです。ただし、PiPの実装は正当化されるべきであり、ユーザーの気を散らすものであってはなりません。
ビデオ通話と会議はPiPの主要なシナリオの1つです。Zoom、FaceTime、Google Meetでは、PiPによりユーザーは他のアプリで作業(メモの閲覧、プレゼンテーションの視聴、メールの確認)しながら相手を見ることができます。ビデオ通話のPiPには、バックグラウンドでのカメラサポートと、バックグラウンドでのオーディオキャプチャを継続するための適切なオーディオセッション設定が必要です。iOSでは、ビデオ通話はAVPlayerを使用しないため、AVPlayerLayerの代わりにAVSampleBufferDisplayLayerを使用してこれを行います。
ストリーミングサービス(YouTube、Netflix、Twitch)は、新しいコンテンツを探しながら視聴を続けるためにPiPを積極的に使用しています。YouTube PremiumはPiPを有料機能として提供し、Netflixもコンテンツライセンス制限によりPiPを特定のサブスクリプションプランに制限しています。ストリーミングアプリでPiPを実装するには、PiPモードでセキュアなパイプラインをサポートするDRMシステム(FairPlay、Widevine)との統合が必要です。
PiPはユーザーの操作が必要なインタラクティブな動画コンテンツを含むアプリには適していません:プレーヤー内テストのある教育プラットフォーム、チャット付きのゲームストリーム、動画内に商品リンクがあるショッピングアプリ。これらの場合、PiPウィンドウは追加情報を表示するには小さすぎ、インタラクティブ要素はPiP内でサポートされていません。コンテンツとの操作が必要ない受動的な視聴にのみPiPを使用することを推奨します。
音楽やポッドキャストアプリでは、PiPは過剰です — 視覚的ウィンドウなしのバックグラウンドオーディオで十分です。PiPはフローティングウィンドウでの動画レンダリングに追加のGPUリソースを消費し、バッテリー駆動時間を短縮します。コンテンツがオーディオベースの場合(音楽、ポッドキャスト、オーディオブック)— PiPなしでバックグラウンド再生を使用します。視覚的な場合は、ユーザーエクスペリエンスを向上させるためにPiPを実装します。
よくある質問
iOSのPiPには、iPhone 6s以上、iOS 14以上、およびサポート対象地域(米国、カナダ、オーストラリア、EU、ロシアなど)が必要です。アプリはオーディオセッションを.playbackカテゴリに設定し、UIBackgroundModes = audioを追加する必要があります。設定も確認してください:設定 > 一般 > ピクチャー・イン・ピクチャー。
iOSでは、PiPウィンドウのサイズは完全にシステムによって決定され、開発者が設定することはできません。Androidでは、PictureInPictureParams.BuilderのsetAspectRatioを介してアスペクト比のみを設定できますが、正確なウィンドウサイズはシステムが決定します。ユーザーはAndroid 12+でピンチ操作によりPiPウィンドウのサイズを変更できます。
はい、DRMセッションがPiPモードでセキュアなパイプラインをサポートしている場合、PiPはDRM保護コンテンツ(iOSのFairPlay、AndroidのWidevine L1)で動作します。Widevine L3は、フローティングウィンドウ内のデコード済みコンテンツのセキュリティを保証しないため、PiPをサポートしない場合があります。テスト段階でDRMとPiPの互換性を確認してください。
iOSでは — 1つのPiPウィンドウのみです。Android 12+では、理論的にはマルチPiPがサポートされていますが、実際にはほとんどのデバイスがハードウェアの制限により1つのウィンドウに制限されています。トップデバイス(Samsung Galaxy S24、Pixel 8)は2つのPiPウィンドウをサポートできますが、パフォーマンスが低下します。
はい、ライフサイクル処理は非常に重要です。iOSでは、PiPに移行する際、アプリはwillStart通知を受け取り、そこでUIを非表示にしてメモリを解放する必要があります。Androidでは、PiPへの出入りの際にonPictureInPictureModeChangedが呼び出されます。適切なライフサイクル処理がないと、システムがアプリをメモリからアンロードし、再生が中断される可能性があります。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。