#簡單剖析webrtc,並結合easyrtc與coturn(stun,turn)服務實現音視訊聊天
-
webRTC全稱為Web Real-Time Communications,即web實時通訊
-
音視訊聊天實現前提,跟直播不一樣哦~api型別繁多,有的也過時了,見到有不同的就翻翻MDN,換個方案吧,谷歌需要https或者localhost才能開啟媒體許可權,火狐則不需要,但做相容很費工夫。localhost下就自己開兩個網頁測吧,後面會講easyrtc
- 理解websocket連線/websocket算是node.js最繁華的領域了,socket.io簡單粗暴https://github.com/socketio/socket.io.git
- 理解webrtc的工作流程 juejin.im/post/5b3f50…
- stun伺服器作用,獲取雙方ip協助建立連線
- turn伺服器作用,轉發音視訊
- 信令伺服器作用,利用socket.io實現,主要就是轉發音視訊聊天雙方的軟硬體資訊ip,裝置資訊,協助直連或者視訊轉發
-
簡化文章內容介紹,webrtc流程,以下在內網中可以執行
- 1.獲取使用者音視訊媒體,完成這步,即可看到自己的攝像頭影像
navigator.mediaDevices.getUserMedia({ audio: true, video: true, }).then((stream) => { let video = document.querySelector('#video') video.srcObject = stream // mediaDevices.getUserMedia獲取到的音視訊流捆綁在video標籤上 video.onloadedmetadata = () => video.play() // 讀取資料時進行播放 }) 複製程式碼
- 2.進行peertopeer點對點連線,
- 2-1.房主createOffer回撥中能取到房主的資訊desc,音視訊結構軟硬體資訊,儲存本地,並且傳送到信令伺服器,協助轉發
let peer = new RTCPeerConnection(servers) pc.createOffer(sendOffer, function (error) { console.log('傳送 offer 失敗') }) function sendOffer (desc) { console.log('sendOffer') pc.setLocalDescription(desc); socket.emit('offer', JSON.stringify({ data: {sdp: desc} }) ) } 複製程式碼
- 2-2.房主createOffer時會觸發自身連線的onicecandidate事件,獲取candidate,使用者地址等
pc.onicecandidate = function(event) { if (event.candidate !== null) { socket.emit("_ice_candidate",JSON.stringify({ type: '_candidate', data: { candidate: event.candidate } }) ) } }; 複製程式碼
- 2-3.對方在socket中收到offer時,將其設定為遠端描述,offer對應的為answer,建立時會觸發該使用者的onicecandidate事件,能獲得到其使用者地址資訊,此時將描述發給房主
socket.on('offer', function(e) { getUserMedia(function (stream) { let vid1 = document.getElementById('vid1') vid1.srcObject = stream vid1.onloadedmetadata = function(e) { vid1.play(); }; pc.addStream(stream) var json = JSON.parse(e) pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp)); pc.createAnswer(sendAnswer, function (error) { console.log('建立answer失敗') }) }, function (error) { console.log('攝像頭獲取失敗', '接聽視訊失敗'); }) }) function sendAnswer(desc) { pc.setLocalDescription(desc); socket.emit('answer', JSON.stringify({ type: '_answer', data: { sdp: desc } })) } 複製程式碼
- 2-4.房主在接收answer的socket事件中將其設定為遠端描述
socket.on('answer', async function(e) { let data = e.message await peer.setRemoteDescription(data) }) 複製程式碼
-
外網實現點對點音視訊聊天 ICE(結合stun,turn進行穿透獲取音視訊雙方地址)
- STUN解析
- 但現實中我們的視訊通話,不可能侷限在內網,可能會在防火牆,NAT之後,點對點連線之前,我們需要檢測是否能進行,該技術稱為NAT穿透,通常基於UDP協議,如RFC3489。在新的RFC5389中支援了TCP穿透
- TURN解析
- TURN使用中繼穿透NAT:STUN的擴充套件,跟STUN一樣都是通過修改應用層中的私網地址達到NAT穿透的效果,異同點是TURN是通過兩方通訊的“中間人”方式實現穿透。就有點像伺服器轉發音視訊流的意思,在STUN失敗時會走TURN
- NAT作用是啥
- 為了緩解全球ip不足,NAT可以將內網的私有地址轉為外網的共有地址,從而可以進行internet訪問
- 防止外部主機攻擊內部主機
- 當然前端開發是不熟悉這些的,閱讀多篇RTC部落格得知谷歌開源了stun,coturn相關的服務,只需要將依賴安裝,賬號密碼加密設定即可使用參考文獻https://www.cnblogs.com/idignew/p/7440048.html
- 配置完畢coturn後測試地址,返回有relay屬性為伺服器地址證明成功https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
- STUN解析
-
easyRTC
-
經過多次測試,自己的RTCdemo相容性差,目前測試階段就不手寫了。採用了easyRTC,除了safari和古董ie不行,其他方面還是ok的。github.com/priologic/e…
-
- 注意採用beta分支,為最新的專案