Peerjs WebRTC 中未显示远程用户的音频和视频

时间:2021-07-25 13:42:14

标签: express npm webrtc peerjs

我对 PeerJs 和 WebRTC 非常陌生。由于新冠病毒时间,最近开始为我的学校学习和开发远程课程应用程序。

建立连接后,创建的用户可以在视频中看到他,但远程人员的音频/视频不显示。

服务器代码:

io.on('connection', (socket) => {
    socket.on('room-joined', (roomId, userId) => {
        socket.join(roomId)
        socket.broadcast.to(roomId).emit('new-user-connected', userId)

        socket.on('disconnect', () => {
            socket.broadcast.to(roomId).emit('user-disconnected', userId)
        })
        
        socket.on("offer", payload => {
            socket.broadcast.to(roomId).emit("offer-received", payload);
        });

        socket.on("answer", payload => {
            socket.broadcast.to(roomId).emit("answer-received", payload);
        });

        socket.on("ice-candidate", data => {
            socket.broadcast.to(roomId).emit("ice-candidate-message", data);
        });
    })
})

客户代码:

const socket = io('/');
var selectedCamera = 'user'
var totalUsers = []
let localStream;
let localId
let initiater;
let otherUserId;

const peer = new Peer(undefined, {
    host: '/',
    port: '443',
    path: '/myapp',
    secure: true
});

peer.on("open", (id) => {
    localId = id;
    socket.emit("room-joined", roomId, id);
    totalUsers.push(id);
    initSelfStream();
    //console.log('My userId: ' + id)
});

const initSelfStream = () => {
    (async () => {
        try {
            await navigator.mediaDevices.getUserMedia(
                {
                    video: {
                        facingMode: selectedCamera
                    },
                    audio: true
                }).then(stream => {
                    localStream = stream;
                    
                    const video = document.createElement("video");
                    loadAndShowVideoView(video, stream, localId);

                    socket.on('new-user-connected', id => {
                        setTimeout(function() { callUser(id, stream); }, 3000);
                        otherUserId = id;
                    });
                });
        } catch (err) {
            console.log('(async () =>: ' + err);
        }
    })();
}

const callUser = (id, stream) => {
    test1 = createRtcPeerConnection(id);
    localStream.getTracks().forEach(track => test1.addTrack(track, localStream));
}

socket.on("offer-received", (data) => {
    if(data.target == localId){
        test1 = createRtcPeerConnection();
        const desc = new RTCSessionDescription(data.sdp);
        test1.setRemoteDescription(desc).then(() => {
            localStream.getTracks().forEach(track => test1.addTrack(track, localStream));
        }).then(() => {
            return test1.createAnswer();
        }).then(answer => {
            return test1.setLocalDescription(answer);
        }).then(() => {
            const payload = {
                target: data.caller,
                caller: localId,
                sdp: test1.localDescription
            }
            socket.emit("answer", payload);
        });
    }
});
socket.on("answer-received", (data) => {
    if(data.target == localId){
        const desc = new RTCSessionDescription(data.sdp);
        test1.setRemoteDescription(desc).catch(e => console.log(e));
    }
});
socket.on("ice-candidate-message", (data) => {
    if(data.target == localId){
        if (data.candidate.candidate) {
            const payload = {
                target: otherUserId,
                candidate: data.candidate.candidate,
            }
            socket.emit("ice-candidate", payload);
        }
    }
});

const createRtcPeerConnection = (id) => {
    const rtcPeerConnection = new RTCPeerConnection({
        iceServers: [
            {
                urls: "stun:stun.stunprotocol.org"
            },
            {
                urls: 'turn:numb.viagenie.ca',
                credential: 'muazkh',
                username: 'webrtc@live.com'
            },
        ]
    });

    rtcPeerConnection.onicecandidate = handleICECandidateEvent;
    rtcPeerConnection.ontrack = handleTrackEvent;
    rtcPeerConnection.onnegotiationneeded = () => handleNegotiationNeededEvent(id);

    return rtcPeerConnection;
}

