我刚刚在 github here 提交了一个 peerjs 与 nodejs 一起工作的完整工作示例:
。我浪费了很多时间来尝试遵循许多教程,但似乎没有一个对我有用。通过使用它并在 peerjs 客户端电报组中阅读,人们通过在随机位置添加延迟和代码阻塞睡眠功能来使应用程序正常工作,我知道这是一个时间问题。但有趣的是,我的大脑是如何工作的,像往常一样,我在半夜醒来,得到了解决方案。
这是大多数教程发生在我身上的事情。要响应呼叫,他们需要首先设置事件侦听器peer.on('call',(call) => {...}),然后他们需要在该函数中使用call.answer(stream) 接听呼叫。
由于他们需要本地流来接听电话,所以我找到的所有示例都称为
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* use the stream */
})
.catch(function(err) {
/* handle the error */
});
或者他们使用 async/await 构造并调用:
async function getMedia(constraints) {
let stream = null;
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
/* use the stream */
} catch(err) {
/* handle the error */
}
}
然后在 .then 的情况下或在异步函数的情况下的非阻塞等待之后返回 promise 之后,他们启动事件侦听器,如本例中的一个教程,该教程不适用于我的设置:
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
peer.on(“call”, (call) => {
call.answer(stream);
const video = document.createElement(“video”);
call.on(“stream”, (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on(“user-connected”, (userId) => {
connectToNewUser(userId, stream);
});
});
有什么问题?很简单,当目标客户端回复发起方客户端时,它首先通知对等服务器它想要连接到同一个房间,通知发起方客户端目标客户端想要连接的信令机制自行到达发起方客户端速度。来自发起方客户端的响应是使用对等服务器通过信令机制提供的 id 调用目标。发起方客户端需要它的视频/音频流对象来进行呼叫,这是它在第一次创建房间时已经获得的东西,在通过信号机制接收到房间里有其他人要呼叫的通知之前。
因此,呼叫可能发生得非常快(或者如果信令很慢,则非常慢,为了讨论,我们将假设信令非常快),因此在几毫秒内从发起方客户端向目标客户端发出呼叫.但是,不能保证发起者客户端已准备好接收此调用,它很可能处于刚刚启动的情况,连接到对等服务器以获取和 id,现在正在等待 getUserMedia() 的承诺返回的方法。因此,不能保证在目标客户端获得其流可用并因此设置“呼叫”事件处理程序后呼叫将到达。因此,可以在处理程序存在之前接收到事件。然后,目标客户端将永远等待(就像我在教程中发生的那样),看起来没有任何效果。
我为了让它工作而改变的是让 peer.on('call', async (call) => {... 立即,因此,在任何服务器连接发生之前启动 'call' 事件处理程序。然后,在事件处理程序中,等待流的返回,如下所示:
peer.on("call", async (call) => {
let stream = null;
console.log('*** "call" event received, calling call.answer(strem)');
// Obtain the stream object
try {
stream = await navigator.mediaDevices.getUserMedia(
{
audio: true,
video: true,
});
// Set up event listener for a peer media call -- peer.call, returns a mediaConnection that I name call
// Answer the call by sending this clients video stream --myVideo-- to calling remote user
call.answer(stream);
// Create new DOM element to place the remote user video when it comes
const video = document.createElement('video');
// Set up event listener for a stream coming from the remote user in response to this client answering its call
call.on("stream", (userVideoStream) => {
console.log('***"stream" event received, calling addVideoStream(UserVideoStream)');
// Add remote user video stream to this client's active videos in the DOM
addVideoStream(video, userVideoStream);
});
} catch (err) {
/* handle the error */
console.log('*** ERROR returning the stream: ' + err);
};
});
希望这会有所帮助,这样其他人就不必再经历这个了!