我正在尝试基于WebRTC API实现非常简单的视频聊天。 不幸的是,到目前为止,我的代码只是从Chrome到Chrome以及Firefox到Firefox。
如果我在Chrome-to-Firefox或Firefox-to-Chrome中尝试,我会收到以下错误输出:
Failed to set local offer sdp: Session error code: ERROR_CONTENT. Session error description: Failed to set local video description recv parameters..(anonymous function) @ helloWebRtc.js:126***
我可能错过了某些内容,还是在Chrome或Firefox浏览器中需要一些标记?
你知道吗?如果我能帮助解决这个问题,我将不胜感激。提前谢谢大家!
我的helloWebRtc.js
看起来像这样:
var localVideo = document.querySelector("#localVideo");
var remoteVideo = document.querySelector("#remoteVideo");
var SIGNAL_ROOM = "signal_room";
var CHAT_ROOM = "chat_room";
var serverConfig = {
"iceServers": [
{
"urls": "stun:stun.l.google.com:19302"
}
]
};
var optionalConfig = {
optional: [
{
RtpDataChannels: true
},
{
DtlsSrtpKeyAgreement: true
}
]
};
var rtcPeerConn,
localStream;
io = io.connect();
io.emit("ready", {"chat_room": CHAT_ROOM, "signal_room": SIGNAL_ROOM});
io.emit("signal", {
"room": SIGNAL_ROOM,
"type": "user_here",
"message": "new user joined the room"
});
io.on("rtcSignaling", function(data) {
if(!rtcPeerConn) {
startSignaling();
}
if(data.type !== "user_here" && data.message) {
var message = JSON.parse(data.message);
if(message.description) {
var remoteDesc = new RTCSessionDescription(message.description);
rtcPeerConn.setRemoteDescription(remoteDesc, function() {
// if we receive an offer we need to answer
if(rtcPeerConn.remoteDescription.type === "offer") {
rtcPeerConn.createAnswer(sendLocalDescription, function(error) {
console.error("error on creating answer", error);
});
}
}, function(error) {
console.error("error on set remote description", error);
});
} else if(message.candidate) {
var iceCandidate = new RTCIceCandidate(message.candidate);
rtcPeerConn.addIceCandidate(iceCandidate);
}
}
});
function startSignaling() {
rtcPeerConn = new RTCPeerConnection(serverConfig, optionalConfig);
//send any ice candidate to the other peer
rtcPeerConn.onicecandidate = function(event) {
if(event.candidate) {
io.emit("signal", {
"room": SIGNAL_ROOM,
"type": "candidate",
"message": JSON.stringify({
"candidate": event.candidate
})
});
}
};
rtcPeerConn.onnegotiationneeded = function() {
rtcPeerConn.createOffer(sendLocalDescription, function(error) {
console.error("error on creating offer", error);
});
};
// add the other peer's stream
rtcPeerConn.onaddstream = function(event) {
console.info("on add stream called");
remoteVideo.srcObject = event.stream;
};
// add local stream
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
})
.then(function(stream) {
localVideo.srcObject = stream;
localStream = stream;
rtcPeerConn.addStream(localStream);
})
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}
function sendLocalDescription(description) {
rtcPeerConn.setLocalDescription(
description,
function() {
io.emit("signal", {
"room": SIGNAL_ROOM,
"type": "description",
"message": JSON.stringify({
"description": rtcPeerConn.localDescription
})
});
},
function(error) {
console.error("error to set local desc", error);
}
);
}
我的NodeJS服务器(使用express.io
)如下所示:
var express = require('express.io');
var app = express();
var PORT = 8686;
app.http().io();
console.log('server started @ localhost:8686');
// declaring folders to access i.e.g html files
app.use(express.static(__dirname + '/views'));
app.use('/scripts', express.static(__dirname + '/scripts'));
// root url i.e. "localhost:8686/"
app.get('/', function(req, res) {
res.sendFile('index.html');
});
/**
* Socket.IO Routes for signaling pruposes
*/
app.io.route('ready', function(req) {
req.io.join(req.data.chat_room);
req.io.join(req.data.signal_room);
app.io.room(req.data.chat_room).broadcast('announce', {
message: 'New client in the ' + req.data.chat_room + ' room.'
});
});
app.io.route('send', function(req) {
app.io.room(req.data.room).broadcast('message', {
message: req.data.message,
author: req.data.author
});
});
app.io.route('signal', function(req) {
// Note: req means just broadcasting without letting the sender also receive their own message
if(req.data.type === "description" || req.data.type === "candidate")
req.io.room(req.data.room).broadcast('rtcSignaling', {
type: req.data.type,
message: req.data.message
});
else
req.io.room(req.data.room).broadcast('rtcSignaling', {
type: req.data.type
});
});
app.listen(PORT);
答案 0 :(得分:1)
你可以比较chrome和firefox生成的商品SDP,可能会有一些与其他商品无法互操作的差异。
答案 1 :(得分:0)
在创建对等连接时,只需检查是否将DtlsSrtpKeyAgreement参数设置为true。
pc = new RTCPeerConnection(pc_config,{optional: [{RtpDataChannels: true},{
DtlsSrtpKeyAgreement: true}]});
答案 2 :(得分:0)
编辑下面的旧答案:Chrome和Firefox之间的互操作性有几个漏洞。来自webrtc团队的人给了我建议,让提议者保持同一方。因此,如果A在设置流向B时创建商品,那么当设置流向A时,B要求A创建新商品,而不是创建一个商品。
另见: https://bugs.chromium.org/p/webrtc/issues/detail?id=5499#c15
我确实注意到,如果Firefox启动会话,Chrome会将来自Firefox的流从视频元素中踢出,但您可以在流上创建新的对象URL并将其设置为源。
希望有所帮助。
旧消息:
我遇到了同样的事情,所以如果你有答案,我很好奇。
我确信FireFox与Chrome在设置DTLS角色方面存在不匹配(错误),另请参阅:
https://bugs.chromium.org/p/webrtc/issues/detail?id=2782#c26