您好,我正在尝试使用带SignalR的WebRTC和基于信号的{R {3}}建立视频聊天 错误是:
setRemoteDescription:InvalidStateError:无法设置远程答案 sdp:处于错误状态:kStable onError @ webrtc.js:26 pc.setRemoteDescription.error @ webrtc.js:101 2webrtc.js:26
func localDescCreated:OperationError:无法设置本地答案sdp: 处于错误状态:kStable onError @ webrtc.js:26 pc.setLocalDescription.error @ webrtc.js:115 3webrtc.js:26
createAnswer:InvalidStateError:PeerConnection无法创建 可以在有其他优惠或没有本地优惠的状态下回答。
还有我的js(不好意思!):
// Generate random room name if needed
if (!location.hash) {
location.hash = Math.floor(Math.random() * 0xFFFFFF).toString(16);
}
const roomHash = location.hash.substring(1);
const roomName = 'test';
const configuration = {
iceServers: [
{
'urls': [
'stun:74.125.142.127:19302',
'stun:23.21.150.121:3478'
]
}
]
};
let room;
let pc;
function onSuccess() { };
function onError(context, error) {
console.error(`${context} : ${error}`);
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("/video")
.build();
connection.on('Start', () => {
connection.invoke('JoinRoom', roomName).catch(error => onError("on invoke join room",error));
connection.invoke('GetMembers', roomName).catch(error => onError("on invoke GetMembers",error));
});
connection.on('members',
users => {
console.log('MEMBERS', users);
// If we are the second or greater user to connect to the room we will be creating the offer
users = JSON.parse(users);
const isOfferer = users.length === 2 ? true : false;
console.log("isOfferer", isOfferer);
console.log("users length = ", users.length);
startWebRTC(isOfferer);
});
// Send signaling data via signalr
function sendMessage(message) {
connection.invoke('send', message);
}
function startWebRTC(isOfferer) {
pc = new RTCPeerConnection(configuration);
// 'onicecandidate' notifies us whenever an ICE agent needs to deliver a
// message to the other peer through the signaling server
pc.onicecandidate = event => {
if (event.candidate) {
sendMessage(JSON.stringify({ 'candidate': event.candidate }));
console.log("send message - ", { 'candidate': event.candidate });
}
};
// If user is offerer let the 'negotiationneeded' event create the offer
if (isOfferer) {
pc.onnegotiationneeded = () => {
pc.createOffer().then(localDescCreated).catch(error => onError("onnegotiationneeded",error));
}
}
// When a remote stream arrives display it in the #remoteVideo element
pc.ontrack = event => {
const stream = event.streams[0];
if (!remoteVideo.srcObject || remoteVideo.srcObject.id !== stream.id) {
remoteVideo.srcObject = stream;
}
};
navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
}).then(stream => {
// Display your local video in #localVideo element
localVideo.srcObject = stream;
// Add your stream to be sent to the conneting peer
stream.getTracks().forEach(track => pc.addTrack(track, stream));
}, error => onError("adding media devices", error));
// Listen to signaling data from Scaledrone
connection.on('newMessage', (message) => {
message = JSON.parse(message);
if (message.sdp) {
// This is called after receiving an offer or answer from another peer
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), () => {
// When receiving an offer lets answer it
if (pc.remoteDescription.type === 'offer') {
pc.createAnswer().then(localDescCreated).catch(error => onError("createAnswer", error));
}
}, error => onError("setRemoteDescription", error));
} else if (message.candidate) {
// Add the new ICE candidate to our connections remote description
pc.addIceCandidate(
new RTCIceCandidate(message.candidate), onSuccess, error => onError("addIceCandidate", error)
);
}
});
}
function localDescCreated(desc) {
pc.setLocalDescription(
desc,
() => sendMessage(JSON.stringify({ 'sdp': pc.localDescription })),
error => onError("func localDescCreated", error)
);
}
connection.start().catch(err => console.error(err.toString()));