javascript - WebRTC over internet/heroku 不工作(视频、音频流)
问题描述
我基本上正在制作一个 WebRTC 视频聊天应用程序。您可以创建一个房间,用户可以使用提供的 6 位数代码加入。在房间里,你有视频聊天、共享记事本、聊天、屏幕共享和其他微小的细节。该应用程序在本地运行良好(当我打开 2 个浏览器选项卡并通过它们进行通信时),但在我完成 MVP 并将其部署到 heroku 后,我发现没有人可以连接到我。发生的情况是客人加入房间,他的本地视频和我的(主机)正在工作,但我们看不到对方,主机收到客人离开对话的警报(客人离开处理程序,当冰候选状态时调用已更改)。我试过实现一个 TURN 服务器,但没有帮助。这是用户加入时调用的代码片段。(我正在从 mongoDB 数据库中获取 ice 候选者):
const iceConfiguration = { }
iceConfiguration.iceServers = [];
//turn server
iceConfiguration.iceServers.push({
url: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: 'webrtc@live.com'
},)
//stun server
iceConfiguration.iceServers.push({
urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'],
})
let peerConnection = new RTCPeerConnection(iceConfiguration.iceServers)
async function start(){
localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
remoteStream = new MediaStream()
localStream.getTracks().forEach((track) => {
peerConnection.addTrack(track, localStream);
});
peerConnection.ontrack = (event) => {
console.log(event.streams[0])
event.streams[0].getTracks().forEach((track) => {
remoteStream.addTrack(track);
});
};
webcamVideo.srcObject = localStream;
remoteVideo.srcObject = remoteStream;
webcamVideo.muted = true
peerConnection.oniceconnectionstatechange = async function() {
if(peerConnection.iceConnectionState == 'disconnected') {
if (username == host){
alert("guest left")
await fetch(`/session/${interviewId}/removeGuest`, {method: "PUT"})
peerConnection.close()
peerConnection = new RTCPeerConnection(iceConfiguration.iceServers)
start()
}else{
handleHostDisconnect()
}
}
}
if (username === host){
peerConnection.onicecandidate = () => {
console.log("New ice candidate")
}
const sendChannel = peerConnection.createDataChannel("sendChannel");
sendChannel.onopen = () => canSendMessages = true;
sendChannel.onclose = () => console.log("closed!!!!!!");
const offerDescription = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offerDescription);
const body = JSON.stringify({
hostOffer: JSON.stringify(peerConnection.localDescription.toJSON())
})
fetch(`/session/${interviewId}/hostOffer`, {
method: "PUT",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body
})
const controller = new AbortController()
const interval = setInterval(async ()=>{
const res = await fetch(`/session/${interviewId}/get`, {
"signal": controller.signal
})
const data = await res.json()
if (data.guestAnswer){
controller.abort()
clearInterval(interval)
await peerConnection.setRemoteDescription(JSON.parse(data.guestAnswer))
}
}, 2500)
}
//GUEST JOINING
else{
peerConnection.onicecandidate = async () =>{
console.log("JSON.stringify(peerConnection.localDescription)")
const body = JSON.stringify({
guestAnswer: JSON.stringify(peerConnection.localDescription)
})
await fetch(`/session/${interviewId}/guestAnswer`, {
method: "PUT",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body
})
}
peerConnection.ondatachannel = (ev) =>{
const receiveChannel = ev.channel
receiveChannel.onopen = () => canSendMessages = true;
receiveChannel.onclose = () => console.log("closed!!!!!!");
peerConnection.channel = receiveChannel;
}
const res = await fetch(`/session/${interviewId}/get`)
const interview = await res.json()
await peerConnection.setRemoteDescription(JSON.parse(interview.hostOffer))
const localDesc = await peerConnection.createAnswer()
await peerConnection.setLocalDescription(localDesc)
otherNameLabel.textContent = interview.host
otherUser = interview.host
}
}
抱歉,如果代码有点混乱,我尝试删除尽可能多的不相关行。不要被“面试”标签所迷惑,它是一个会话,因为这个网络应用程序旨在简化编码面试。堆栈:Node.js、MongoDB、Express、hbs
解决方案
您使用的 TURN 凭据无效。这可以使用涓流冰测试页面来确认。如果证书有效,您将获得一名接力候选人。
您可以运行自己的 TURN 服务器,也可以付费购买托管服务器。
如果您从双方发布候选人,您将获得更高的连接成功率。现在你只有一个onicecandidate
时间if (username !== host)
推荐阅读
- sonarqube - 在詹金斯的 JAVA_HOME 中找不到“java”可执行文件
- typescript - 打字稿导入/导出给出“SyntaxError: Unexpected token 'export'”
- ios - @import geolocator:找不到模块'geolocator'
- html - 为什么将背景附件从滚动更改为固定更改此背景图像的宽度?
- sql - 字符串中有“时如何更新sql中的列值
- javascript - 尝试添加键以减少对象时,Typescript groupBy“不能用于索引类型'{}'”
- java - 如何解决持久化 mapDB 的问题?
- c++ - 堆上的页面对齐内存分配是否有任何优化或不同的 API?
- python - 在python中生成随机数流
- python - 在python字典中填写值