问题描述
在进行视频聊天时,我遇到了addIceCandidate的错误。有时它工作正常,有时则不行。我发现直接进入视频路线时,视频聊天功能正常。但是,如果我以编程方式进行操作,则无法正常工作,则显示错误。
以编程方式表示,在我的应用程序中,对于视频聊天,应该将请求发送给另一位用户。并且在接受两个用户都可以重定向到视频路由之后。我使用Firebase对其进行了管理。当两个用户都在视频路线上并且其中一个发送了创建要约请求时,在另一端(即在另一用户端)显示:
无法在“ RTCPeerConnection”上执行“ addIceCandidate”:处理ICE候选者时出错
这是我的videoChat组件videoChat.js
const localVideoRef = useRef();
const remoteVideoRef = useRef();
const pc_config = {
iceServers: [
{
urls: "stun:stun.l.google.com:19302",},],};
let pc = new RTCPeerConnection(pc_config);
let recordedChunks = [];
useEffect(() => {
if (
localStorage.getItem("id") &&
localStorage.getItem("debateAccountToken") &&
localStorage.getItem("email")
) {
socket.current = io.connect("http://localhost:8000/webrtcPeer");
socket.current.on("connection-success",(success) => {
console.log("connection... ",success);
});
// when createOffer() called this event is fired
socket.current.on("offerOrAnswer",async (sdp) => {
console.log("offerOrAnswer event called",sdp);
let sessionDesc = await new RTCSessionDescription(sdp);
pc.setRemoteDescription(sessionDesc)
.then((result) => {
console.log("result...",result);
})
.catch((err) => {
console.log("errr.. ",err);
});
});
// createOffer() is also calling candidate event
socket.current.on("candidate",async (candidate) => {
console.log("candidate.. ");
const newCandidate = await new RTCIceCandidate(candidate);
if (candidate) await pc.addIceCandidate(newCandidate);
});
pc.onicecandidate = (e) => {
console.log("on ice candidate.. ",e);
if (!e || !e.candidate) return;
if (e.candidate) {
sendToPeer("candidate",e.candidate);
}
};
pc.oniceconnectionstatechange = (e) => {
console.log("e... ",e);
if (
e.target.connectionState == "connected" ||
e.target.connectionState == "connecting"
) {
const options = { mimeType: "video/webm; codecs=vp9" };
recordScreen()
.then((captureStream) => {
mediaRecorder = new MediaRecorder(captureStream,options);
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start();
setTimeout((event) => {
console.log("stopping",mediaRecorder.state);
mediaRecorder.stop();
captureStream.getTracks().forEach((track) => track.stop());
captureStream.oninactive = (ev) => {
console.log("on remove track ",ev);
socket.current.emit("disconnect");
socket.current.disconnect();
console.log("socket disconnected",mediaRecorder.state);
pc.close();
};
},30000);
})
.catch((err) => console.log("error in record screen ",err));
}
};
// createOffer() will call ontrack event
pc.ontrack = (e) => {
remoteVideoRef.current.srcObject = e.streams[0];
};
pc.onnegotiationneeded = async () => {
const offer = await pc.createOffer();
console.log("offer created.. ",offer);
if (pc.signalingState != "stable") return;
await pc.setLocalDescription(offer);
};
navigator.mediaDevices
.getUserMedia({ video: true,audio: true })
.then((stream) => {
window.localStream = stream;
localVideoRef.current.srcObject = stream;
stream.getTracks().forEach((track) => pc.addTrack(track,stream));
})
.catch((error) => {
console.log("errror.. ",error.toString());
toast.error(error);
});
} else {
history.push("/");
}
},[]);
const sendToPeer = (messageType,payload) => {
console.log("send to peer fn called...",messageType,payload);
socket.current.emit(messageType,{
socketID: socket.current.id,payload,});
};
const handleDataAvailable = async (event) => {
console.log("data-available",event);
if (event.data.size > 0) {
recordedChunks.push(event.data);
download();
} else {
// ...
console.log("in else");
}
};
const download = async () => {
console.log("in download fn");
var blob = await new Blob(recordedChunks,{
type: "video/mp4",});
var url = URL.createObjectURL(blob);
// api call
};
const createOffer = () => {
console.log("offer created ");
pc.createOffer({ offerToReceiveAudio: 1,offerToReceiveVideo: 1 }).then(
(sdp) => {
console.log("sdp... ",sdp);
pc.setLocalDescription(sdp);
sendToPeer("offerOrAnswer",sdp);
}
);
};
const createAnswer = () => {
console.log("answer.. ");
pc.createAnswer({ offerToReceiveVideo: 1,offerToReceiveAudio: 1 })
.then((sdp) => {
pc.setLocalDescription(sdp);
sendToPeer("offerOrAnswer",sdp);
setCallAccepted(true);
})
.catch((error) => {
console.log("error in create answer",error);
});
};
async function recordScreen() {
console.log("recordScreen fn called");
let captureStream = null;
return navigator.mediaDevices
.getdisplayMedia({
video: true,audio: true,})
.catch((err) => {
console.error("Error:" + err);
return null;
});
}
return (
<div className="row" style={{ marginLeft: "5px" }}>
<div className="col-6">
<video
style={{ width: "65%",height: "65%" }}
controls
ref={localVideoRef}
autoplay
></video>
</div>
<div className="col-6">
<video
style={{ width: "65%",height: "65%" }}
controls
ref={remoteVideoRef}
autoplay
></video>
</div>
</div>
<button onClick={createOffer}>Offer</button>
<button onClick={createAnswer}>Answer</button>
)
这是我在节点js中的后端主文件:
const express = require("express");
const http = require("http");
const app = express();
const server = http.createServer(app);
const socket = require("socket.io");
const io = socket(server);
const peers = io.of("/webrtcPeer");
let connectedPeers = new Map();
peers.on("connection",(socket) => {
console.log("connection established.. ",socket.id);
socket.emit("connection-success",{ success: socket.id });
connectedPeers.set(socket.id,socket);
socket.on("disconnect",() => {
console.log("disconnected");
connectedPeers.delete(socket.id);
});
socket.on("offerOrAnswer",(data) => {
for (const [socketID,socket] of connectedPeers.entries()) {
if (socketID !== data.socketID) {
console.log("offerOrAnswer ",socketID,data.payload.type);
socket.emit("offerOrAnswer",data.payload);
}
}
});
socket.on("candidate",(data) => {
// send candidate to the other peer(s) if any
for (const [socketID,socket] of connectedPeers.entries()) {
// don't send to self
if (socketID !== data.socketID) {
console.log("on candidate event ",data);
socket.emit("candidate",data.payload);
}
}
});
});
此addIceCandidate错误不会再出现,最初是显示此错误无法创建答案。也许我在某个地方弄错了。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)