【问题标题】:How to play Multiple Videos in requestPictureInPicture?如何在 requestPictureInPicture 中播放多个视频?
【发布时间】:2020-11-12 13:36:41
【问题描述】:

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

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

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

【问题讨论】:

    标签: javascript video html5-canvas html5-video picture-in-picture


    【解决方案1】:

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

    具有画中画 API 的操作系统通常会将画中画模式限制为仅一个窗口。画中画模式下是否只允许一个窗口由实现和平台决定。但是,由于一个画中画窗口的限制,规范假设给定的文档只能有一个画中画窗口。

    当有一个画中画请求而窗口已经在画中画中时会发生什么将作为实现细节留下:当前画中画窗口可以关闭,画中画- 可以拒绝图片请求,甚至可以创建两个画中画窗口。无论如何,用户代理必须触发适当的事件,以通知网站画中画状态的变化。

    所以我们可以说你最好不要期望它同时打开两个窗口。


    现在,如果您真的愿意,您确实可以在画布上绘制两个视频,并将此画布传递给画中画窗口,在将其 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>

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

    【讨论】:

    • 非常感谢您花时间解释您的想法,甚至写出代码 sn-p。我迫不及待地想玩这个。看起来您使用 drawImage 在画布上“播放”视频,动画显示下一帧,然后在 PictureInPicture 中播放画布。我也想知道为什么滚动会影响视频,但我印象深刻的是这真的会发生。上帝的技术从未停止让我惊讶。非常感谢@Kaiido
    猜你喜欢
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 2015-01-24
    • 2017-08-20
    • 1970-01-01
    相关资源
    最近更新 更多