【发布时间】:2021-11-22 15:27:41
【问题描述】:
我正在尝试创建视频聊天,并在后端使用 express 和 socket.io,在前端使用 react 和 simple-peer。
这是我的服务器代码:
const http = require('http');
const express = require('express');
const app = express();
const httpServer = http.createServer(app);
app.use(require('cors')());
const io = require('socket.io')(httpServer, {
cors: {
origin: ['http://localhost:3000', 'http://localhost:3001'],
method: ['GET', 'POST']
}
});
const cache = {};
io.on('connection', socket => {
socket.on('join', id => {
cache[id] = socket.id;
console.log('cache', cache);
socket.join(id);
});
socket.on('disconnect', () => {
socket.broadcast.emit('callEnded');
});
socket.on('callUser', data => {
console.log('calling user', data.userToCall, cache[data.userToCall]);
io.to(data.userToCall).emit('callUser', {
signal: data.signalData,
from: data.from,
name: data.name
});
});
// socket.on('answerCall', data => {
// console.log('data', data);
// io.to(cache[data.to]).emit('callAccepted', data.signal);
// });
socket.on('answerCall', data => {
console.log('answering call', data);
io.to(data.to).emit('callAccepted', data.signal);
});
});
httpServer.listen(4000, () => 'Listening...');
我正在接受来自端口 3000 和 3001 的请求,因为这是我运行我的两个应用程序的地方。由于我目前在后端没有登录系统,因此我正在为每个对等方运行一个应用程序。
第一个应用的代码如下所示:
import { useEffect, useState, useRef } from "react";
import Peer from "simple-peer";
import io from "socket.io-client";
import './App.css';
const ID = 'fey'
function App() {
const [ stream, setStream ] = useState()
const [receivingCall, setReceivingCall] = useState(false) ;
const [caller, setCaller] = useState("") ;
const [callerSignal, setCallerSignal] = useState() ;
const [callAccepted, setCallAccepted] = useState(false);
const [callEnded, setCallEnded] = useState(false);
const socket = io.connect("http://localhost:4000/");
const myVideo = useRef()
const userVideo = useRef()
const connectionRef = useRef()
useEffect(() => {
navigator.mediaDevices.getUserMedia({video: true, audio: true})
.then((stream)=>{
setStream(stream)
myVideo.current.srcObject = stream
})
.catch((err) => console.log(err))
socket.emit('join', ID)
socket.on("callUser", (data)=>{
setReceivingCall(true)
setCaller(data.from)
setCallerSignal(data.signal)
})
}, [])
const callUser = ()=> {
const peer = new Peer({
initiator:true,
trickle:false,
stream:stream
})
peer.on("signal", (data)=>{
socket.emit("callUser",{
userToCall: 'fey-clone',
signalData: data,
from: ID,
name: "Fey"
})
})
peer.on("stream", (stream)=> {
userVideo.current.srcObject = stream
})
socket.on("callAccepted", (signal) => {
console.log('call accepted!!')
setCallAccepted(true)
peer.signal(signal)
})
connectionRef.current = peer
}
const answerCall = () => {
console.log('peer exists')
setCallAccepted(true)
const peer = new Peer({
initiator:false,
trickle:false,
stream: stream
})
peer.on("signal", (data)=> {
console.log('call answered')
socket.emit("answerCall", {signal:data, to: caller})
})
peer.on("stream", (stream) =>{
userVideo.current.srcObject = stream
})
peer.signal(callerSignal)
connectionRef.current = peer
}
const leaveCall = ()=>{
setCallEnded(true)
connectionRef.current.destroy()
}
return (
<div className="App">
<div className="video">
{stream && <video playsInline muted ref={myVideo} autoPlay style={{width: "300px", height: "300px" }} />}
{callAccepted && <video playsInline muted ref={userVideo} autoPlay style={{width: "300px", height: "300px" }} />}
</div>
{callAccepted && !callEnded ? (
<button onClick={leaveCall}>
End Call
</button>
):(
<button onClick={callUser}>call meeee</button>
)}
{receivingCall && !callAccepted ? (
<div className="caller">
<h1>Fey is calling ...</h1>
<button onClick={answerCall} >
Answer
</button>
</div>
) : null
}
</div>
);
}
export default App;
另一个对等点的代码看起来很相似,但 ID 不同,userToCall 是另一个。
import { useEffect, useState, useRef } from "react";
import Peer from "simple-peer";
import io from "socket.io-client";
import './App.css';
const ID = 'fey-clone'
function App() {
const [ stream, setStream ] = useState()
const [receivingCall, setReceivingCall] = useState(false) ;
const [caller, setCaller] = useState("") ;
const [callerSignal, setCallerSignal] = useState() ;
const [callAccepted, setCallAccepted] = useState(false);
const [callEnded, setCallEnded] = useState(false);
const socket = io.connect("http://localhost:4000/");
const myVideo = useRef()
const userVideo = useRef()
const connectionRef = useRef()
useEffect(() => {
navigator.mediaDevices.getUserMedia({video: true, audio: true})
.then((stream)=>{
setStream(stream)
myVideo.current.srcObject = stream
})
.catch((err) => console.log(err))
socket.emit('join', ID)
socket.on("callUser", (data)=>{
setReceivingCall(true)
setCaller(data.from)
setCallerSignal(data.signal)
})
}, [])
const callUser = ()=> {
const peer = new Peer({
initiator:true,
trickle:false,
stream:stream
})
peer.on("signal", (data)=>{
socket.emit("callUser",{
userToCall: 'fey',
signalData: data,
from: ID,
name: "fey clone"
})
})
peer.on("stream", (stream)=> {
userVideo.current.srcObject = stream
})
socket.on("callAccepted", (signal) => {
console.log('call accepted!!')
setCallAccepted(true)
peer.signal(signal)
})
connectionRef.current = peer
}
const answerCall = () => {
setCallAccepted(true)
const peer = new Peer({
initiator:false,
trickle:false,
stream: stream
})
peer.on("signal", (data)=> {
console.log(data, caller)
socket.emit("answerCall", {signal:data, to: caller})
})
peer.on("stream", (stream) =>{
console.log('I streeeam')
userVideo.current.srcObject = stream
})
peer.signal(callerSignal)
connectionRef.current = peer
}
const leaveCall = ()=>{
setCallEnded(true)
connectionRef.current.destroy()
}
return (
<div className="App">
<div className="video">
{stream && <video playsInline muted ref={myVideo} autoPlay style={{width: "300px", height: "300px" }} />}
{callAccepted && <video playsInline muted ref={userVideo} autoPlay style={{width: "300px", height: "300px" }} />}
</div>
{callAccepted && !callEnded ? (
<button onClick={leaveCall}>
End Call
</button>
):(
<button onClick={callUser}>call meeee</button>
)}
{receivingCall && !callAccepted ? (
<div className="caller">
<h1>Fey is calling ...</h1>
<button onClick={answerCall} >
Answer
</button>
</div>
) : null
}
</div>
);
}
export default App;
呼叫似乎是通过正确的接收者。当fey 呼叫fey-clone 时,fey-clone 可以接听电话。 signal 似乎也可以正常工作。但是,原来的调用者fey似乎从来没有收到来自服务器的事件callAccepted,所以视频通话无法开始。服务器很可能没有将事件发送给正确的对等方,但我尝试调试无济于事。我在这里有什么遗漏吗?
【问题讨论】:
标签: node.js reactjs express socket.io webrtc