作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
<分区>
我正在实现 WebRTC 点对点调用,它在所有浏览器中运行良好,除非 chrome 是调用初始化程序(调用邀请函数)。
如果 chrome 是 call initializer,ICE 连接状态变为 connected 并且视频出现在另一个 peer 中,然后会出现错误“DOMException: “Cannot create answer in state stable”' 并且视频停止传输到另一个 peer同行。
如果接收器也是 chrome,则错误显示“无法在‘RTCPeerConnection’上执行‘createAnswer’:PeerConnection 无法在 have-remote-offer 或 have-local-pranswer 以外的状态下创建答案。”
这些是 handleVideoOfferMsg 函数和 handleGetUserMediaError 函数(触发错误)代码:
function handleVideoOfferMsg(msg) {
// debugger;
// $("#ring")[0].play();
var localStream = null;
targetUsername = msg.from;
// Call createPeerConnection() to create the RTCPeerConnection.
log("Starting to accept invitation from " + targetUsername);
createPeerConnection();
// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.
var desc = new RTCSessionDescription(msg.sdp);
myPeerConnection.setRemoteDescription(desc).then(function () {
log("Setting up the local media stream...");
return navigator.mediaDevices.getUserMedia(responserConstraints);
})
.then(function(stream) {
$("#video-container").removeClass("hidden");
log("-- Local video stream obtained");
localStream = stream;
if(responserConstraints.hasOwnProperty('video'))
{
$("#localVideo").removeClass('hidden')[0].srcObject = localStream;
}
log("-- Adding outgoing tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.then(function() {
log("------> Creating answer");
// Now that we've successfully set the remote description, we need to
// start our stream up locally then create an SDP answer. This SDP
// data describes the local end of our call, including the codec
// information, options agreed upon, and so forth.
return myPeerConnection.createAnswer();
})
.then(function(answer) {
log("------> Setting local description after creating answer");
// We now have our answer, so establish that as the local description.
// This actually configures our end of the call to match the settings
// specified in the SDP.
return myPeerConnection.setLocalDescription(answer);
})
.then(function() {
var msg = {
name: myUsername,
target: targetUsername,
type: "video-answer",
sdp: myPeerConnection.localDescription
};
// We've configured our end of the call now. Time to send our
// answer back to the caller so they know that we want to talk
// and how to talk to us.
log("Sending answer packet back to other peer");
sendToServer(msg);
})
.catch(
handleGetUserMediaError);
}
function handleGetUserMediaError(e) {
log(e);
switch(e.name) {
case "NotFoundError":
alert("Unable to open your call because no camera and/or microphone" +
"were found.");
break;
case "SecurityError":
case "PermissionDeniedError":
// Do nothing; this is the same as the user canceling the call.
break;
default:
//the error occur here
alert("Error opening your camera and/or microphone: " + e.message);
console.log("----------");
console.log(e);
break;
}
// Make sure we shut down our end of the RTCPeerConnection so we're
// ready to try again.
closeVideoCall();
}
邀请函数:
function invite() {
log("Starting to prepare an invitation");
if (myPeerConnection) {
alert("You can't start a call because you already have one open!");
} else {
var clickedUsername = $("input[name=teacherId]").val();
console.log('user id is '+ clickedUsername);
// Don't allow users to call themselves, because weird.
if (clickedUsername === myUsername) {
alert("I'm afraid I can't let you talk to yourself. That would be weird.");
return;
}
// Record the username being called for future reference
targetUsername = clickedUsername;
log("Inviting user " + targetUsername);
// Call createPeerConnection() to create the RTCPeerConnection.
log("Setting up connection to invite user: " + targetUsername);
createPeerConnection();
// Now configure and create the local stream, attach it to the
// "preview" box (id "video"), and add it to the
// RTCPeerConnection.
log("Requesting webcam access...");
isInviter = true;
navigator.mediaDevices.getUserMedia(mediaConstraints)
.then(function(localStream) {
$("#video-container").removeClass("hidden");
console.log(localStream);
log("-- Local video stream obtained");
if(responserConstraints.hasOwnProperty('video'))
{
var localVideo = $('#localVideo');
localVideo.removeClass('hidden')[0].srcObject = localStream;
localVideo[0].mute;
}
else
{
var videoEl = document.getElementById("video");
videoEl.muted = true;
videoEl.srcObject = localStream;
}
log("-- Adding incoming tracks to the RTCPeerConnection");
localStream.getTracks().forEach(track => myPeerConnection.addTrack(track, localStream));
})
.catch(handleGetUserMediaError);
}
}
控制台响应如下:
[3:28:31 PM] *** ICE gathering state changed to: gathering
opensocket.js:66 [3:28:31 PM] Outgoing ICE candidate: candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10
opensocket.js:66 [3:28:31 PM] Sending 'new-ice-candidate' message: {"type":"new-ice-candidate","candidate":{"candidate":"candidate:202810205 1 udp 2122260223 192.168.1.21 39265 typ host generation 0 ufrag 76SW network-id 1 network-cost 10","sdpMid":"audio","sdpMLineIndex":0,"usernameFragment":"76SW"},"hash":"m0wk8Kaz8JFejuJGte7kAmNtYDiWPZNBGl7fKA5b"}
opensocket.js:66 [3:28:31 PM] -- Local video stream obtained
opensocket.js:66 [3:28:31 PM] -- Adding outgoing tracks to the RTCPeerConnection
opensocket.js:66 [3:28:31 PM] ------> Creating answer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:363 stable
opensocket.js:66 [3:28:31 PM] *** Negotiation needed
opensocket.js:66 [3:28:31 PM] ---> Creating offer
opensocket.js:66 [3:28:31 PM] InvalidStateError: Failed to execute 'createAnswer' on 'RTCPeerConnection': PeerConnection cannot create an answer in a state other than have-remote-offer or have-local-pranswer.
我找不到解决它的方法!错误只发生在 chrome 中!
有什么帮助吗?
编辑:这是我的 handleNegotiationNeededEvent 函数:
function handleNegotiationNeededEvent() {
console.log(myPeerConnection.signalingState);
log("*** Negotiation needed");
log("---> Creating offer");
myPeerConnection.createOffer().then(function(offer) {
log("---> Creating new description object to send to remote peer");
return myPeerConnection.setLocalDescription(offer);
})
.then(function() {
log("---> Sending offer to remote peer");
sendToServer({
name: myUsername,
target: targetUsername,
type: "video-offer",
sdp: myPeerConnection.localDescription
});
})
.catch(reportError);
}
我是一名优秀的程序员,十分优秀!