如何在requestPictureInPicture中播放多个视频?

How to play Multiple Videos in requestPictureInPicture?

requestPictureInPicture 太神奇了,但它看起来只适用于 1 个视频。

如何让requestPictureInPicture播放多个视频,让我可以同时观看两个视频?

基本上这只显示一个视频:

      video
      .requestPictureInPicture()
      .catch(error => {
        console.log(error) // Error handling
      });
      video2
      .requestPictureInPicture()
      .catch(error => {
        console.log(error) // Error handling
      });

https://codepen.io/zecheesy/pen/YzwBJMR

想法:也许我们可以将两个视频放在一个 canvas 中?并让 pictureInPicture 同时播放两个视频? https://googlechrome.github.io/samples/picture-in-picture/audio-playlist

我不确定这是否可行。非常希望得到您的帮助!

关于同时打开两个 PictureInPitcure windows,the specs have a paragraph 只是为了它,他们解释说他们实际上把它留作实现细节:

Operating systems with a Picture-in-Picture API usually restrict Picture-in-Picture mode to only one window. Whether only one window is allowed in Picture-in-Picture mode will be left to the implementation and the platform. However, because of the one Picture-in-Picture window limitation, the specification assumes that a given Document can only have one Picture-in-Picture window.

What happens when there is a Picture-in-Picture request while a window is already in Picture-in-Picture will be left as an implementation detail: the current Picture-in-Picture window could be closed, the Picture-in-Picture request could be rejected or even two Picture-in-Picture windows could be created. Regardless, the User Agent will have to fire the appropriate events in order to notify the website of the Picture-in-Picture status changes.

所以我们只能说您不应该期望它同时打开两个 windows。


现在,如果您真的愿意,您确实可以在 canvas 上绘制两个视频,然后将此 canvas 传递给画中画 window,然后将其 captureStream() 管道化到第三个

这是一个概念证明:

const vids = document.querySelectorAll( "video" );
const btn = document.querySelector( "button" );

// wait for both video has their metadata
Promise.all( [ ...vids ].map( (vid) => {
  return new Promise( (res) => vid.onloadedmetadata = () => res() );
} ) )
.then( () => {
  if( !HTMLVideoElement.prototype.requestPictureInPicture ) {
    return console.error( "Your browser doesn't support the PiP API" );
  }
  btn.onclick = async (evt) => {
    const canvas = document.createElement( "canvas" );
    // both videos share the same 16/9 ratio
    // so in this case it's really easy to draw both on the same canvas
    // to make it dynamic would require more maths
    // but I'll let it to the readers
    const height = 720;
    const width = 1280;
    canvas.height = height * 2; // vertical disposition
    canvas.width = width;
    const ctx = canvas.getContext( "2d" );
    
    const video = document.createElement( "video" );
    video.srcObject = canvas.captureStream();

    let began = false; // rPiP needs video's metadata
    anim();
    await video.play();
    began = true;
    video.requestPictureInPicture();
    
    function anim() {
      ctx.drawImage( vids[ 0 ], 0, 0, width, height );
      ctx.drawImage( vids[ 1 ], 0, height, width, height  );
      // iff we are still in PiP mode
      if( !began || document.pictureInPictureElement === video ) {
        requestAnimationFrame( anim );
      }
      else {
        // kill the stream
        video.srcObject.getTracks().forEach( track => track.stop() );
      }
    }
  }
} );
video { width: 300px }
<button>enter Picture in Picture</button><br>
<video crossorigin  muted controls autoplay loop
  src="https://upload.wikimedia.org/wikipedia/commons/2/22/Volcano_Lava_Sample.webm"></video>
<video crossorigin  muted controls autoplay loop
  src="https://upload.wikimedia.org/wikipedia/commons/a/a4/BBH_gravitational_lensing_of_gw150914.webm"></video>

请注意,因为我确实将视频静音,所以以原始视频看不见的方式滚动会使它们暂停。