Picture-in-Picture API と、 webkitPresentationMode の違いについて調べてみた


これは何?

safari で、ビデオの Picture in Picture をするのに、2つのAPI

が利用できるので、その違いについて調べてみた。

とりま使い方

Picture-in-Picture API

ボタンクリックに応じて  toggle するようなケースだと、以下のようなスニペットになる。

if (document.pictureInPictureEnabled) {
  if (document.pictureInPictureElement) {
    document.exitPictureInPicture();
  } else {
    videoEl.requestPictureInPicture();
  }
}
  • document.pictureInPictureEnabled
    • Picture-in-Picture APIが使えるかどうかを返す boolean
  • document.pictureInPictreElement
    • PinP になっている要素があれば true
  • [video element].requestPictureInPicture()
    • 該当のビデオ要素を P2P 表示する 
  • document.exitPictureInPicture()
    • P2P表示の解除

あとイベントとしてはビデオ要素に対し

  • enterpictureinpicture
  • leavepictureinpicture

を、それぞれ PinP になったとき/解除されたときに発火してくれる

webkitPresentationMode

PresentationMode では、 inline, picture-in-picture, fullscreen と 3 つの表示モードを切り替えられる。スニペットで書くと以下のような感じ

if( 
    videoEl.webkitSupportsPresentationMode && 
    typeof videoEl.webkitSetPresentationMode === "function"
  ) {
  btnInline.onclick = () => {
    videoEl.webkitSetPresentationMode("inline")
  }
  btnPinP.onclick = () => {
    videoEl.webkitSetPresentationMode("picture-in-picture")
  }
  btnFullscreen.onclick = () => {
    videoEl.webkitSetPresentationMode("fullscreen")
  }
}

全て video要素に対する API となっており、

  • webkitSupportsPresentationMode
    • presentation mode に対応しているかを返す boolean
  • webkitSetPresentationMode()
    • ビデオ要素に対し、presentation mode を設定する。指定できる値は inline, picture-in-picture, fullscreen

なので、 webkitEnterFullscreenPicture-in-Picture API をがっちゃんこしたような仕様となっている。

イベントに関してはモードが変化した際

  • webkitpresentationmodechange

を発火してくれるので、この中で、 webkitPresentationMode を参照してモードを判定する。スニペットで書くと、

videoEl.onwebkitpresentationmodechanged = () => {
 console.log( videoEl.webkitPresentationMode )
 // `inline` or `picture-in-picture` or `fullscreen`
}

といった感じ

違い

基本的な動作は一緒だが、以下の違いがある

  • 対応する iOS のバージョンが違う
    • Picture-in-Picture API の対応は比較的新しく、 MDN によると Mobile safari では、 13.4 以降。一方 webkitPresentationMode9.0 以降
  • fullscreen にも対応
    • 仕様の紹介のところで書いたように、 picture-in-picture 以外にも fullscreen に対応している。もちろん、 fullscreen 用途であれば webkitEnterFullscreen を使えば良いが、 webkitpresentationmodechanged で、フルスクリーンが解除されたことをイベント検知できるのは嬉しいところ( iPhone safari だと、 現状(iOS15) W3C Fullscreen API に対応していないし。あと、 webkitEnterFullscreen() を使った場合も、上のイベントは発火してくれる)
  • iOS simulatorで Picture-in-Picture API はオフになっている
    • iOS simulator だと、 document.pictureInPictureEnabled が false を返し、この API を動かすことはできない。一方、 webkitPresentationMode であれば、メソッドを呼ぶことはできる(ただし、simulator の safari が固まってしまうので、実質的には使えない

てなところ。