ピクチャー イン ピクチャーで動画を視聴する

François Beaufort
François Beaufort

ピクチャー イン ピクチャー(PIP)を使用すると、フローティング ウィンドウで動画を視聴できます (常に他のウィンドウの上に重ねて)表示するので、生徒は自分の状態を 他のサイトやアプリを操作している間に視聴中に コンテンツを見ている人がいるかもしれません

Picture-in-Picture Web API を使用すると、 ウェブサイトの動画要素のピクチャー イン ピクチャー。まずは 公式のピクチャー イン ピクチャー サンプルをご覧ください。

背景

2016 年 9 月、Safari には WebKit API を介したピクチャー イン ピクチャーのサポートが追加されました ダウンロードします。6 か月後、Chrome では Android O のリリースにより、モバイル デバイスで ネイティブ Android API を使用します。6 か月後、Google はGoogle が Safari と互換性のある機能である Web API を標準化し、 ピクチャー イン ピクチャーに関するすべてのエクスペリエンスを作成、管理できます。 それがここにあります。

コードを開始する

ピクチャー イン ピクチャーに切り替えます

まずは、動画要素とユーザーが操作する方法から始めましょう。 追加することをおすすめします

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

ピクチャー イン ピクチャーのリクエストはユーザー操作への応答でのみリクエストし、 videoElement.play() から返される Promise。これは、Promise は未処理であるため、 ただし、ユーザー操作は伝播されます。代わりに、requestPictureInPicture() を 次のように、pipButtonElement でクリック ハンドラを実行します。お客様の責任 2 回クリックした場合の影響を 受け取れるようにします

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  await videoElement.requestPictureInPicture();

  pipButtonElement.disabled = false;
});

Promise が解決されると、Chrome は動画を小さなウィンドウに縮小して表示できるようにします。 ユーザーは他のウィンドウ上を移動したり位置を移動したりできます。

これで完了です。パフォーマンスは良好です。読むのをやめると、ご自分の貴重な できます。残念なことに、常にそうとは限りません。Promise は、いかなるものについても拒否する場合があります。 理由は次のとおりです。

  • ピクチャー イン ピクチャーはシステムでサポートされていません。
  • ドキュメントでは、制約が厳しいため、ピクチャー イン ピクチャーの使用が許可されていません 権限ポリシーをご覧ください。
  • 動画のメタデータがまだ読み込まれていません(videoElement.readyState === 0)。
  • 動画ファイルは音声のみです。
  • 新しい disablePictureInPicture 属性は動画要素に存在します。
  • 呼び出しがユーザー ジェスチャーのイベント ハンドラで行われていない(ボタンのクリックなど)。 Chrome 74 以降では、これは要素がない場合にのみ該当します。 すでにピクチャー イン ピクチャーです。

以下の機能サポートのセクションでは、以下に基づいてボタンを有効または無効にする方法を示しています。 制限します。

これらの潜在的なエラーをキャプチャする try...catch ブロックを追加して、 状況を把握できるようにします。

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  try {
    await videoElement.requestPictureInPicture();
  } catch (error) {
    // TODO: Show error message to user.
  } finally {
    pipButtonElement.disabled = false;
  }
});

ピクチャー イン ピクチャーでも動画要素でも、動画要素の動作は イベントが発生し、メソッドの呼び出しが機能します。クラウド内の状態の変化を反映し、 ピクチャー イン ピクチャー ウィンドウ(再生、一時停止、移動など)に加え、 JavaScript でプログラムによって状態を変更できます。

ピクチャー イン ピクチャーを終了

では、ピクチャー イン ピクチャーの開始と終了をボタンで切り替えてみましょう。水 まず、読み取り専用オブジェクト document.pictureInPictureElement が 動画要素ですそうでない場合は、 上記のようにピクチャー イン ピクチャー。お持ちでない場合は、お電話で退出をお願いします。 document.exitPictureInPicture(): 動画が再び表示されます。 クリックします。このメソッドは Promise も返します。

    ...
    try {
      if (videoElement !== document.pictureInPictureElement) {
        await videoElement.requestPictureInPicture();
      } else {
        await document.exitPictureInPicture();
      }
    }
    ...

ピクチャー イン ピクチャー イベントをリッスンする

オペレーティング システムでは通常、ピクチャー イン ピクチャーのウィンドウを 1 つのウィンドウに制限しているため、 Chrome の実装はこのパターンに沿っています。つまり、ユーザーはプレイできるのは 一度に 1 つのピクチャー イン ピクチャー動画を作成する。ユーザーがゲームをやめるまでに ユーザーがリクエストしなかったときにピクチャー イン ピクチャーで通知します。

新しい enterpictureinpicture イベント ハンドラと leavepictureinpicture イベント ハンドラを使用すると、 ユーザーに合わせた エクスペリエンスを提供しますインターネットの閲覧から ライブ配信のチャットを表示できます。

videoElement.addEventListener('enterpictureinpicture', function (event) {
  // Video entered Picture-in-Picture.
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  // Video left Picture-in-Picture.
  // User may have played a Picture-in-Picture video from a different page.
});

ピクチャー イン ピクチャー ウィンドウをカスタマイズする

Chrome 74 では、 Media Session API を使用してコントロールできるピクチャー イン ピクチャー ウィンドウ。

ピクチャー イン ピクチャー ウィンドウのメディア再生コントロール
図 1: ピクチャー イン ピクチャー ウィンドウのメディア再生コントロール
で確認できます。

デフォルトでは、再生/一時停止ボタンは常にピクチャー イン ピクチャーに表示されます。 動画が MediaStream オブジェクト(getUserMedia()getDisplayMedia()canvas.captureStream() など)、または動画に MediaSource がある 再生時間が +Infinity に設定されています(ライブフィードなど)。再生/一時停止ボタンが 常に表示される場合は、両方の「Play」に対してメディア セッション アクション ハンドラを設定してください。および 「一時停止」使用できます。

