WebRTC on AWS EC2 with TURN server on AWS EC2 on 2 different networks, error: ICE failed, add a STUN server
WebRTC on AWS EC2 with TURN server on AWS EC2 on 2 different networks, error: ICE failed, add a STUN server
目前我有一个使用 WebRTC 的视频聊天 Web 应用程序,它是用部署在 AWS EC2 实例上的 Reactjs 编写的。视频聊天与本地网络或同一互联网网络上两台不同计算机上的两个用户一起工作,我们可以轻松地交谈和看到对方。
然而,当我尝试与其他网络上的另一个用户进行视频聊天时,视频聊天停止工作并且我在 Chrome 浏览器控制台中收到如下错误消息:
Uncaught (in promise) DOMException: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
另一个用户得到:
ICE failed, add a STUN server and see about:webrtc for more details
我认为问题出在 TURN 服务器上,但是我已经使用 COTURN 设置了 TURN 服务器(https://github.com/coturn/coturn) on an AWS EC2 instance and it seems to work when I test it on https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ 在我尝试查看中继时使用相同的凭据。
我使用这个 Whosebug post 中的说明部署了 TURN 服务器:
How to create stun turn server instance using AWS EC2
我还允许对 AWS 安全组上的大量端口进行 UDP 和 TCP 的入站端口访问。
一些相关代码,这个处理我从 WebRTC 信令服务器返回的响应:
/**
* Parse a broadcast message and reply back with
* the appropriate details
*/
receiveBroadcast(packetObject) {
try {
var payload = JSON.parse(packetObject.Payload)
} catch (err) {
var payload = packetObject.Payload
}
if (payload.Type == 'Ice Offer') {
// Set remote descriptions and construct an ICE answer
var icePacket = new this.rtcSessionDescription({
type: payload.IcePacket.type,
sdp: payload.IcePacket.sdp,
})
this.peerConnection.setRemoteDescription(icePacket, function () {
this.peerConnection.createAnswer(this.onCreateAnswerSuccess.bind(this), this.onCreateSessionDescriptionError)
}.bind(this), this.onSetSessionDescriptionError)
} else if (payload.Type == 'Ice Answer') {
// Set the remote description
var icePacket = new this.rtcSessionDescription({
type: payload.IcePacket.type,
sdp: payload.IcePacket.sdp,
})
this.peerConnection.setRemoteDescription(icePacket, function () {
this.onSetRemoteSuccess()
}.bind(this), this.onSetSessionDescriptionError)
} else if (payload.Type == 'Ice Candidate') {
console.log('ICE payload :')
console.log(payload)
// Add the candidate to the list of ICE candidates
var candidate = new this.rtcIceCandidate({
sdpMLineIndex: payload.sdpMLineIndex,
sdpMid: payload.sdpMid,
candidate: payload.candidate,
})
this.peerConnection.addIceCandidate(candidate)
}
}
主要是最后一行不行。
我设置了console.logs看看流程是什么样的:
Local stream set
bundle.js:1 Video Set
bundle.js:1 setRemoteDescription complete
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:0 1 UDP 2122252543 xxx.xxx.x.xx 57253 typ host", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:1 1 UDP 2122187007 xx.xxx.x.xx 53622 typ host", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:2 1 TCP 2105524479 xxx.xxx.x.xx 9 typ host tcptype active", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:3 1 TCP 2105458943 xx.xxx.x.xx 9 typ host tcptype active", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "", sdpMid: "0"}
明白了,这是一个愚蠢的错误,我用来指定 ICE 服务器的配置 JSON 有一个额外的层,WebRTC 无法处理它。然而,WebRTC 错误消息几乎无法使用,而且信息性不强。
因此,对于任何未来坚持调试 WebRTC 的人来说,这些是我想出的步骤和我使用的资源,以便其他人可以更好地调试他们的问题。
1) Use Chrome
2) Open up in new tab chrome://webrtc-internals/
3) Open up your videochat app in another tab and observe whats happening in chrome://webrtc-internals/
4) Make sure not to close the tab with the videochat app, if you do chrome://webrtc-internals will refresh
5) Open up a working videochat app like https://morning-escarpment-67980.herokuapp.com/ which is an app built from this github repo: https://github.com/nguymin4/react-videocall
6) Compare the differences between yours and the successful video chat app's chrome://webrtc-internals
7) Use this resource to help understand error messages and more details: https://blog.codeship.com/webrtc-issues-and-how-to-debug-them/
希望这对您有所帮助。
目前我有一个使用 WebRTC 的视频聊天 Web 应用程序,它是用部署在 AWS EC2 实例上的 Reactjs 编写的。视频聊天与本地网络或同一互联网网络上两台不同计算机上的两个用户一起工作,我们可以轻松地交谈和看到对方。
然而,当我尝试与其他网络上的另一个用户进行视频聊天时,视频聊天停止工作并且我在 Chrome 浏览器控制台中收到如下错误消息:
Uncaught (in promise) DOMException: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
另一个用户得到:
ICE failed, add a STUN server and see about:webrtc for more details
我认为问题出在 TURN 服务器上,但是我已经使用 COTURN 设置了 TURN 服务器(https://github.com/coturn/coturn) on an AWS EC2 instance and it seems to work when I test it on https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ 在我尝试查看中继时使用相同的凭据。
我使用这个 Whosebug post 中的说明部署了 TURN 服务器: How to create stun turn server instance using AWS EC2
我还允许对 AWS 安全组上的大量端口进行 UDP 和 TCP 的入站端口访问。
一些相关代码,这个处理我从 WebRTC 信令服务器返回的响应:
/**
* Parse a broadcast message and reply back with
* the appropriate details
*/
receiveBroadcast(packetObject) {
try {
var payload = JSON.parse(packetObject.Payload)
} catch (err) {
var payload = packetObject.Payload
}
if (payload.Type == 'Ice Offer') {
// Set remote descriptions and construct an ICE answer
var icePacket = new this.rtcSessionDescription({
type: payload.IcePacket.type,
sdp: payload.IcePacket.sdp,
})
this.peerConnection.setRemoteDescription(icePacket, function () {
this.peerConnection.createAnswer(this.onCreateAnswerSuccess.bind(this), this.onCreateSessionDescriptionError)
}.bind(this), this.onSetSessionDescriptionError)
} else if (payload.Type == 'Ice Answer') {
// Set the remote description
var icePacket = new this.rtcSessionDescription({
type: payload.IcePacket.type,
sdp: payload.IcePacket.sdp,
})
this.peerConnection.setRemoteDescription(icePacket, function () {
this.onSetRemoteSuccess()
}.bind(this), this.onSetSessionDescriptionError)
} else if (payload.Type == 'Ice Candidate') {
console.log('ICE payload :')
console.log(payload)
// Add the candidate to the list of ICE candidates
var candidate = new this.rtcIceCandidate({
sdpMLineIndex: payload.sdpMLineIndex,
sdpMid: payload.sdpMid,
candidate: payload.candidate,
})
this.peerConnection.addIceCandidate(candidate)
}
}
主要是最后一行不行。
我设置了console.logs看看流程是什么样的:
Local stream set
bundle.js:1 Video Set
bundle.js:1 setRemoteDescription complete
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:0 1 UDP 2122252543 xxx.xxx.x.xx 57253 typ host", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:1 1 UDP 2122187007 xx.xxx.x.xx 53622 typ host", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:2 1 TCP 2105524479 xxx.xxx.x.xx 9 typ host tcptype active", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "candidate:3 1 TCP 2105458943 xx.xxx.x.xx 9 typ host tcptype active", sdpMid: "0"}
bundle.js:1 ICE payload :
bundle.js:1 {Type: "Ice Candidate", sdpMLineIndex: 0, candidate: "", sdpMid: "0"}
明白了,这是一个愚蠢的错误,我用来指定 ICE 服务器的配置 JSON 有一个额外的层,WebRTC 无法处理它。然而,WebRTC 错误消息几乎无法使用,而且信息性不强。
因此,对于任何未来坚持调试 WebRTC 的人来说,这些是我想出的步骤和我使用的资源,以便其他人可以更好地调试他们的问题。
1) Use Chrome
2) Open up in new tab chrome://webrtc-internals/
3) Open up your videochat app in another tab and observe whats happening in chrome://webrtc-internals/
4) Make sure not to close the tab with the videochat app, if you do chrome://webrtc-internals will refresh
5) Open up a working videochat app like https://morning-escarpment-67980.herokuapp.com/ which is an app built from this github repo: https://github.com/nguymin4/react-videocall
6) Compare the differences between yours and the successful video chat app's chrome://webrtc-internals
7) Use this resource to help understand error messages and more details: https://blog.codeship.com/webrtc-issues-and-how-to-debug-them/
希望这对您有所帮助。