我工作了几个小时才能让简单的WebRTC运行起来。但是select distinct(ID) AS ID
,'' AS OUTPUT_TYPE
, (
select top 1
NOTE_TEXT
from [table] AS t
where NOTE_TEXT is not null
and NOTE_TEXT != ''
and t.SUPPLIER_ID = s.SUPPLIER_ID
) as NOTE_TEXT
from [table] as s
没有被调用(除了空候选者)。此外,在接受要约后,被叫方将触发onicecandidate
事件。我认为这应该只在创建报价后才会发生。我几乎阅读了互联网上的每个WebRTC示例,但我没有发现我的错误。
事件处理程序仅记录。
初始化:
negotationneeded
呼叫者:
this.ws = new WebSocket('ws://localhost:8443');
this.pc = new RTCPeerConnection(this.configuration);
var mediaConstraints = { audio: true, video: false };
var self = this;
this.pc.onicecandidate = this.gotIceCandidate.bind(this);
this.pc.onaddstream = this.handleAddStream.bind(this);
this.pc.onremovestream = this.handleRemoveStream.bind(this);
this.pc.oniceconnectionstatechange = this.handleICEConnectionStateChange.bind(this);
this.pc.onicegatheringstatechange = this.handleICEGatheringStateChange.bind(this);
this.pc.onsignalingstatechange = this.handleSignalingStateChange.bind(this);
this.pc.onnegotiationneeded = this.handleNegotiationNeeded.bind(this);
被叫方:
if (!location.hash) { //the caller has a location.hash
self.initiator = true;
self.hash = self.createHash();
this.ws.onopen = () => {
this.localStream = new MediaStream();
navigator.mediaDevices.getUserMedia(mediaConstraints).then((stream) => {
//this.pc.onaddstream({stream:stream});
this.localStream = stream;
return this.pc.addStream(stream);
}).then(
() => {
return this.pc.createOffer();
}).then(
(desc) => {
return this.pc.setLocalDescription(desc)
}
).then(
() => {
let data = JSON.stringify({
'sdp': this.pc.localDescription,
'hash': this.hash,
'initiator': this.initiator
});
this.ws.send(data);
console.log("sdp send:" + data);
}).catch(this.error);
}
this.ws.onmessage = function (msgRaw) {
let msg = JSON.parse(msgRaw.data);
console.log("recieved a msg for initiator: " + msgRaw.data);
if (msg.sdp) {
self.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp)).then(
function () {
console.log("initiator remote location set")
}
);
}
if (msg.ice) {
console.log("got ice message for initiator" + msg.ice);
self.setIceCandiate(msg.ice);
}
}
}
Event HAndler:
else {
this.ws.onmessage = (msgRaw) => {
console.log("recieved a msg for caller: " + msgRaw.data);
let msg = JSON.parse(msgRaw.data);
if (msg.sdp) {
console.log("recieved a sdp for caller: " + msg.sdp.type + msg.sdp.sdp);
self.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp)).then(
(() => {
return navigator.mediaDevices.getUserMedia(mediaConstraints);
})
).then(
(stream) => {
//hier stream handlen
this.localStream = stream;
return this.pc.addStream(stream);
}
).then(() => {
return this.pc.createAnswer()
})
.then(
(desc) => {
return this.pc.setLocalDescription(desc)
}
).then(() => {
var data = JSON.stringify({
'sdp': this.pc.localDescription,
'initiator': this.initiator, 'hash': this.hash
});
console.log(data);
this.ws.send(data);
}).catch(this.error);
}
else if (msg.ice) {
console.log("got ice message for caller" + msg.ice);
self.setIceCandiate(msg.ice);
}
}
this.hash = location.hash;
this.initiator = false;
this.ws.onopen = function () {
self.ws.send(JSON.stringify({
'hash': self.hash,
'initiator': self.initiator
}));
}
}
这是调用者的日志(登录Opera Dev Tools控制台):
handleAddStream(): void {
console.log("handleAddStream");
}
handleRemoveStream(): void {
console.log("handleRemoveStream");
}
handleICEConnectionStateChange(): void {
console.log("handle ICE connection state change:" + this.pc.iceConnectionState);
}
handleICEGatheringStateChange(): void {
console.log("handle ICE gathering state change: " + this.pc.iceGatheringState);
}
handleSignalingStateChange(): void {
console.log("handle Signaling state change: " + this.pc.signalingState);
}
handleNegotiationNeeded(): void {
console.log("handle negaotation needed");
}
gotIceCandidate(evt:RTCPeerConnectionIceEvent) {
console.log("onIceCandidate: " + evt.candidate);
if (evt.candidate != null) {
console.log("got ice candidate");
this.ws.send(JSON.stringify({
'ice': evt.candidate,
'initiator': this.initiator, 'hash': this.hash
})
)
}
}
被叫方的日志:
handle negaotation needed
bundle.js:83572 sdp send:{"sdp":{"type":"offer","sdp":"v=0\r\no=- 1136332092735661893 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio\r\na=msid-semantic: WMS UAGAiTGJkol3ekmevak1bV3v5qAciinhzlKh\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:AMaT\r\na=ice-pwd:kl8Hzi7+XMuD5KhcteFZKBPM\r\na=ice-options:trickle\r\na=fingerprint:sha-256 32:F2:9A:92:09:8A:17:A6:52:20:88:01:FA:83:50:FC:6C:85:D0:51:1C:E4:81:88:36:C0:F6:34:F9:AF:20:10\r\na=setup:actpass\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:110 telephone-event/48000\r\na=rtpmap:112 telephone-event/32000\r\na=rtpmap:113 telephone-event/16000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:3433491845 cname:WBo9Ljf049MIHSUN\r\na=ssrc:3433491845 msid:UAGAiTGJkol3ekmevak1bV3v5qAciinhzlKh ad862009-7cc9-44a0-99f8-db76d6bf6d42\r\na=ssrc:3433491845 mslabel:UAGAiTGJkol3ekmevak1bV3v5qAciinhzlKh\r\na=ssrc:3433491845 label:ad862009-7cc9-44a0-99f8-db76d6bf6d42\r\n"},"hash":"b5fe2d","initiator":true}
bundle.js:83643 handle Signaling state change: have-local-offer
bundle.js:83640 handle ICE gathering state change: gathering
bundle.js:83640 handle ICE gathering state change: complete
bundle.js:83670 onIceCandidate: null
bundle.js:83577 recieved a msg for initiator: {"sdp":{"type":"answer","sdp":"v=0\r\no=- 6491298606329810899 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio\r\na=msid-semantic: WMS o7uVOFEMUCnV4NwOSj64rYW9E1FfFXBxxABe\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:nVAM\r\na=ice-pwd:FuhqvuJNyzJosJbyoNjlRPnc\r\na=ice-options:trickle\r\na=fingerprint:sha-256 3C:8D:2D:AE:29:D2:88:1E:D1:56:11:B9:EE:CC:2F:6D:D8:8E:41:71:ED:D2:6D:BC:79:FD:12:21:FA:C4:44:43\r\na=setup:active\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:110 telephone-event/48000\r\na=rtpmap:112 telephone-event/32000\r\na=rtpmap:113 telephone-event/16000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:1112390810 cname:P9L/gZVWuFwyyY7Y\r\na=ssrc:1112390810 msid:o7uVOFEMUCnV4NwOSj64rYW9E1FfFXBxxABe 26d25a55-d006-4b21-8219-5ad387146d52\r\na=ssrc:1112390810 mslabel:o7uVOFEMUCnV4NwOSj64rYW9E1FfFXBxxABe\r\na=ssrc:1112390810 label:26d25a55-d006-4b21-8219-5ad387146d52\r\n"}}
bundle.js:83643 handle Signaling state change: stable
bundle.js:83637 handle ICE connection state change:checking
bundle.js:83580 initiator remote location set
bundle.js:83631 handleAddStream