ピクチャ・イン・ピクチャ

W3C作業草案,

この文書の詳細情報
このバージョン:
https://www.w3.org/TR/2026/WD-picture-in-picture-20260616/
最新公開バージョン:
https://www.w3.org/TR/picture-in-picture/
編集中の草案:
https://w3c.github.io/picture-in-picture/
以前のバージョン:
履歴:
https://www.w3.org/standards/history/picture-in-picture/
フィードバック:
GitHub
編集者:
(Google LLC)
(Mozilla Foundation)
以前の編集者:
(Google LLC)
Web Platform Tests:
permissions-policy/
picture-in-picture/

概要

この仕様は、ウェブサイトが他のウィンドウの上に常に表示されるフローティングビデオウィンドウを作成できるAPIを提供します。 これにより、ユーザーは他のコンテンツサイトやデバイス上のアプリケーションを操作しながら、メディアの視聴を続けることができます。

この文書のステータス

このセクションは、発行時点でのこの文書のステータスを説明します。現行のW3C出版物一覧やこの技術レポートの最新改訂版は、W3C標準および草案インデックスで確認できます。

この仕様へのフィードバックやコメントを歓迎します。 議論にはGitHub Issuesの利用を推奨します。 または、Media Working Groupのメーリングリストpublic-media-wg@w3.orgアーカイブ)にコメントを送ることもできます。 本草案では、ワーキンググループで今後議論予定の未解決課題をいくつか取り上げています。 これらの課題の妥当性を含め、結論はまだ出ていません。

この文書はMedia Working Groupによる 勧告トラックを用いた作業草案として公開されました。 この文書はW3C勧告となる予定です。

作業草案として公開されたことはW3Cおよびそのメンバーによる支持を意味しません。

この文書は草案であり、今後いつでも更新・置換・廃止される可能性があります。 進行中の作業以外としてこの文書を引用するのは不適切です。

この文書はW3C特許ポリシーの下で運営されているグループによって作成されました。 W3Cは、グループの成果物に関連してなされた特許開示の公開リストを管理しています。 そのページには特許開示方法の案内もあります。個人が本質的請求項を含むと信じる特許の実際の知識を持つ場合は、 W3C特許ポリシー第6節に従って情報開示しなければなりません。

この文書は2025年8月18日版W3Cプロセス文書に従い管理されています。

1. 導入

このセクションは規範的ではありません。

多くのユーザーは、他のコンテンツやサイト、またはデバイス上のアプリケーションを操作している間も、メディアの視聴を続けたいと考えています。このような活動のための一般的なUI手段が「ピクチャ・イン・ピクチャ(PiP)」です。これは、ビデオが他のウィンドウの上に常に表示される独立した小型ウィンドウ内に表示されるものです。このウィンドウはユーザーエージェントが表示されていなくても画面上に残ります。ピクチャ・イン・ピクチャは、デスクトップやモバイルOSにおける一般的なプラットフォーム機能です。

この仕様は HTMLVideoElement を拡張し、 ウェブサイトが以下のプロパティ群を通じてこの動作を開始・制御できるようにします:

2.

2.1. カスタムピクチャ・イン・ピクチャボタンの追加

<video id="video" src="https://example.com/file.mp4"></video>

<button id="togglePipButton"></button>

<script>
  const video = document.getElementById("video");
  const togglePipButton = document.getElementById("togglePipButton");

  // ピクチャ・イン・ピクチャがサポートされていない、または無効の場合はボタンを非表示にします。
  togglePipButton.hidden =
    !document.pictureInPictureEnabled || video.disablePictureInPicture;

  togglePipButton.addEventListener("click", async () => {
    // まだピクチャ・イン・ピクチャ要素がなければリクエストし、既にあれば終了します。
    try {
      if (document.pictureInPictureElement) {
        await document.exitPictureInPicture();
      } else {
        await video.requestPictureInPicture();
      }
    } catch (err) {
      // ビデオのピクチャ・イン・ピクチャモード開始/終了に失敗しました。
    }
  });
</script>

2.2. ビデオのピクチャ・イン・ピクチャ変更の監視

<video id="video" src="https://example.com/file.mp4"></video>