// Show a play/pause button in the Picture-in-Picture window
navigator.mediaSession.setActionHandler('play', function () {
  // User clicked "Play" button.
});
navigator.mediaSession.setActionHandler('pause', function () {
  // User clicked "Pause" button.
});

「前の曲」を表示していますと「次のトラック」ウィンドウ コントロールも同様で、設定 そうしたアプリのメディア セッション アクション ハンドラが、オブジェクトをピクチャー イン ピクチャーで表示します。 これらのアクションに対処できるようになります。

navigator.mediaSession.setActionHandler('previoustrack', function () {
  // User clicked "Previous Track" button.
});

navigator.mediaSession.setActionHandler('nexttrack', function () {
  // User clicked "Next Track" button.
});

実際の動作を確認するには、公式のメディア セッション サンプルをご覧ください。

ピクチャー イン ピクチャーのウィンドウ サイズを取得する

動画の出入りに合わせて画質を調整するには ピクチャー イン ピクチャーでは、ピクチャー イン ピクチャーのウィンドウ サイズを把握し、 ユーザーが手動でウィンドウのサイズを変更したときに通知を受け取れます。

以下の例は、広告スペースの幅と高さを取得する方法を示しています。 作成時またはサイズ変更時のピクチャー イン ピクチャー ウィンドウ。

let pipWindow;

videoElement.addEventListener('enterpictureinpicture', function (event) {
  pipWindow = event.pictureInPictureWindow;
  console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`);
  pipWindow.addEventListener('resize', onPipWindowResize);
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  pipWindow.removeEventListener('resize', onPipWindowResize);
});

function onPipWindowResize(event) {
  console.log(
    `> Window size changed to ${pipWindow.width}x${pipWindow.height}`
  );
  // TODO: Change video quality based on Picture-in-Picture window size.
}

小さな変更を行うたびに、サイズ変更イベントに直接フックしないことをおすすめします。 に設定すると、個別のイベントが発生し、 サイズ変更のたびにコストの高いオペレーションを実行すると、パフォーマンスの問題が発生します。イン 言い換えると、サイズ変更操作により、イベントが繰り返し発生して、 迅速にデプロイできます。一般的な手法として、スロットリングや デバウンスを使用してこの問題に対処します。

機能のサポート

Picture-in-Picture Web API はサポートされていない場合があるため、この API 段階的な機能強化が実現しますサポートされている場合でも、 ユーザーによって無効にされた、または権限ポリシーによって無効にされた。幸いなことに、 新しいブール値 document.pictureInPictureEnabled を使用してこれを決定します。

if (!('pictureInPictureEnabled' in document)) {
  console.log('The Picture-in-Picture Web API is not available.');
} else if (!document.pictureInPictureEnabled) {
  console.log('The Picture-in-Picture Web API is disabled.');
}

動画の特定のボタン要素に適用する場合は、次のようにします。 ピクチャー イン ピクチャーのボタンの公開設定を管理します。

if ('pictureInPictureEnabled' in document) {
  // Set button ability depending on whether Picture-in-Picture can be used.
  setPipButton();
  videoElement.addEventListener('loadedmetadata', setPipButton);
  videoElement.addEventListener('emptied', setPipButton);
} else {
  // Hide button if Picture-in-Picture is not supported.
  pipButtonElement.hidden = true;
}

function setPipButton() {
  pipButtonElement.disabled =
    videoElement.readyState === 0 ||
    !document.pictureInPictureEnabled ||
    videoElement.disablePictureInPicture;
}

MediaStream 動画サポート

MediaStream オブジェクト(getUserMedia()getDisplayMedia()canvas.captureStream() など)は、Chrome 71 のピクチャー イン ピクチャーにも対応しています。この ユーザーのウェブカメラを含むピクチャー イン ピクチャー ウィンドウを表示できます。 またはキャンバス要素を含めることができますなお、 動画要素を DOM に接続しなくても ピクチャー イン ピクチャーで管理できます。

ピクチャー イン ピクチャー ウィンドウにユーザーのウェブカメラを表示する

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

ディスプレイをピクチャー イン ピクチャー ウィンドウに表示する

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getDisplayMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

ピクチャー イン ピクチャー ウィンドウにキャンバス要素を表示する

const canvas = document.createElement('canvas');
// Draw something to canvas.
canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);

const video = document.createElement('video');
video.muted = true;
video.srcObject = canvas.captureStream();
video.play();

// Later on, video.requestPictureInPicture();

canvas.captureStream()Media Session API を組み合わせると、次のことができます。 オーディオ再生リストのウィンドウを作成できます(Chrome 74)詳しくは、 オーディオ プレイリストのサンプル

ピクチャー イン ピクチャー ウィンドウに表示された音声再生リスト
図 2.ピクチャー イン ピクチャー ウィンドウに表示された音声再生リスト
で確認できます。

サンプル、デモ、Codelab

ピクチャー イン ピクチャーを試すには、公式のピクチャー イン ピクチャーのサンプルをご覧ください ウェブ API。

その後、デモと Codelab について説明します。

次のステップ

まず、実装ステータスのページを確認して、 API は現在、Chrome とその他のブラウザに実装されています。

今後リリースされる内容は次のとおりです。

ブラウザ サポート

Picture-in-Picture Web API は、Chrome、Edge、Opera、Safari でサポートされています。 詳しくは、MDN をご覧ください。

リソース

Mounir Lamouri と Jennifer Apacible の協力により、 ピクチャー イン ピクチャー、こちらの記事のヘルプをご覧ください。本当にありがとう 標準化の取り組みに関与します。