webrtc不支持怎么调用设想吐_如何在Chrome中为WebRTC调用者设置远程描述而不出错?...

I hope there is no flaw in the logic.

Step 1: caller creates offer

Step 2: caller sets localDescription

Step 3: caller sends the description to the callee

//------------------------------------------------------//

Step 4: callee receives the offer sets remote description

Step 5: callee creates answer

Step 6: callee sets local description

Step 7: callee send the description to caller

//------------------------------------------------------//

Step 8: caller receives the answer and sets remote description

And here is the code for the above

const socket = io();

const constraints = {

audio: true,

video: true

};

const configuration = {

iceServers: [{

"url": "stun:23.21.150.121"

}, {

"url": "stun:stun.l.google.com:19302"

}]

};

const selfView = $('#selfView')[0];

const remoteView = $('#remoteView')[0];

var pc = new RTCPeerConnection(configuration);

pc.onicecandidate = ({

candidate

}) => {

socket.emit('message', {

to: $('#remote').val(),

candidate: candidate

});

};

pc.onnegotiationneeded = async () => {

try {

await pc.setLocalDescription(await pc.createOffer());

socket.emit('message', {

to: $('#remote').val(),

desc: pc.localDescription

});

} catch (err) {

console.error(err);

}

};

pc.ontrack = (event) => {

// don't set srcObject again if it is already set.

if (remoteView.srcObject) return;

remoteView.srcObject = event.streams[0];

};

socket.on('message', async ({

from,

desc,

candidate

}) => {

$('#remote').val(from);

try {

if (desc) {

// if we get an offer, we need to reply with an answer

if (desc.type === 'offer') {

await pc.setRemoteDescription(desc);

const stream = await navigator.mediaDevices.getUserMedia(constraints);

stream.getTracks().forEach((track) => pc.addTrack(track, stream));

selfView.srcObject = stream;

await pc.setLocalDescription(await pc.createAnswer());

console.log(pc.localDescription);

socket.emit({

to: from,

desc: pc.localDescription

});

} else if (desc.type === 'answer') {

await pc.setRemoteDescription(desc).catch(err => console.log(err));

} else {

console.log('Unsupported SDP type.');

}

} else if (candidate) {

await pc.addIceCandidate(new RTCIceCandidate(candidate)).catch(err => console.log(err));

}

} catch (err) {

console.error(err);

}

});

async function start() {

try {

// get local stream, show it in self-view and add it to be sent

const stream = await requestUserMedia(constraints);

stream.getTracks().forEach((track) => pc.addTrack(track, stream));

attachMediaStream(selfView, stream);

} catch (err) {

console.error(err);

}

}

socket.on('id', (data) => {

$('#myid').text(data.id);

});

// this function is called once the caller hits connect after inserting the unique id of the callee

async function connect() {

try {

await pc.setLocalDescription(await pc.createOffer());

socket.emit('message', {

to: $('#remote').val(),

desc: pc.localDescription

});

} catch (err) {

console.error(err);

}

}

socket.on('error', data => {

console.log(data);

});

Now this code throws an error while executing Step 8

DOMException: Failed to execute 'setRemoteDescription' on

'RTCPeerConnection': Failed to set remote offer sdp: Called in wrong

state: kHaveLocalOffer

DOMException: Failed to execute 'addIceCandidate' on

'RTCPeerConnection': Error processing ICE candidate

Tried to debug but didn't find any flaw in the logic or code. Noticed one weird thing that the the pc object has localDescription and currentLocalDescription and i think the callee who creates the answer must have both the description type to be answer but instead shows the localDescription to be offer and currentLocalDescription type is answer.

I have no idea if it is supposed to behave like that or not as I am begginer.

Thanks in advance.

解决方案

Your code is correct. This is a long-standing bug in Chrome with negotiationneeded.

I've instrumented it in a fiddle (right-click and open in TWO adjacent windows, then click call in one).

In Firefox, it works. The offerer negotiates once because you add two tracks (video/audio) at once:

negotiating in stable

onmessage answer

and, on the answerer side, the tracks you add outside of 'stable' state are added to the answer:

onmessage offer

adding audio track

adding video track

But in Chrome, it's broken, firing negotiationneeded twice on the offerer, once per track added:

negotiating in stable

negotiating in stable

onmessage offer

DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection':

Failed to set remote offer sdp: Called in wrong state: kHaveLocalOffer

onmessage offer

DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection':

Failed to set remote offer sdp: Called in wrong state: kHaveLocalOffer

onmessage offer

DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection':

Failed to set remote offer sdp: Called in wrong state: kHaveLocalOffer

and firing negotiationneeded twice on the answerer side, which isn't even in 'stable' state:

onmessage offer

adding audio track

adding video track

negotiating in have-remote-offer

negotiating in have-remote-offer

onmessage offer

DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection':

Failed to set remote offer sdp: Called in wrong state: kHaveLocalOffer

These extra events cause the havoc of reciprocal state errors seen on both ends here.

To be specific, Chrome violates two parts of the spec here:

"Queue a task" to fire this event. "queueing prevents negotiationneeded from firing prematurely, in the common situation where multiple modifications to connection are being made at once."

If connection's signaling state is not "stable", abort these steps [to fire the event].

Workaround

Working around both Chrome bugs requires (using async/await for brevity):

let negotiating = false;

pc.onnegotiationneeded = async e => {

try {

if (negotiating || pc.signalingState != "stable") return;

negotiating = true;

/* Your async/await-using code goes here */

} finally {

negotiating = false;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值