<script>
  const video = document.getElementById("video");

  video.addEventListener("enterpictureinpicture", (event) => {
    // ビデオがピクチャ・イン・ピクチャモードに入りました。
    const pipWindow = event.pictureInPictureWindow;
    console.log(`ピクチャ・イン・ピクチャウィンドウの幅: ${pipWindow.width}`);
    console.log(`ピクチャ・イン・ピクチャウィンドウの高さ: ${pipWindow.height}`);
  });

  video.addEventListener("leavepictureinpicture", () => {
    // ビデオがピクチャ・イン・ピクチャモードから離脱しました。
  });
</script>

2.3. ピクチャ・イン・ピクチャウィンドウサイズ変更に応じたビデオサイズの更新

<video id="video" src="https://example.com/file.mp4"></video>

<button id="pipButton"></button>

<script>
  const video = document.getElementById("video");
  const pipButton = document.getElementById("pipButton");

  pipButton.addEventListener("click", async () => {
    try {
      await video.requestPictureInPicture();
    } catch (error) {
      // ビデオのピクチャ・イン・ピクチャモード開始に失敗しました。
    }
  });

  video.addEventListener("enterpictureinpicture", (event) => {
    // ビデオがピクチャ・イン・ピクチャモードに入りました。
    const pipWindow = event.pictureInPictureWindow;
    updateVideoSize(pipWindow.width, pipWindow.height);
    pipWindow.addEventListener("resize", onPipWindowResize);
  });

  video.addEventListener("leavepictureinpicture", (event) => {
    // ビデオがピクチャ・イン・ピクチャモードから離脱しました。
    const pipWindow = event.pictureInPictureWindow;
    pipWindow.removeEventListener("resize", onPipWindowResize);
  });

  function onPipWindowResize(event) {
    // ピクチャ・イン・ピクチャウィンドウがリサイズされました。
    const { width, height } = event.target;
    updateVideoSize(width, height);
  }

  function updateVideoSize(width, height) {
    // TODO: pipウィンドウの幅・高さに基づいてビデオサイズを更新する。
  }
</script>

3. 概念

3.1. 定義

Picture-in-Picture ウィンドウとは、 video 要素を表示するウィンドウである。

DocumentOrShadowRoot は次を持つ:

  1. Picture-in-Picture 要素。これは Element または null であり、初期値は null である。

traversable navigable は次を持つ:

  1. picture-in-picture 並列キュー。これは 並列キューであり、 新しい並列キューを開始することによって作成される。

ユーザー エージェントは次を持つ:

  1. 0 個以上のオリジンからなる アクティブな Picture-in-Picture セッションの開始元 リスト。これは初期状態では空である。

    注:ユーザーエージェントが 複数の Picture-in-Picture ウィンドウをサポートする場合、このリストは重複を許す。

あるオリジンは、 アクティブな Picture-in-Picture セッションの開始元内のいずれかのオリジンが、そのオリジンと 同一 origin-domainである場合、アクティブな Picture-in-Picture セッションを持つという。

3.2. Picture-in-Picture

動画フレームはページ内と Picture-in-Picture ウィンドウ内で同時にレンダリングされないことが推奨されるが、同時にレンダリングされる場合は、 同期を保たなければならない。

動画が Picture-in-Picture モードで再生される場合、状態は インラインで再生されているかのように遷移するべきである。つまり、イベントは同じ 時点で発火するべきであり、メソッド呼び出しは同じ挙動を持つべきである、などである。ただし、 ユーザーエージェントは、video 要素が Picture-in-Picture と互換性がないとみなされる 状態に入ったとき、Picture-in-Picture から遷移してもよい。

video に適用されるスタイル(opacity、visibility、transform など)は、 Picture-in-Picture ウィンドウ内では適用してはならない。そのアスペクト比は 動画サイズに基づく。

Picture-in-Picture ウィンドウには最大サイズと 最小サイズがあることも推奨される。たとえば、画面の一方の寸法の 4 分の 1 から 半分の間に制限され得る。

DocumentOrShadowRootPicture-in-Picture 要素が設定されている場合、 Picture-in-Picture ウィンドウは、たとえ DocumentOrShadowRoot関連するグローバルオブジェクト関連付けられた Document可視性状態が "hidden" であっても、表示されていなければならない。 ユーザーエージェントは、ユーザーが Picture-in-Picture ウィンドウを手動で閉じる方法を 提供するべきである。

