【发布时间】:2015-07-06 09:35:03
【问题描述】:
我正在尝试使用浏览器中可用的 API 来实现 webRTC。我以本教程为指导:https://www.webrtc-experiment.com/docs/WebRTC-PeerConnection.html
这是我目前正在做的事情。首先,我在页面中获取音频元素。我还有一个audioStream 变量,用于存储当发起用户单击呼叫按钮或接收用户单击应答按钮时从navigator.webkitGetUserMedia 获得的流。然后是一个用于存储当前调用的变量。
var audio = document.querySelector('audio');
var audioStream;
var call = {};
然后我有以下设置:
var iceServers = [
{ url: 'stun:stun1.l.google.com:19302' },
{ url: 'turn:numb.viagenie.ca', credential: 'muazkh', username: 'webrtc@live.com' }
];
var sdpConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: false
}
};
var DtlsSrtpKeyAgreement = {
DtlsSrtpKeyAgreement: true
};
在页面加载时,我创建了一个新的对等点:
var peer = new webkitRTCPeerConnection({
'iceServers': iceServers
});
在添加流事件上,我只是将事件分配给调用变量。
peer.onaddstream = function(event){
call = event;
};
在ice 候选人事件中,我将候选人发送给peer。
peer.onicecandidate = function(event){
var candidate = event.candidate;
if(candidate){
SocketService.emit('message', {
'conversation_id': me.conversation_id,
'targetUser': to,
'candidate': candidate
});
}
if(typeof candidate == 'undefined'){
send_SDP();
}
};
一旦收集状态完成,我就发送 SDP。
peer.ongatheringchange = function(e){
if(e.currentTarget && e.currentTarget.iceGatheringState === 'complete'){
send_SDP();
}
};
send_SDP 方法所做的是将本地描述发送给对等体。
function send_SDP(){
SocketService.emit('message', {
'conversation_id': me.conversation_id,
'targetUser': to,
'sdp': peer.localDescription
});
}
这是我在 CALL 按钮的事件侦听器中的内容。 因此,它首先获取音频,然后将流分配给当前对等对象。然后它创建一个新的报价,它是成功的,本地描述被设置,一旦完成,它就会向另一个对等方发送报价。
getAudio(
function(stream){
peer.addStream(stream);
audioStream = stream;
peer.createOffer(function(offerSDP){
peer.setLocalDescription(offerSDP, function(){
SocketService.emit('message', {
'conversation_id': me.conversation_id,
'targetUser': to,
'offerSDP': offerSDP
});
},
function(){});
},
function(){},
sdpConstraints
);
},
function(err){});
在接收对等方上,报价被捕获,因此它显示有人正在调用的模式。然后接收对等方可以单击 ANSWER 按钮。但在这里,我什至在单击 ANSWER 按钮之前就使用优惠设置会话描述。
SocketService.on('message', function(msg){
if(msg.offerSDP){
//show calling modal on the receiving peer
var remoteDescription = new RTCSessionDescription(msg.offerSDP);
peer.setRemoteDescription(remoteDescription, function(){
createAnswer(msg.offerSDP);
},
function(){});
}
});
一旦设置了远程描述,就会创建答案。首先通过获取音频然后将流添加到本地对等对象。接下来,使用offerSDP 创建远程会话描述,然后将此远程会话描述设置为本地对等对象。之后,创建应答,在本地对等体上设置本地描述,然后将 answerSDP 发送给发起呼叫的对等体。
function createAnswer(offerSDP) {
getAudio(
function(stream){
peer.addStream(stream);
audioStream = stream;
var remoteDescription = new RTCSessionDescription(offerSDP);
peer.setRemoteDescription(remoteDescription);
peer.createAnswer(function(answerSDP) {
peer.setLocalDescription(answerSDP, function(){
SocketService.emit('message', {
'conversation_id': me.conversation_id,
'targetUser': to,
'answerSDP': answerSDP
});
},
function(){});
}, function(err){}, sdpConstraints);
},
function(err){
}
);
};
发起呼叫的对等方收到answerSDP。完成后,它会使用answerSDP 创建远程描述,并使用它为其本地对等对象设置远程描述
if(msg.answerSDP){
var remoteDescription = new RTCSessionDescription(msg.answerSDP);
peer.setRemoteDescription(remoteDescription, function(){
},
function(){});
}
在那之后,我不确定接下来会发生什么。根据我的理解,onicecandidate 事件在发起对等方(调用方)上触发,并将候选人发送到接收对等方。然后执行以下代码:
if(msg.candidate){
var candidate = msg.candidate.candidate;
var sdpMLineIndex = msg.candidate.sdpMLineIndex;
peer.addIceCandidate(new RTCIceCandidate({
sdpMLineIndex: sdpMLineIndex,
candidate: candidate
}));
}
现在,一旦单击 ANSWER 按钮,就会向接收对等方拾取的发起对等方发送一条消息。它使用调用流作为音频元素的来源,一旦加载了所有元数据,它就会播放音频。
SocketService.emit('message', {
'answerCall': true,
'conversation_id': me.conversation_id,
'targetUser': to
});
audio.src = window.URL.createObjectURL(call.stream);
audio.onloadedmetadata = function(e){
audio.play();
}
这里可能有问题。这就是为什么音频只有单向的原因。只有发起呼叫的用户才能听到接收用户的输入。发起用户发出的声音也可以听到,所以就像在呼应你所说的一样。有什么想法吗?
如果您知道任何说明如何使用本机 API 调用实现 webRTC 的教程或书籍,那也会有所帮助。提前致谢。
【问题讨论】:
-
您在这里使用过时的 API 硬编码到特定的浏览器 (Chrome),而不是使用 the standard。我可以建议使用 adapter.js 跨浏览器的 polyfill 吗?
标签: javascript webrtc