NodeJS 如何在Youtube API中获得谁暂停了视频?(通过Socket.io)

gywdnpxw  于 2023-02-03  发布在  Node.js
关注(0)|答案(2)|浏览(139)

基本上,我正在挑战自己去构建一个类似于watch2gether的东西,在那里你可以通过Youtube API和Socket.io同时观看youtube视频。
我的问题是,除了使用Youtube API的 'onStateChange' 事件之外,没有办法检查视频是否已暂停。
但由于我无法监听 * CLICK * 本身,而只能监听实际的暂停 * EVENT *,所以当我发出暂停命令并通过套接字广播它时,当播放器在其他套接字中暂停时,它将再次触发事件,因此我无法跟踪谁先单击了暂停,也无法防止暂停循环。
这是我目前拥有的:

// CLIENT SIDE
// onStateChange event
function YtStateChange(event) {
    if(event.data == YT.PlayerState.PAUSED) {
        socket.emit('pausevideo', $user); // I'm passing the current user for future implementations
    }
    // (...) other states
}

// SERVER SIDE
socket.on('pausevideo', user => {
    io.emit('smsg', `${user} paused the video`)
    socket.broadcast.emit('pausevideo'); // Here I'm using broadcast to send the pause to all sockets beside the one who first clicked pause, since it already paused from interacting with the iframe
});

// CLIENT SIDE
socket.on('pausevideo', () => {
    ytplayer.pauseVideo(); // The problem here is, once it pauses the video, onStateChange obviously fires again and results in an infinite ammount of pauses (as long as theres more than one user in the room)
});

我想到的唯一可能的解决方案是使用一个不同的播放/暂停按钮,而不是iframe上的实际Youtube播放器来捕捉点击事件,并从那里暂停播放器,但我知道无数的网站使用普通iframe并捕捉这类事件,但我找不到一种方法来做我目前的知识。

xwmevbvl

xwmevbvl1#

如果这里的目标是能够忽略YT.PlayerState.PAUSED事件,而该事件是由您之前调用ytplayer.pauseVideo()引起的,那么您可以通过以下方法来实现:在调用ytplayer.pauseVideo()时记录时间戳,然后在获得YT.PlayerState.PAUSED事件时检查该时间戳,以查看是否因为您刚刚调用ytplayer.pauseVideo()而发生了暂停的事件。
总的概念是这样的:

let pauseTime = 0;
const kPauseIgnoreTime = 250;    // experiment with what this value should be

// CLIENT SIDE
// onStateChange event
function YtStateChange(event) {
    if(event.data == YT.PlayerState.PAUSED) {
        // only send pausevideo message if this pause wasn't caused by
        // our own call to .pauseVideo()
        if (Date.now() - pauseTime > kPauseIgnoreTime) {
            socket.emit('pausevideo', $user); // I'm passing the current user for future implementations
        }
    }
    // (...) other states
}

// CLIENT SIDE
socket.on('pausevideo', () => {
    pauseTime = Date.now();
    ytplayer.pauseVideo();
});

如果您的页面中有多个这样的变量,那么(而不是像这样的变量)您可以将pauseTime存储在与事件关联的球员相关的DOM元素中。
你可以做一些实验来看看kPauseIgnoreTime的最佳值是什么。它需要足够大,以便检测到任何由你专门调用ytplayer.pauseVideo()引起的YT.PlayerState.PAUSED事件,但不要太长,以免它捕捉到某人可能暂停,然后很快取消暂停的情况。

abithluo

abithluo2#

事实上,我发现了一个解决方案,而周围的工作什么家伙回答,我会张贴在这里,以防有人陷入同样的问题,并最终在这里。
由于socket.broadcast.emit不向自身发射,因此我创建了一个bool ignorePause,并使其仅在客户机接收到暂停请求时为 true
然后,我只在暂停请求尚未广播并接收到时才发出套接字,如果是这样,则忽略emit,并再次将bool设置为false,以防客户端/套接字随后暂停视频。

相关问题