3.3. ピクチャ・イン・ピクチャの終了

Picture-in-Picture 終了アルゴリズムが呼び出されたとき、 ユーザーエージェントは以下の手順を実行しなければならない:

  1. pictureInPictureElementnull である場合、InvalidStateError を投げ、 これらの手順を中止する。

  2. pictureInPictureElement に関連付けられたPicture-in-Picture ウィンドウで、ウィンドウを閉じるアルゴリズムを実行する。

  3. タスクをキューに入れvideo において leavepictureinpicture という名前のイベントを発火する。 その際、PictureInPictureEvent を使用し、その bubbles 属性を true に初期化し、その pictureInPictureWindow 属性を、pictureInPictureElement に関連付けられたPicture-in-Picture ウィンドウに初期化する。

  4. pictureInPictureElement の設定を解除する。

  5. 関連設定オブジェクトオリジンに一致する項目を 1 つ、 アクティブな Picture-in-Picture セッションの開始元から削除する。

Picture-in-Picture 終了アルゴリズムが呼び出されたときに、動画の再生状態が変更されることは推奨されない。 ウェブサイトによって開始された場合、その体験はウェブサイトが制御するべきである。 ただし、ユーザーエージェントは、動画の再生状態を変更する Picture-in-Picture ウィンドウのコントロール(例: 一時停止)を公開してもよい。

文書のアンロード時クリーンアップ手順の 1 つとして、Picture-in-Picture 終了アルゴリズムを実行する。

3.4. ピクチャ・イン・ピクチャの無効化

一部のページは、video 要素に対して Picture-in-Picture モードを無効にしたい場合がある。たとえば、 場合によっては、ユーザーエージェントが Picture-in-Picture コンテキストメニューを提案することを防ぎたい場合がある。 これらのユースケースをサポートするため、新しい disablePictureInPicture 属性が、video 要素の内容属性のリストに追加される。

disablePictureInPicture IDL 属性は、同じ名前の内容 属性を反映しなければならない。

disablePictureInPicture 属性が video 要素に存在する場合、 ユーザーエージェントは、その video 要素が Picture-in-Picture モードで再生されること、またはそれを行うための UI を提示することを防止してもよい。

disablePictureInPicture 属性が video 要素に追加されたとき、 ユーザーエージェントはこれらの手順を実行してもよい:

  1. requestPictureInPicture() メソッドによって返された保留中の promise を、InvalidStateError で拒否する。

  2. videopictureInPictureElement である場合、Picture-in-Picture 終了アルゴリズムを実行する。

3.5. フルスクリーンとの相互作用

pictureInPictureElementfullscreen flagが設定されたとき、 Picture-in-Picture 終了アルゴリズムを実行することが推奨される。

3.6. ページの可視性との連携

ピクチャインピクチャウィンドウの可視性は、システム可視状態トラバーサブル・ナビゲーブルで変更されたかどうかを 判定するためにユーザーエージェントが考慮してはなりません。

3.7. ピクチャー・イン・ピクチャーウィンドウは1つのみ

ピクチャー・イン・ピクチャーAPIを持つオペレーティングシステムは、通常ピクチャー・イン・ピクチャーモードを一つのウィンドウに制限します。ピクチャー・イン・ピクチャーモードで一つのウィンドウのみ許可されるかどうかは、実装とプラットフォームに委ねられます。しかし、ピクチャー・イン・ピクチャーウィンドウが一つしか持てないという制限があるため、この仕様は一つのDocument でピクチャー・イン・ピクチャーウィンドウは一つだけであると仮定します。

すでにウィンドウがピクチャー・イン・ピクチャー状態のときに新たなピクチャー・イン・ピクチャーのリクエストが来た場合にどうするかは実装依存です。現在のピクチャー・イン・ピクチャーウィンドウを閉じる、リクエストを拒否する、あるいは2つのピクチャー・イン・ピクチャーウィンドウを作る、といった挙動になり得ます。いずれにしても、ユーザーエージェントはウェブサイトにピクチャー・イン・ピクチャー状態の変化を通知するために、適切なイベントを発火しなければなりません。

