我对 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>
寻求帮助
答案 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如果你的同伴在同一个区域就可以正常工作