const handleICECandidateEvent = (e) => {
    if (e.candidate) {
        const payload = {
            target: otherUserId,
            candidate: e.candidate,
        }
        socket.emit("ice-candidate", payload);
    }
}
const handleTrackEvent = (e) => {
    const video = document.createElement("video");
    loadAndShowVideoView(video, e.streams[0], "Temporary Id")
}
const handleNegotiationNeededEvent = (targetUserID) => {
    test1.createOffer().then(offer => {
        return test1.setLocalDescription(offer);
    }).then(() => {
        const payload = {
            target: targetUserID,
            caller: localId,
            sdp: test1.localDescription
        };
        socket.emit("offer", payload);
    }).catch(e => console.log(e));
}

const loadAndShowVideoView = (video, stream, id) => {
    video.classList.add('video-inset', 'background-black');
    video.setAttribute("id", id);
    video.style.position = "relative"
    video.autoplay = true;
    
    video.srcObject = stream;
    video.style.height = 50+"vh"
    video.style.width = 50+"vw"
    
    video.muted = true;
    video.style.objectFit = "cover"
    
    appendVideo(video, stream, id)
}
const appendVideo = (video, stream, id) => {
    video.addEventListener("loadedmetadata", () => {
            loader.style.opacity = 0
            container.append(video);
            video.play()
            if(loader.style.visibility == "visible") {
                loader.style.display = "none";
            }
    });
}

ejs 查看文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script>
    const roomId = "<%= roomId %>"
  </script>
  <script src="peer.min.js" defer></script>
  <script src="/socket.io/socket.io.js" defer></script>
  <script src="client.js" defer></script>
</head>
<body>
    <div class="container background-black" id="loader">
        <div class="loader"></div>
    </div>
    <div class="views-container background-black" id="container"></div>
</body>
</html>

寻求帮助

1 个答案:

答案 0 :(得分:0)

好吧,我不是专业人士,但我不久前完成了我的第一个 webrtc 项目

首先你应该检查你的浏览器控制台是否有错误

第二,您似乎在某些部分使用了 peerjs,而在其他部分使用了纯 WEBRTC!我认为这行不通......你需要选择一个

您需要 peer.on('call') 侦听其他用户连接 call.answer(stream) 为呼叫者发送您的流,并需要 call.on('stream') 接收呼叫者流

事情是这样的

var peer = new Peer({
    config: {'iceServers': [
            { url: 'stun:stun.l.google.com:19302' },
        ]} /* Sample servers, please use appropriate ones */
});


peer.on('open', function(id) {
    MY_PEER_ID = id ;
    io.emit('peer_id_offer' , {  chat_room  : ROOM , id : id}); // send your peerid to other users in the room via socket.io 
});



// call other peers when you receive their id 
io.on('peer_id_recived' , function(data){
     callPeer(value.peer_id); // look at the function below 
});

// calling other peer when we receive their id via socket.io sending them our stream and expecting to receive theirs 
 function callPeer( id )
{
        navigator.mediaDevices.getUserMedia({ video : true , audio : true })
        .then(  (stream) => {

            addOurVideo(stream);
            
            let  call = peer.call(id , stream);
            
            call.on('stream' , function(remoteStream){
                    addRemoteVideo(remoteStream);

            })
        })
        .catch( (e)=>{
            console.log('error1' , e );
        });
}




// handle reciving call from other clients in the room 
peer.on('call' , function (call) {


    /// send your own stream for the caller and add the caller stream to your page 
    navigator.mediaDevices.getUserMedia({ video : true , audio : true })
        .then((stream) => {
            
            call.answer(stream);
            call.on('stream' , function(remoteStream){
                
                    addRemoteVideo(remoteStream);
            })

        })
        .catch( (e)=>{
            console.log('error2' , e );
        });

})

你需要一些双重检查以避免调用/添加重复的流/对等

这是我的代码,检查一下,看看我是怎么做的

https://chate-test-3000.herokuapp.com/peer?room=someRomeName

只是一个提示

var peer = new Peer({
    config: {'iceServers':  clientICE.iceServers } /* Sample servers, please use appropriate ones */
});

而不是clientICE.iceServers,我使用了一些商业转服务器

您必须提供自己的冰服务器并在此处替换它们

您可以使用免费的谷歌服务

var peer = new Peer({
    config: {'iceServers': [
            { url: 'stun:stun.l.google.com:19302' },
        ]} /* Sample servers, please use appropriate ones */
});

最终你需要使用商业turn server来处理更复杂的网络配置,但现在google stun server如果你的同伴在同一个区域就可以正常工作