4. API

4.1. HTMLVideoElementへの拡張

partial interface HTMLVideoElement {
  [NewObject] Promise<PictureInPictureWindow> requestPictureInPicture();

  attribute EventHandler onenterpictureinpicture;
  attribute EventHandler onleavepictureinpicture;

  [CEReactions] attribute boolean disablePictureInPicture;
};

requestPictureInPicture() メソッドの手順 Picture-in-Picture を要求する は次のとおり:

  1. Picture-in-Picture サポートfalse の場合、 NotSupportedError DOMException拒否された promiseを返す。

  2. docthisノード文書とする。

  3. doc"picture-in-picture" という名前の ポリシー制御機能使用することを許可されていない場合、NotAllowedError DOMException拒否された promiseを返す。

  4. thisreadyState 属性が HAVE_NOTHING である場合、InvalidStateError DOMException拒否された promiseを返す。

  5. this に 映像トラックがない場合、InvalidStateError DOMException拒否された promiseを返す。

  6. thisdisablePictureInPicture が true である場合、ユーザーエージェントは InvalidStateError DOMException拒否された promiseを返してもよい。

  7. docPicture-in-Picture 要素null である場合:

    1. this関連するグローバルオブジェクト一過性のアクティベーションを持たない場合、NotAllowedError DOMException拒否された promiseを返す。

    2. ユーザーアクティベーションを消費する。対象は this関連するグローバルオブジェクトである。

  8. thisdocPicture-in-Picture 要素である場合:

    1. docPicture-in-Picture 要素に関連付けられた Picture-in-Picture ウィンドウ解決された promiseを返す。

  9. globalthis関連するグローバルオブジェクトとする。

  10. p を、this関連するレルム内で作成された 新しい promiseとする。

  11. p を返し、docpicture-in-picture 並列キューに 以下の手順をエンキューする

    1. thisdocPicture-in-Picture 要素である場合:

      1. global を対象として、メディア要素イベントタスクソース上に グローバルタスクをキューに入れthis に関連付けられた Picture-in-Picture ウィンドウp解決する。

      2. これらの手順を中止する。

    2. Picture-in-Picture ウィンドウthis に関連付けることを試みる。

    3. 直前の手順が失敗した場合:

      1. global を対象として、メディア要素イベントタスク ソース上にグローバルタスクをキューに入れInvalidStateError DOMExceptionp拒否する。

      2. これらの手順を中止する。

    4. pipWindow を、this に関連付けられたPicture-in-Picture ウィンドウを表す、 PictureInPictureWindow の新しいインスタンスとする。

    5. global を対象として、メディア要素イベントタスクソース上に グローバルタスクをキューに入れ、 以下の手順を実行する:

      1. pictureInPictureElementnull でない場合、Picture-in-Picture 終了 アルゴリズムを実行する。

      2. docPicture-in-Picture 要素this に設定する。

      3. 関連設定オブジェクトオリジンを、アクティブな Picture-in-Picture セッションの開始元追加する

      4. thisfullscreenElementである場合、 fullscreen を終了する。

      5. this において、 enterpictureinpicture という名前のイベントを発火する。 その際、PictureInPictureEvent を使用し、その bubbles 属性を true に初期化し、その pictureInPictureWindow 属性を Picture-in-Picture ウィンドウに初期化する。

      6. pipWindowp解決する。

4.2. Documentへの拡張

partial interface Document {
  readonly attribute boolean pictureInPictureEnabled;

  [NewObject] Promise<undefined> exitPictureInPicture();
};

pictureInPictureEnabled 属性の取得子は、Picture-in-Picture サポートtrue であり、かつ this が 属性名 picture-in-picture によって示される機能を 使用することを許可されている場合は true を返し、 そうでなければ false を返さなければならない。

Picture-in-Picture サポートは、それを無効にするユーザー設定またはプラットフォーム上の制限がある場合、 false である。そうでなければ true である。

exitPictureInPicture() メソッドは、呼び出されたとき、 新しい promise promise を返し、以下の手順を並列に実行しなければならない:

  1. Picture-in-Picture 終了アルゴリズムを実行する。

  2. 直前の手順が例外を投げた場合、その例外で promise を拒否し、 これらの手順を中止する。

  3. promise解決する。

