首页 > 解决方案 > 即使我关闭了 PeerConnection,我也会看到黑屏。请帮我解决这个问题

问题描述

这是应用程序客户端的 Room.js 代码!我正在维护两个数组,一个是 peersRef,另一个是 peers,所有视频都是从 peers 渲染的。虽然在销毁对等方时调用了 onClick 按钮,但我想存在一些问题。

import React, { useEffect, useRef, useState } from "react";
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 => {
            // console.log();
            ref.current.srcObject = stream;
        })
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

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


const videoConstraints = {
    height: window.innerHeight / 2,
    width: window.innerWidth / 2
};

const Room = (props) => {


    const{email} = props;

    console.log(email);

    const [peers, setPeers] = useState([]);
    const [audiomute,setAudioMute] = useState(true);
    const [videomute,setVideoMute]= useState(true);
    const [myID,setMyID] = useState('');

    const socketRef = useRef();
    const userVideo = useRef();
    const peersRef = useRef([]);
    const roomID = props.match.params.roomID;

    useEffect(() => {
        socketRef.current = io.connect("/");
        navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: false }).then(stream => {
            userVideo.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);

            });

            socketRef.current.on('user-disconnected',users=>{
                console.log("Event is called");
                peers = users;  
            })

        });
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    function createPeer(userToSignal, callerID, stream) {
        const peer = new Peer({
            initiator: true,
            trickle: false,
            stream,
        });
        setMyID(userToSignal);
        peer.on("signal", signal => {
            socketRef.current.emit("sending signal", { userToSignal, callerID, signal })
        })
        // console.log(peer);
        console.log(peersRef.current);
        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);
        console.log(peersRef.current);
        return peer;
    }

    console.log(peers);

    const leavecall = ()=>{

        for(let i =0;i<peersRef.length;i++){
            if(peersRef.current[i].peerID===myID){
                peersRef.current[i].peer.destroy();
                peersRef.current.splice(i,1);
                peers[i].destroy();
                peers.splice(i,1);
                break;
            }
        }

        console.log(peers);
        window.location = "http://localhost:3000/";
    }

    const muteAudio=(e)=>{
        e.preventDefault();
        console.log("Called")
        if(audiomute){
            navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: true });
        }
        else{
            navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: false })
        }
        setAudioMute(!audiomute);
        
    }

    // const MuteVideo=(e)=>{
    //     e.preventDefault();
    //     setVideoMute(!videomute);
    //     navigator.mediaDevices.getUserMedia({ video: variable, audio: false })
    // }


    return (
        <Container>
            <StyledVideo muted ref={userVideo} autoPlay playsInline />
            {peers.map((peer, index) => {
                return (
                    <>
                        <Video key={index++} peer={peer} />
                    </>
                );
            })}

                        <button className="btn btn-danger" onClick={leavecall}>Hangup</button>
        </Container>
    );
};

export default Room;

这是服务器端代码!

require('dotenv').config();
const express = require("express");
const http = require("http");
const app = express();
const server = http.createServer(app);
const socket = require("socket.io");
const cors = require("cors");
const io = socket(server);


app.use(cors());
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];
        console.log(users);
        if (room) {
            room = room.filter(id => id !== socket.id);
            users[roomID] = room;
        }
        io.to(roomID).broadcast.emit('user-disconnected',users);
        console.log(users);

    });

});

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



这是当我与其他选项卡断开连接时看到的内容,视频元素应该完全消失,但这并没有发生

非常感谢您的帮助。

标签: node.jsreactjssocket.iowebrtc

解决方案


当您终止连接时,视频的最后一帧仍然可以渲染,只需删除视频元素或为其分配一个空的新流


推荐阅读