peer.on('call') 永远不会被调用

Posted

技术标签:

【中文标题】peer.on(\'call\') 永远不会被调用【英文标题】:peer.on('calll') is never being calledpeer.on('call') 永远不会被调用 【发布时间】:2021-06-30 09:24:26 【问题描述】:

对等 js 不工作

我只是在 NodeJs 和 ReactJs 中创建 peerjs 视频流应用程序


下面的代码工作正常,我可以创建新的对等点,open 事件也正常工作。

const peer = new Peer(undefined,
            host:"/",
            port:"5001"
        );

peer.on('open',id=>
  socket.emit('join-room', roomId,id);
)

在服务器端,每当发出'join-room' 事件时,服务器都会发出另一个事件'user-disconnected' 并将userId (peerjs) 传递给客户端。

// server.js
socket.on('join-room',(roomId,userId)=>
    console.log(`user $userId joined $roomId`);
    socket.join(roomId);
    socket.to(roomId).emit('user-connected',userId);

    socket.on('disconnect', () => 
        socket.to(roomId).emit('user-disconnected', userId)
    )
)

每当在客户端触发'user-connected' 时,我都会调用connectToNewUser,并且到目前为止一切正常。

socket.on('user-connected',userId=>
    console.log("New user connected...")
    connectToNewUser(userId, stream)
);

错误

这是在控制台console.log('connectToNewUser',1222.....)上记录的,没有错误。

但是,这个call.on('stream') 永远不会被调用

connectToNewUser(userId, stream) 
    console.log('connectToNewUser',userId)
    const call = peer.call(userId, stream);
    const video = getVideo();
    call.on('stream', userVideoStream => 
      // never called
      console.log('connectToNewUser','on','stream')
      addVideoStream(video, userVideoStream)
    );
    call.on('close', () => 
      video.remove()
    )

    peers[userId] = call

call.on('stream') 从未被调用的原因是peer.on('call') 从未被调用。

peer.on('call', call => 
    // never called
    console.log('This peer is being called...');
    call.answer(stream)
    const video = getVideo();
    call.on('stream', userVideoStream => 
        console.log('This peer is being called...on-stream...');
        addVideoStream(video, userVideoStream)
    )
);

Github repo

【问题讨论】:

【参考方案1】:

我也遇到了同样的问题,在 *** 上经历了 10 多个解决方案后,这是我的建议。

connectToNewUser() 在用户完成导航承诺之前被触发。

尝试修改为:

socket.on('user-connected',userId=>
    console.log("New user connected...")
    //connectToNewUser(userId, stream)
    setTimeout(connectToNewUser,1000,userId,stream)
);

它对我有用。

【讨论】:

【参考方案2】:

您的代码类似于我正在处理的项目。我在启动 peer 实例时遇到了麻烦。我不得不将它在我的组件树中上移一级,因为我正在做的事情导致重新渲染,并且正在重新创建 peer 实例,并使用新的 id

还要检查您创建套接字的位置。确保您的user-connected 事件正在useEffect() 中注册。

  useEffect(() => 
    videoSocket = initiateVideoSocket(roomId, username, peer.id);
    // When a viewer connects, this event is emitted and the streamer will connect to the viewer.
    videoSocket.on("user-connected", (roomId, viewerPeerId) => 
      connectToNewViewer(viewerPeerId, videoStream);
    );
  , [videoStream]);
  const viewerVideoSocket = initiateVideoSocket(
    room,
    props.username,
    viewerPeerId
  );

  const viewerChatSocket = initiateChatSocket(room, props.username);
  let streamerVideoDiv;

  useEffect(() => 
    viewerVideoSocket.emit(
      "user-connected",
      room,
      props.username,
      viewerPeerId
    );

    viewerPeer.on("call", (call) => 
      call.answer();
      call.on("stream", (stream) => 
        streamerVideoDiv = document.getElementById("streamer-video");
        const content = document.createElement("video");
        content.srcObject = stream;
        content.addEventListener("loadedmetadata", () => 
          content.play();
        );
        streamerVideoDiv.append(content);
      );
    );

    return () => 
      disconnectSocket();
    ;
  , []);

【讨论】:

peer.on('open',id=> socket.emit('join-room', roomId,id); ) 这工作正常,这意味着对等方能够与服务器建立连接 对。因此,您的套接字正在发出 join-room 事件并且正在调用该函数。你能console.log()你的peer实例看看它是否工作正常吗? 是的,套接字正在发出 join-room 事件 另外,在connectToNewUser() 函数中,这已成功记录console.log('connectToNewUser',userId),但我认为此语句不起作用const call = peer.call(userId, stream) 如果有时间可以去repogithub.com/ats1999/conference【参考方案3】:

您的代码的唯一问题是您在客户端上初始化 peer.on("call") 事件之前从服务器发出用户连接事件,这最终导致新客户端错过此事件。 最好的解决方案是在初始化 peer.on("call",...) 事件后发出一个就绪事件。

peer.on('call', call => 
console.log('This peer is being called...');
call.answer(stream)
const video = getVideo();
call.on('stream', userVideoStream => 
    console.log('This peer is being called...on-stream...');
    addVideoStream(video, userVideoStream)
))
socket.emit("ready")`

然后在服务器端调用侦听器内的“用户连接”广播事件以获取“就绪”事件:

socket.on('join-room',(roomId,userId)=>
console.log(`user $userId joined $roomId`);
socket.join(roomId);
socket.on('ready',()=>
socket.broadcast.to(roomId).emit('user-connected',userId);
)

socket.on('disconnect', () => 
 socket.to(roomId).emit('user-disconnected', userId)
))

这将在客户端准备好接收 peer.on("call". .. .) 事件

【讨论】:

【参考方案4】:

我认为你的代码是这样的

const peer = new Peer(undefined,host:"/",port:"5001")
peer.on('open',id=>
  socket.emit('join-room', roomId,id)
)

navigator.mediaDevices.getUserMedia(
    video : true,
    audio : true
).then( stream => 

    socket.on('user-connected',userId=>
         // call the new user and send our stream
    );
    
   peer.on('call',call=>
        // pick up the call and send our stream
   )

)

每当有新客户端加入时,就会创建一个新的对等对象,然后套接字发出 join-room 并且服务器将 user-connected 广播给所有其他客户端

所以现在当新用户加入所有其他客户端的user-connected 函数时,所有其他客户端都调用新客户端。

需要注意的一个关键点是 navigator.mediaDevices.getUserMedia(video : true,audio : true) 需要一些时间

因此,当一个新客户端加入时,所有其他客户端会立即呼叫新客户端,但接听呼叫的功能(即peer.on('call',call=>))可能尚未在新客户端上定义,这就是新客户端不响应的原因,因为它仍在设置其视频流

要解决此问题,您必须在设置视频流后加入房间 所以像这样的

navigator.mediaDevices.getUserMedia(
    video : true,
    audio : true
).then( stream => 

    const peer = new Peer(undefined,host:"/",port:"5001")
    peer.on('open',id=>
        socket.emit('join-room', roomId,id)
    )

    socket.on('user-connected',userId=>
         // call the new user and send our stream
    );
   
   peer.on('call',call=>
        // pick up the call and send our stream
   )

)

【讨论】:

【参考方案5】:

这里 Peer 对象在 Camera 和/或 Mic 准备好使用之前创建。

navigator.mediaDevices.getUserMedia(
  video: true,
  audio: true
).then(stream =>  
    //peer.on('call')
)

peer.on('call') 只会在getUserMedia() 完成执行后被浏览器执行。

问题是您正在接收呼叫事件,但还没有处理程序准备好处理该事件。最好的解决方案是在媒体准备好使用后加入会议室。

navigator.mediaDevices.getUserMedia(
  video: true,
  audio: true
).then(stream =>    
  const myPeer = new Peer(undefined, 
    host: '/',
    port: '3001'
  )
  myPeer.on('open', id =>  
    socket.emit('join-room', ROOM_ID, id)
  )

  myPeer.on('call', call =>  )
  )

【讨论】:

以上是关于peer.on('call') 永远不会被调用的主要内容,如果未能解决你的问题,请参考以下文章

10.5 Interrupted System Calls

IOS:UITextInput 上的 Tokenizer 永远不会被调用

S3.putObject - 回调永远不会被调用

QAbstractItemModel data() 永远不会被调用

Muzei 插件卡在永远不会收到 onUpdate() 调用的状态

Android onSystemUiVisibilityChange 永远不会被调用