信令失败:WebRTC 视频通话网站开发中“对等体被破坏后无法发信”问题

问题描述 投票:0回答:1

请原谅我初学者的问题。我想使用 webRTC、Peer 和 Next.js 创建一个用于群组视频通话的网站。我使用 Node.js 的信令服务器来连接对等点。但由于某种原因,当我运行它时,我总是收到错误:在对等点被销毁后无法发出信号。

有什么建议吗?谢谢

这是我的房间的文件句柄,用户可以加入。

'use client'
import React, { useEffect, useRef, useState } from "react";
import { useRouter } from 'next/navigation'; // Fix typo in import statement
import io from "socket.io-client";
import Peer from "simple-peer";
import styled from "styled-components";

const Container = styled.div`
    padding: 20px;
    display: flex;
    height: 100vh;
    width: 90%;
    margin: auto;
    flex-wrap: wrap;
`;

const StyledVideo = styled.video`
    height: 40%;
    width: 50%;
`;

const Video = (props) => {
    const ref = useRef();

    useEffect(() => {
        props.peer.on("stream", stream => {
            ref.current.srcObject = stream;
        });
    }, [props.peer]);

    return (
        <StyledVideo playsInline autoPlay ref={ref} />
    );
}

const Room = () => {
    const router = useRouter();
    const [peers, setPeers] = useState([]);
    const socketRef = useRef();
    const userVideo = useRef();
    const peersRef = useRef([]);
    const id  = router.query; // Use router.query to get the room ID
    const roomID = 123
    useEffect(() => {
        console.log(id)
        const videoConstraints = {
            height: window.innerHeight / 4,
            width: window.innerWidth / 4
        };

        socketRef.current = io.connect("http://localhost:8000");
        
        navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: true }).then(stream => {
            userVideo.current.srcObject = stream;
            socketRef.current.emit("join room", roomID);

            socketRef.current.on("all users", users => {
                const peers = [];
                users.forEach(userID => {
                    if (userID !== socketRef.current.id) {
                        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);
                if (item) {
                    item.peer.signal(payload.signal);
                }
            });
        });
    }, [roomID]);

    function 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;
    }

    function 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;
    }

    return (
        <div className="bg-gray-100 min-h-screen flex flex-col">
            <h1 className="text-2xl font-semibold p-4">Video Chat Room</h1>
            <div className="video-container p-4 flex-1">
                {userVideo && <StyledVideo muted ref={userVideo} autoPlay playsInline />}
                {peers.map((peer, index) => (
                    <Video key={index} peer={peer} />
                ))}
            </div>
            {/* Chat bar */}
            <div className="bg-white p-4 border-t border-gray-300">
                <div className="chat-messages"></div>
                <div className="flex mt-2">
                    <input
                        type="text"
                        placeholder="Type a message..."
                        className="p-2 border border-gray-300 rounded-lg flex-1"
                    />
                    <button
                        className="ml-2 bg-blue-500 text-white px-4 py-2 rounded-lg"
                    >
                        Send
                    </button>
                </div>
            </div>
            <div className="p-4">
                <button
                    className="bg-blue-500 text-white px-4 py-2 rounded-lg"
                >
                </button>
                <button
                    className="ml-2 bg-blue-500 text-white px-4 py-2 rounded-lg"
                >
                </button>
            </div>
        </div>
    );
};

export default Room;

这是我的信令服务器

require('dotenv').config();
const express = require("express");
const http = require("http");
const app = express();
const cors = require("cors");
app.use(cors)
const server = http.createServer(app);
const socket = require("socket.io");
const io = socket(server, {
    cors: {
      origin: "http://localhost:3000",
      methods: ["GET", "POST"],
    },
  });
  

const users = {};

const socketToRoom = {};

io.on('connection', socket => {
    socket.on("join room", roomID => {
        if (users[roomID]) {
            const length = users[roomID].length;
            if (length === 4) {
                socket.emit("room full");
                return;
            }
            users[roomID].push(socket.id);
        } else {
            users[roomID] = [socket.id];
        }
        socketToRoom[socket.id] = roomID;
        const usersInThisRoom = users[roomID].filter(id => id !== socket.id);

        socket.emit("all users", usersInThisRoom);
        
    });

    socket.on("sending signal", payload => {
        io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID });
    });

    socket.on("returning signal", payload => {
        io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });
    });

    socket.on('disconnect', () => {
        const roomID = socketToRoom[socket.id];
        let room = users[roomID];
        if (room) {
            room = room.filter(id => id !== socket.id);
            users[roomID] = room;
        }
    });

});

server.listen(process.env.PORT || 8000, () => console.log('server is running on port 8000'));

我希望您能在代码中找出我的问题所在。我非常感谢您在识别和解决问题方面提供的帮助。谢谢你。

next.js webrtc peerjs videocall simple-peer
1个回答
0
投票

我认为你也应该检查 PeerJS 文档。在那里,他们提到了这样的破坏

此操作无法撤消;相应的对等对象将不再是 能够创建或接收任何连接,其 ID 将被没收 (云)服务器及其所有数据和媒体连接将 关闭。

有关更多信息,请查看此 PeerJS

© www.soinside.com 2019 - 2024. All rights reserved.