在本文中,我们将使用 Socket.io 和 Peer-to-Peer 库在 React 和 Express 之间为视频通话应用程序建立连接。
设置后端
1. 安装必要的软件包
npm init -y
npm install express socket.io cors
2. 导入库
const express = require(“express”);
const http = require(“http”);
const { Server } = require(“socket.io”);
const cors = require(“cors”);
3. 快速设置
const app = express ();
app.use (cors());
4. HTTP 服务器连接
const server = http.createServer(app);
5. Socket.io 和 CORS 设置
const io = new Server (server, {
cors : {
origin : 'http://localhost:3000' ,
methods : [ 'GET' , 'POST' ],
},
});
根据您的前端调整原点。
6. 端口配置
const PORT = 5000;
7. 用户连接
io.on('connection', (socket) => {
console.log('A user connected');
});
用于监听新套接字连接的事件,每次有新用户进入时在控制台上打印消息。
8. 加入视频通话房间
socket.on('join room', (roomID) => {
if (rooms.has(roomID)) {
rooms.get(roomID).push(socket.id);
} else {
rooms.set(roomID, [socket.id]);
}
const otherUsers = rooms.get(roomID).filter(id => id !== socket.id);
socket.emit('all users', otherUsers);
});
此代码监听“加入房间”事件。如果指定房间存在,则将套接字 ID 添加到该房间,否则创建一个新房间。此外,将该房间 ID 中存在的所有用户发送到客户端。
9. 发送信号以进行 WebRTC 连接
socket.on('sending signal', (payload) => {
io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID });
});
此代码监听来自客户端的“发送信号”事件,并向 userToSignal 标识的指定用户发出“用户加入”事件。
userToSignal — 已经在房间中的用户的 ID。
callerID — 进入房间的用户的ID。
10. 返回 WebRTC 连接的信号
socket.on('returning signal', (payload) => {
io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });
});
此代码监听来自客户端的“returning signal”事件,并向callerID标识的指定用户发出“receiving returned signal”事件。
11. 用户断线
socket.on('disconnect', () => {
console.log('A user disconnected');
rooms.forEach((value, key) => {
if (value.includes(socket.id)) {
rooms.set(key, value.filter(id => id !== socket.id));
if (rooms.get(key).length === 0) {
rooms.delete(key);
}
}
});
socket.broadcast.emit('user left', socket.id);
});
此代码监听“disconnect”事件,并在每次用户断开连接时在控制台上打印消息。它从指定的房间中删除套接字 ID,如果房间为空,则删除该房间。此外,通过发出“user left”事件通知房间中的所有用户。
12. 服务器初始化
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
设置前端
1. 安装库
npm install react react-dom socket.io-client simple-peer react-icons react-router-dom
2. 导入库
import React, { useState, useEffect, useRef } from 'react';
import { FaCamera, FaUserPlus, FaMicrophone, FaMicrophoneSlash } from 'react-icons/fa';
import io from 'socket.io-client';
import Peer from 'simple-peer';
import { useNavigate } from 'react-router-dom';
3. 视频通话的状态和参考
const [roomId,setRoomId] = useState('');
const [peers,setPeers] = useState([]);
const [isMicOn,setIsMicOn] = useState(true);
const [isCameraOn,setIsCameraOn] = useState(true);
const socketRef = useRef();
const userVideoRef = useRef();
const peersRef = useRef([]);
const streamRef = useRef();
const navigation = useNavigate();
4. 套接字连接和流处理
useEffect(() => {
socketRef.current = io.connect('http://localhost:5000');
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
streamRef.current = stream;
if (userVideoRef.current) {
userVideoRef.current.srcObject = stream;
}
socketRef.current.emit('join room', roomId);
socketRef.current.on('all users', users => {
const peers = [];
users.forEach(userId => {
const peer = createPeer(userId, socketRef.current.id, stream);
peersRef.current.push({
peerID: userId,
peer,
});
peers.push(peer);
});
setPeers(peers);
});
socketRef.current.on('user joined', payload => {
const peer = addPeer(payload.signal, payload.callerID, stream);
peersRef.current.push({
peerID: payload.callerID,
peer,
});
setPeers(users => [...users, peer]);
});
socketRef.current.on('receiving returned signal', payload => {
const item = peersRef.current.find(p => p.peerID === payload.id);
item.peer.signal(payload.signal);
});
})
.catch(err => {
console.error("Error accessing media devices:", err);
});
return () => {
if (socketRef.current) {
socketRef.current.disconnect();
}
if (streamRef.current) {
streamRef.current.getTracks().forEach(track => track.stop());
}
};
}, [roomId]);
根据您的后端调整 URL。
每当 roomId 发生变化时,此 useEffect 钩子就会运行。它连接到 WebSocket 服务器并设置事件侦听器,用于管理参与者并访问用户的设备以获取视频和音频流。它会监听有关用户加入或离开的所有通知。
5. 切换麦克风
const toggleMic = () => {
const audioTracks = streamRef.current.getAudioTracks();
audioTracks.forEach(track => {
track.enabled = !track.enabled;
});
setIsMicOn(prev => !prev);
};
6. 切换摄像头
const toggleCamera = () => {
const videoTracks = streamRef.current.getVideoTracks();
videoTracks.forEach(track => {
track.enabled = !track.enabled;
});
setIsCameraOn(prev => !prev);
};
7. 创建对等体
const createPeer = (userToSignal, callerID, stream) => {
const peer = new Peer({
initiator: true,
trickle: false,
stream,
});
peer.on('signal', signal => {
socketRef.current.emit('sending signal', { userToSignal, callerID, signal });
});
return peer;
};
通过设置事件监听器来通知服务器发出“发送信号”,为用户建立新的 WebRTC 对等连接,从而发起呼叫。
8. 添加 Peer
const addPeer = (incomingSignal, callerID, stream) => {
const peer = new Peer({
initiator: false,
trickle: false,
stream,
});
peer.on('signal', signal => {
socketRef.current.emit('returning signal', { signal, callerID });
});
peer.signal(incomingSignal);
return peer;
};
通过设置事件监听器来通知服务器发出“returning signal”,为接听电话的用户建立新的 WebRTC 对等连接。
9. 处理房间创建
const handleRoomCreate = ( ) => {
const newRoomId = Math . random (). toString ( 36 ). substring ( 7 );
setRoomId (newRoomId);
};
为用户和其他参与者生成唯一的代码以加入。
10. 处理房间加入
const handleRoomJoin = ( e ) => {
e.preventDefault ( );
};
11. 显示用户和参与者的视频
return (
<div>
<div>
<video playsInline muted ref={userVideoRef} autoPlay/>
<div>You</div>
</div>
{peers.length > 0 ? (
peers.map((peer, index) => (
<Video key={index} peer={peer} />
))
) : (
<div>
<p>Waiting for a participant...</p>
</div>
)}
</div>
);
此代码为用户和房间中的其他参与者呈现视频元素。
12. 参与者的视频组件
const Video = ({ peer }) => {
const ref = useRef();
useEffect(() => {
peer.on('stream', stream => {
if (ref.current) {
ref.current.srcObject = stream;
}
});
}, [peer]);
return (
<div>
<video playsInline autoPlay ref={ref} />
<div>Participant</div>
</div>
);
};
13. 房间操作按钮
<div>
<button onClick={toggleMic}>
{isMicOn ? <FaMicrophone/> : <FaMicrophoneSlash/>}
{isMicOn ? "Mute" : "Unmute"}
</button>
<button onClick={toggleCamera}>
{isCameraOn ? <FaCamera className/> : <FaCamera/>}
{isCameraOn ? "Turn Off Camera" : "Turn On Camera"}
</button>
</div>
通过以上步骤,您将创建视频通话应用程序。此外,还可以集成白板和聊天选项,使其成为更强大的应用程序。
了解更多信息,可以参考此链接:https://github.com/JainSneha6/SyncSpace。作者:Sneha Jain
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/yinshipin/52834.html