4.3. DocumentOrShadowRootへの拡張

partial interface mixin DocumentOrShadowRoot {
  readonly attribute Element? pictureInPictureElement;
};

pictureInPictureElement 属性の取得子は、これらの手順を実行しなければならない:

  1. thisシャドウルートであり、そのホスト接続されていない場合、null を返してこれらの手順を中止する。

  2. candidate を、Picture-in-Picture 要素this に対して リターゲットした結果とする。

  3. candidatethis が同じツリー内にある場合、 candidate を返してこれらの手順を中止する。

  4. null を返す。

4.4. インターフェース PictureInPictureWindow

[Exposed=Window]
interface PictureInPictureWindow : EventTarget {
  readonly attribute long width;
  readonly attribute long height;

  attribute EventHandler onresize;
};

PictureInPictureWindow インスタンスは、HTMLVideoElement に関連付けられたPicture-in-Picture ウィンドウを表す。 インスタンス化されたとき、 PictureInPictureWindow のインスタンスは、その stateopened に設定される。

PictureInPictureWindow のインスタンスで ウィンドウを閉じる アルゴリズムが呼び出されたとき、その stateclosed に設定される。

width 属性は、stateopened である場合、 pictureInPictureElement に関連付けられたPicture-in-Picture ウィンドウCSS ピクセル単位の幅を 返さなければならない。そうでなければ、0 を返さなければならない。

height 属性は、stateopened である場合、 pictureInPictureElement に関連付けられたPicture-in-Picture ウィンドウCSS ピクセル単位の高さを 返さなければならない。そうでなければ、0 を返さなければならない。

Picture-in-Picture ウィンドウ pipWindow のサイズが変化したとき、 ユーザーエージェントは タスクをキューに入れて、pipWindow において resize という名前のイベントを発火しなければならない。

4.5. イベントタイプ

[Exposed=Window]
interface PictureInPictureEvent : Event {
    constructor(DOMString type, PictureInPictureEventInit eventInitDict);
    [SameObject] readonly attribute PictureInPictureWindow pictureInPictureWindow;
};

dictionary PictureInPictureEventInit : EventInit {
    required PictureInPictureWindow pictureInPictureWindow;
};
enterpictureinpicture

HTMLVideoElement がピクチャ・イン・ピクチャに入ったときに発火されます。

leavepictureinpicture

HTMLVideoElement がピクチャ・イン・ピクチャモードから離脱したときに発火されます。

resize

PictureInPictureWindow のサイズが変更されたときに発火されます。

4.6. タスクソース

本仕様でキューイングされるすべてのタスクのタスクソースは、 当該ビデオ要素のメディア要素イベントタスクソースです。

4.7. CSS疑似クラス

:picture-in-picture 疑似クラスは ピクチャ・イン・ピクチャ要素に一致しなければなりません。これはpictureInPictureElement とは異なり、 シャドウホストチェーンには適用されません。

5. セキュリティに関する考慮事項

このセクションは規範的ではありません。

なりすまし等による悪用を防ぐため、APIはHTMLVideoElementのみに適用されます。 ピクチャ・イン・ピクチャウィンドウへのユーザー操作は意図的に制限されており、影響はピクチャ・イン・ピクチャウィンドウ自身または再生中のメディアのみに限定されます。

5.1. セキュアコンテキスト

このAPIは[SECURE-CONTEXTS]に限定されていません。なぜなら、ユーザーエージェントが通常すべてのメディアに対してネイティブに提供している機能をウェブアプリケーションへ公開するためであり、ブラウジングコンテキストに関係なく利用可能です。

5.2. Permissions Policy

この仕様は、ポリシー制御機能として "picture-in-picture" という名前の機能を定義する。これは、Picture-in-Picture を要求するSecurityError を返すかどうか、および pictureInPictureEnabledtruefalse かを制御する。

この機能のデフォルト許可リスト*です。

6. 謝辞

Jennifer Apacible、Zouhir Chahoud、Marcos Cáceres、Philip Jägenstedt、 Jeremy Jones、Chris Needham、Jer Noble、Justin Uberti、Yoav Weiss、Eckhart Wörnerの皆様には、この文書へのご貢献に感謝いたします。

