12┃音視訊直播系統之 WebRTC 實現1對1直播系統實戰

autofelix發表於2022-05-21

一、搭建 Web 伺服器

  • 前面我們已經實現過,但是沒有詳細說HTTPS服務

  • 首先需要引入了 express 庫,它的功能非常強大,用它來實現 Web 伺服器非常方便

  • 同時還需要引入 HTTPS 服務,並讓 Web 服務執行於 HTTPS 之上即可

var https = require('https');
var express = require('express');
var serveIndex = require('serve-index');

// 使用 express 實現 WEB 服務
var app = express(); 
app.use(serveIndex('./public'));
app.use(express.static('./public'));

//HTTPS 證書和金鑰檔案
var options = {
 key : fs.readFileSync('./cert/www.autofelix.cn.key'),
 cert: fs.readFileSync('./cert/www.autofelix.cn.pem')
}

//https server
var https_server = https.createServer(options, app);
var io = socketIo.listen(https_server);
https_server.listen(443, '0.0.0.0');

 

二、實現信令系統

  • 信令系統超級重要,直播系統中,由誰來發起呼叫、什麼時間發 SDP 等各種操作都是由信令控制的

  • 客戶端命令︰join使用者加入房間、leave使用者離開房間、message端到端命令

  • 服務端命令︰joined使用者已加入、leaved使用者已離開、other_joined其他使用者已加入、bye其他使用者已離開、full房間已滿

  • 在初始時,客戶端處於 init/leaved 狀態,在該狀態下使用者只能傳送 join 訊息

  • 服務端收到 join 訊息後,會返回 joined 訊息,此時客戶端為 joined 狀態

  • 如果使用者離開房間,那客戶端又回到了初始狀態

  • 如果客戶端收到 second user join 訊息,則切換到 joined_conn 狀態,該狀態下可以進行通話

  • 如果客戶端收到 second user leave 訊息,則切換到 joined_unbind 狀態,該狀態與 joined 狀態基本一致

12┃音視訊直播系統之 WebRTC 實現1對1直播系統實戰

 

三、搭建 TURN 伺服器

  • 其中最重要的 TURN 服務。它有兩個作用,一是提供 STUN 服務,客戶端可以通過 STUN 服務獲取自己的外網地址;二是提供資料中繼服務

  • 目前最著名的 TURN 伺服器是由 Google 發起的開源專案 coturnhttps://github.com/coturn/coturn

  • coturn 的編譯安裝與部署步驟如下︰

// 下載原始碼
git clone https://github.com/coturn/coturn.git

// 編譯, 生成 Makefile
./configure --prefix=/usr/local/coturn

// 安裝
make && make install

// 關於 coturn 服務配置
listening-port=3478  // 指定偵聽的埠
external-ip=147.104.34.27 // 指定雲主機的公網ip地址
user=username:password // 訪問stun/turn服務的使用者名稱和密碼
realm=stun.xxx.cn // 域名,這個必須設定

 

四、視訊直播之音視訊資料的採集

  • 第一步通過 getUserMedia 就可以獲取到音視訊資料

  • 以前是在瀏覽器顯示頁面時就開始採集,而現在則是在使用者點選 Connect Sig Server 按鈕時才開始採集音視訊資料

  • 信令系統建立好後,後面的邏輯都是圍繞著信令系統建立起來的,RTCPeerConnection 物件也不例外

  • 在客戶端,使用者要想與遠端通話,首先要傳送 join 訊息,也就是要先進入房間,如果伺服器判定使用者是合法的,則會給客戶端回 joined 訊息

  • 客戶端收到 joined 訊息後,就要建立 RTCPeerConnection 物件了,也就是要建立一條與遠端通話的音視訊資料傳輸通道

  • 我們需要設定 TURN 伺服器地址、使用者名稱和密碼,這樣當 RTCPeerConnection 通過 P2P 建立連線失敗時,就會使用 TURN 伺服器進行資料中繼

  • RTCPeerConnection 物件建立好後,我們要將前面獲取的音視訊資料與它繫結到一起,這樣才能通過 RTCPeerConnection 物件將音視訊資料傳輸出去

var pcConfig = {
 'iceServers': [{ // 指定 ICE 伺服器信令
 'urls': 'turn:stun.al.learningrtc.cn:3478', //turn 伺服器地址
 'credential': "passwd", //turn 伺服器密碼,你要用自己的
 'username': "username" //turn 伺服器使用者名稱,你要用自己的
 }]
};

function createPeerConnection(){
 	if(!pc){
 		pc = new RTCPeerConnection(pcConfig); // 建立 peerconnection 物件
 		pc.ontrack = getRemoteStream; // 當遠端的 track 到來時會觸發該事件
 	}else {
 		console.log('the pc have be created!');
 	}
 	return;
}

// 將獲取的音視訊資料與 RTCPeerConnection 繫結到一起
function bindTracks(){
 //add all track into peer connection
 localStream.getTracks().forEach((track)=>{
 		pc.addTrack(track, localStream); // 將 track 與 peerconnection 繫結
 });
}

 

五、視訊直播之音視訊的渲染與播放

  • 按照上面的步驟,音視訊資料就可以被採集到了,RTCPeerConnection 物件也建立好了,通過信令伺服器也可以將各端的 Candidate 交換完成了

  • 此時在 WebRTC 的底層就會進行連通性檢測,它首先判斷通訊的雙方是否在同一個區域網內

  • 如果在同一個區域網內,則讓雙方直接進行連線

  • 如果不在同一區域網內,則嘗試用P2P 連線

  • 如果仍然不成功,則使用 TURN 服務進行資料中繼

  • 一旦資料連通後,資料就從一端源源不斷地傳到了遠端,此時遠端只需要將資料與播放器對接,就可以看到對端的視訊、聽到對方的聲音了

  • 當資料流過來的時候會觸發 RTCPeerConnection 物件的 ontrack 事件

  • 只要我們偵聽該事件,並在回撥函式中將收到的 track<video> 標籤繫結到一起即可

var remoteVideo = document.querySelector('video#remotevideo');

pc = new RTCPeerConnection(pcConfig);
pc.ontrack = getRemoteStrea // 當遠端的 track 過來時觸發該事件

function getRemoteStream(e){ // 事件處理函式
 	remoteStream = e.streams[0]; // 儲存遠端的流
 	remoteVideo.srcObject = e.streams[0]; // 與 HTML 中的視訊標籤繫結
}

 

相關文章