NodeJS 如何在播放/缓冲时同步两个具有相同源的视频

xkftehaa  于 2023-06-22  发布在  Node.js
关注(0)|答案(1)|浏览(189)

在应用程序的主页/着陆页中,我放置了两个视频,用户可以看到自动播放无控件
这两个视频使用相同的来源的MP4视频约。90MB大小:

<source src={VIDEO_SRC} type="video/mp4" />

第一个视频是更大的尺寸,是在背景中,并有一个模糊的效果,所以它只是在那里改善视觉外观。

<video
          key="big-video"
          loop
          muted
          autoPlay
          preload="none"
          poster="/MainVideoPoster.jpg"
          className="w-full h-full object-cover object-center blur-sm"
        >
          <source src={VIDEO_SRC} type="video/mp4" />
        </video>

第二视频在模糊视频的顶部。这是用户会看到的。

<video
          key="small-video"
          loop
          muted
          autoPlay
          preload="none"
          poster="/MainVideoPoster.jpg"
          className="w-full h-full object-contain object-center screen-md:object-contain"
        >
          <source src={VIDEO_SRC} type="video/mp4" />
        </video>

我们的想法是实现类似于你可以在这个页面上找到的东西:here
这些是我注意到的问题:

  • 感觉就像是浏览器在下载视频两次而不是一次,尽管两个视频都有相同的来源,并且在同一个页面上(第二个在第一个的上面)
  • 视频不同步。例如,第一个由于缓冲而暂停,第二个不同时暂停,并且变得明显的是,模糊视频没有在其上显示与正常视频相同的帧。

如何同步两个视频并确保下载的是同一个源?
有没有更好的方法来实现这一点?
谢谢你!

mcdcgff0

mcdcgff01#

不幸的是,mediaGroup属性,让你实现你想要的是超出规范和浏览器删除它...
另外,请注意,即使是LoL网站也有这个问题。
但是,这不会阻止我们...
你手头的工具是一种改变播放速率、获取和设置当前时间的方法。
还有一些事件可供您使用,以便您可以在视频停止缓冲等时做出React。

// Check canplay event to know when both videos are ready to play and start them.
let video1ready,video2ready  = false;
function tryStart(){
    if(video1ready && video2ready){
        video1.play();
        video2.play();
    }
}
video1.on('canplay',()=>{
    video1ready = true;
    tryStart();
});
video2.on('canplay',()=>{
    video2ready = true;
    tryStart();
});
// Stopped to load next frame, make the other video wait too.
video1.on('waiting',()=>{video2.pause();});
video2.on('waiting',()=>{video1.pause();});
// Resumed from buffering, continue playing the other video too.
video1.on('playing',()=>{video2.play();});
video2.on('playing',()=>{video1.play();});

所以,基本上,有了这个,我们可以更接近同步。这个想法是简单地使两个视频播放/暂停,如果/当另一个正在改变状态。
现在,另一种方法也可以是监视播放时间并将它们同步在一起。这在某种程度上是非常容易的,但是如果发生缓冲,这可能会变得混乱,因为正在运行的视频在播放时会抖动,并且会在几毫秒内被搜索回来。
您可以每隔X毫秒检查一次,并同步两个视频:

// Set video1's time to video2's, every 250 millisecond.
setInterval(()=>{
    video1.currentTime = video2.currentTime;
},250);

一个更优雅的解决方案,而不仅仅是使视频跳跃是使它赶上,或放慢最快的速度,使他们都回到正轨一起...我会说放慢最远的速度会更有意义,因为加快速度需要更多的帧更快,缓冲会不断发生。您可以使用播放速度播放,将其设置为0.8而不是1。在一段时间内,就像上面一样。

setInterval(()=>{
    const delta = Math.abs(video1.currentTime - video2.currentTime);
    if(delta  <.01 && delta > 0){ // Both videos are very close, let's sync them the hard way.
        video1.currentTime = video2.currentTime;
    }
    if(delta > .01){
        if(video1.currentTime > video2.currentTime){
            // Set the playbackRate lower, according to how many milliseconds we need to catch in the 250ms loop. Without setting lower than 0.8 or it would be too visible.
            video1.playbackRate = Math.max(0.8,1-(delta/.250));
        }else{
            video2.playbackRate = Math.max(0.8,1-(delta/.250));
        }
    }
},250);

我没有测试过任何东西,但理论是存在的,它应该至少可以工作。这些数字都是任意的,你可能需要使用它们才能达到预期的效果。
此外,我使用setInterval,但也许requestAnimationFrame会使事情更好,更准确。

我刚刚意识到我涵盖了同步部分,并没有关于有一个来源的两个视频。这只是因为没有办法拥有它。正如其他人所建议的,使用一个缩小的源模糊的视频,你可以有它很好的优化,即使压缩文物。模糊时不会显示。

相关问题