適合性

文書の慣例

適合性要件は、記述的な断定とRFC 2119用語の組み合わせで表現されます。 この文書の規範部分における “MUST”、 “MUST NOT”、 “REQUIRED”、 “SHALL”、 “SHALL NOT”、 “SHOULD”、 “SHOULD NOT”、 “RECOMMENDED”、 “MAY”、 “OPTIONAL” というキーワードは、 RFC 2119で記載された通りに解釈されます。 ただし、可読性のため本仕様書ではこれらの語句はすべて大文字にはしていません。

この仕様のすべてのテキストは、明示的に非規範的と記されたセクション、例、注記を除き、規範的です。[RFC2119]

この仕様における例は「例えば」という語句で導入されるか、または class="example"で規範的な本文と区別され、次のように表示されます:

これは参考例(インフォーマティブ)です。

参考注記は「注」と始まり、 class="note"で規範的な本文と区別され、次のように表示されます:

注:これは参考注記です。

適合アルゴリズム

アルゴリズムの一部として命令形で記述された要件(例:「先頭の空白文字をすべて除去する」や「falseを返してこれらの手順を中断する」など)は、 アルゴリズム導入部分で用いられているキーワード("must"、"should"、"may"等)の意味で解釈されます。

アルゴリズムや特定の手順として記述された適合性要件は、最終的な結果が同等であれば、どのような方法で実装しても構いません。 特に、この仕様で定義されたアルゴリズムは理解しやすさを重視しており、パフォーマンスを意図したものではありません。 実装者は最適化を推奨します。

索引

本仕様で定義されている用語

参照によって定義されている用語

参考文献

規範参考文献

[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad。CSS 値と単位モジュール レベル4。2024年3月12日。WD。URL: https://www.w3.org/TR/css-values-4/
[DOM]
Anne van Kesteren。DOM標準。リビングスタンダード。URL: https://dom.spec.whatwg.org/
[FULLSCREEN]
Philip Jägenstedt。Fullscreen API 標準。リビングスタンダード。URL: https://fullscreen.spec.whatwg.org/
[HTML]
Anne van Kesteren;他。HTML標準。リビングスタンダード。URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola。Infra 標準。リビングスタンダード。URL: https://infra.spec.whatwg.org/
[PERMISSIONS-POLICY-1]
Ian Clelland。Permissions Policy。2025年10月6日。WD。URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
S. Bradner。RFCで要求レベルを示すための重要語。1997年3月。ベストカレントプラクティス。URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad;Tab Atkins Jr.。セレクター レベル4。2026年1月22日。WD。URL: https://www.w3.org/TR/selectors-4/
[WEBIDL]
Edgar Chen;Timothy Gu。Web IDL 標準。リビングスタンダード。URL: https://webidl.spec.whatwg.org/

参考情報文献

[SECURE-CONTEXTS]
Mike West。セキュアコンテキスト。2023年11月10日。CRD。URL: https://www.w3.org/TR/secure-contexts/

IDL索引

partial interface HTMLVideoElement {
  [NewObject] Promise<PictureInPictureWindow> requestPictureInPicture();

  attribute EventHandler onenterpictureinpicture;
  attribute EventHandler onleavepictureinpicture;

  [CEReactions] attribute boolean disablePictureInPicture;
};

partial interface Document {
  readonly attribute boolean pictureInPictureEnabled;

  [NewObject] Promise<undefined> exitPictureInPicture();
};

partial interface mixin DocumentOrShadowRoot {
  readonly attribute Element? pictureInPictureElement;
};

[Exposed=Window]
interface PictureInPictureWindow : EventTarget {
  readonly attribute long width;
  readonly attribute long height;

  attribute EventHandler onresize;
};

[Exposed=Window]
interface PictureInPictureEvent : Event {
    constructor(DOMString type, PictureInPictureEventInit eventInitDict);
    [SameObject] readonly attribute PictureInPictureWindow pictureInPictureWindow;
};

dictionary PictureInPictureEventInit : EventInit {
    required PictureInPictureWindow pictureInPictureWindow;
};