前言

最近折騰了幾天 apprtc 服務器搭建,搭建的主要目的是爲了學習 Android 、WEB 等各端基於 webrtc 音視頻通信。

經過這幾天的搭建得出了幾點結論:

1、非 https 協議在 chrome 瀏覽器不支持打開音視頻設備。

2、如果想要使各端都能通信,那麼必須所有請求訪問都使用 https 協議,證書可以在購買服務器平臺上免費申請。

如果你正在找工作, 那麼你需要一份 Android 高級開發面試寶典

以下是最終效果圖(手機跟 WEB 互通需要所有 http 更換爲 https 協議,該篇最終結果還未達到各端互通的條件,後續會更新補上)

搭建環境

  • 服務器: 騰訊雲
  • 系統: centos

app2app

web2web

介紹

搭建 apprtc 需要用到以下幾個服務。

apprtc

AppRTC 是用來創建和管理通話狀態的房間服務器。

coturn

coturn 是一種 TURN 內網穿透服務器(也就是中轉服務器),該服務器用於 VOIP 或通用數據流的 NAT 穿越和數據轉發。

collider

collider 它是用 go 語言實現的基於 WebSocket 的信令服務器。

爲了建立一個 webrtc 的通信過程,一般是需要有如下通信信息:

1、會話控制信息,用來開始和結束通話,即開始視頻、結束視頻這些操作指令。

2、發生錯誤時用來相互通告的消息

3、元數據,如各自的音視頻解碼方式、帶寬。

4、網絡數據,對方的公網 IP、端口、內網 IP 及端口。

搭建 AppRTC 服務的基本步驟

1、搭建 AppRTC 房間服務器

2、搭建 Coturn 穿透服務器

3、搭建 Collider 信令服務器

4、搭建 ICE 信息服務器

如何搭建 AppRTC

1、install JDK

yum install java-1.8.0-openjdk

#查看 Java 版本
java -version

2、install node.js

curl -sL https://rpm.nodesource.com/setup_10.x | bash -
yum install -y nodejs
# 確認是否成功
node --version
npm --version

# 構建 apprtc 用到
npm -g install grunt-cli
grunt --version

3、安裝Python和Python-webtest (python2.7)

yum -y install epel-release
yum install python python-webtest python-pip
pip install --upgrade pip

4、安裝google_appengine

wget https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.40.zip
unzip google_appengine_1.9.40.zip

#配置環境變量:在/etc/profile文件最後增加一行:
vim /etc/profile
#添加如下代碼
export google_appengine_path=/root/webrtc/google_appengine
export PATH=$PATH:$google_appengine_path

#最後保存,使之生效
source /etc/profile

5、安裝 go

yum install golang
#查看是否安裝成功
go version 

#創建go工作目錄
mkdir -p /root/webrtc/goWorkspace/src
#配置環境變量:在 vim /etc/profile 文件最後增加一行:
export GOPATH=/root/webrtc/goWorkspace
#保存
source /etc/profile

6、安裝libevent

#當前目錄:root/webrtc/
#https://github.com/coturn/coturn/wiki/CoturnConfig
wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
tar xvf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure
make install

7、安裝 AppRTC

#當前目錄:root/webrtc/
git clone https://github.com/webrtc/apprtc.git
#將collider的源碼軟連接到go的工作目錄下
ln -s /root/webrtc/apprtc/src/collider/collider $GOPATH/src
ln -s /root/webrtc/apprtc/src/collider/collidermain $GOPATH/src
ln -s /root/webrtc/apprtc/src/collider/collidertest $GOPATH/src
#編譯collidermain
go get collidermain
go install collidermain

#go get collidermain: 被牆
#報錯: package golang.org/x/net/websocket: unrecognized import path "golang.org/x/net/websocket"
#執行: 
#mkdir -p $GOPATH/src/golang.org/x/
#cd $GOPATH/src/golang.org/x/
#git clone https://github.com/golang/net.git net 
#go install net

#再執行編譯collidermain
#修改房間服務器爲我們前面的房間服務器:
vim $GOPATH/src/collidermain/main.go
var roomSrv = flag.String(“room-server”, “https://49.235.159.44:8080”, “The origin of the room server”)

vim $GOPATH/src/collider/collider.go
#修改放入自己私有證書,目前這裏放入騰訊雲申請的 證書測試 app -> pc 通不了,固還是用自簽名
e = server.ListenAndServeTLS(“/root/key/chat.codecocoa.com.pem”, 		“/root/key/chat.codecocoa.com.key”)

go get collidermain
go install collidermain

8、安裝coturn

#目錄:root/webrtc/
#https://github.com/coturn/coturn/wiki/Downloads
wget http://coturn.net/turnserver/v4.5.0.7/turnserver-4.5.0.7.tar.gz
tar xvfz turnserver-4.5.0.7.tar.gz
cd turnserver-4.5.0.7
#如果沒有 openssl-devel 需要安裝
yum install openssl-devel
./configure --prefix=./bin
make install

9、配置並運行 coturn Nat 穿透服務器

#內網:172.17.0.11 :DevYk:用戶 12345 密碼 & ctr+c 不會停止
nohup turnserver -L 172.17.0.11 -a -u DevYK:12345 -v -f -r nort.gov &
#或者 作者用的該方案
nohup turnserver -L 172.17.0.11 -a -u DevYK:12345 -v -f -r www.devyk.cn & 
#netstat -ntulp 查看 5766,3478 端口是否啓動

10、collider 信令服務器

配置防火牆,允許訪問8089端口(tcp,用於客戶端和collider建立websocket信令通信)

#創建自簽名的數字證書
#如果沒有openssl,需要安裝
mkdir -p /cert
cd /cert
# CA私鑰
openssl genrsa -out key.pem 2048 
# 自簽名證書
openssl req -new -x509 -key key.pem -out cert.pem -days 1095

#app 與 app 通信由於 ssl 問題需要將 tls =false
nohup $GOPATH/bin/collidermain -port=8089 -tls=true -room-server="https://49.235.159.44:8080" > /root/webrtc/collidermain.log 2>&1 &

#檢查 8089 端口是否啓動
netstat -ntulp

11. apprtc 房間服務器

配置防火牆,允許訪問8080端口(tcp,此端口用於web訪問)

配置文件修改(主要是配置apprtc對應的conturn和collider相關參數)

#49.235.159.44 外網ip
vim /root/webrtc/apprtc/src/app_engine/constants.py

#ICE_SERVER_OVERRIDE = None
# Enable by uncomment below and comment out above, then specify turn and stun
ICE_SERVER_OVERRIDE  = [
   {
     "urls": [
       "turn:49.235.159.44:3478?transport=udp",
       "turn:49.235.159.44:3478?transport=tcp"
     ],
     "username": "DevYK",
     "credential": "12345"
   },
   {
     "urls": [
       "stun:49.235.159.44:8089"
     ]
   }
 ]
#ICE_SERVER_OVERRIDE = None

#pc 必須使用 https
#ICE_SERVER_BASE_URL = 'https://49.235.159.44'
#在 APP 上因爲沒有 SSL 證書,那麼只能用 http
ICE_SERVER_BASE_URL = 'http://49.235.159.44:8088'
ICE_SERVER_URL_TEMPLATE = '%s/v1alpha/iceconfig?key=%s'
ICE_SERVER_API_KEY = os.environ.get('ICE_SERVER_API_KEY')

# Dictionary keys in the collider instance info constant.
WSS_INSTANCE_HOST_KEY = '49.235.159.44:8089'
WSS_INSTANCE_NAME_KEY = 'vm_name'
WSS_INSTANCE_ZONE_KEY = 'zone'
WSS_INSTANCES = [{
    WSS_INSTANCE_HOST_KEY: '49.235.159.44:8089',
    WSS_INSTANCE_NAME_KEY: 'wsserver-std',
    WSS_INSTANCE_ZONE_KEY: 'us-central1-a'
}
#,{
#    WSS_INSTANCE_HOST_KEY: '49.235.159.44:8089',
#    WSS_INSTANCE_NAME_KEY: 'wsserver-std-2',
#    WSS_INSTANCE_ZONE_KEY: 'us-central1-f'
#}
]
#編譯
cd /root/webrtc/apprtc
npm install
grunt build

#如果出現下面錯誤,使用 cnpm 編譯
/root/webrtc/apprtc/node_modules/mkdirp/lib/opts-arg.js 
...

#npm 安裝出現問題 使用 cnpm 安裝
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install
grunt build

啓動:

#172.31.247.136 : 內網ip
nohup dev_appserver.py --host=172.17.0.11 --port 8080 /root/webrtc/apprtc/out/app_engine --skip_sdk_update_check > /root/webrtc/apprtc.log 2>&1 &


#檢查 8080 Python 是否起來
netstat -ntulp

12、 配置 ICE Service

mkdir /root/webrtc/iceService

vim ice.js

var http = require('http');
var crypto = require('crypto')
var hmac = function(key, content) {
  var method = crypto.createHmac('sha1', key)
  method.setEncoding('base64')
  method.write(content)
  method.end()
  return method.read()
}
http.createServer(function(request, response) {
  //賬戶
  var timestamp = Math.floor(Date.now() / 1000)
  var turn_username = timestamp + ':DevYK'
  //密碼
  var key = '12345'
  var password = hmac(key, turn_username)
  // 發送 HTTP 頭部 
  // HTTP 狀態值: 200 : OK
  // 內容類型: text/plain
  response.writeHead(200, {'Content-Type': 'text/plain'});
  console.log(turn_username);
  console.log(password);
  // 發送響應數據 "ice服務器"
  response.end('{"iceServers":[{"username":"'+turn_username+'","credential":"'+password+'","urls":["stun:49.235.159.44:3478","turn:49.235.159.44:3478"]}]}\n');
  }).listen(8088);
  // 終端打印如下信息
  console.log('ICE Server running');

啓動 ICE REST API 服務

nohup node ice.js &

#檢查 8088 服務是否啓動
netstat -ntulp

13、nginx 設置反向代理

nginx 已存在進行配置

11.1 配置反向代理

events {
        worker_connections 1024;
		}
		http{
			#apprtc 服務
        upstream roomserver {
        server 49.235.159.44:8080;
        }
        server {
                listen 80;
                server_name 49.235.159.44;
                return  301 https://$server_name$request_uri;
        }
        server {
                root /root/webrtc/nginx-1.17.8/html;
                index index.php index.html index.htm;
                listen      443 ssl;
                #騰訊雲證書
                #ssl_certificate /root/ssl/1_www.devyk.cn_bundle.crt;
                #ssl_certificate_key /root/ssl/2_www.devyk.cn.key;
                #ssl_session_timeout 5m;
                 #請按照以下協議配置
                #ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
                #請按照以下套件配置,配置加密套件,寫法遵循 openssl 標準。
                #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
                #ssl_prefer_server_ciphers on;
                #自簽名
                ssl_certificate /cert/cert.pem;
                ssl_certificate_key /cert/key.pem;
                server_name 49.235.159.44;
                location / {
                        proxy_pass http://roomserver$request_uri;
                        proxy_set_header Host $host;
                }
                location ~ .php$ {
                        fastcgi_pass unix:/var/run/php5-fpm.sock;
                        fastcgi_index index.php;
                        include fastcgi_params;
                }
        }
}

11.1.1已安裝但是沒有配置 ssl

#開啓 nginx 服務 error
nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module in 
/bin/conf/nginx.conf

解決:

#切換到源碼包:
cd /nginx/nginx-1.17.9

#查看nginx原有的模塊
/bin/sbin/nginx -V
#在configure arguments:後面顯示的原有的configure參數如下:
--prefix=./bin

重新編譯, 加入 --with-http_ssl_module

./configure --prefix=./bin  --with-http_ssl_module

#編譯
make

ps: 這裏千萬別 make install 覆蓋安裝,因爲之前還有 nginx 配置。

將之前的 nginx rm 替換爲 objs/nginx

#在 nginx/1.17 模塊下

rm -rf bin/sbin/nginx

cp objs/nginx bin/sbin/

最後重啓服務

#啓動
bin/sbin/nginx
#重啓
bin/sbin/nginx -s reload

nginx 未安裝配置

11.2 下載 nginx

wget http://nginx.org/download/nginx-1.17.9.tar.gz
tar -zxvf nginx-1.17.9.tar.gz

11.2.1編譯 nginx

./configure --prefix=./bin --with-http_ssl_module

make install

11.2.2 配置 nginx.conf

vim /root/webrtc/nginx-1.17.8/bin/conf/nginx.conf
#apprtc 服務
		events {
 			worker_connections 1024;
		}
		http{
        upstream roomserver {
        server 49.235.159.44:8080;
        }
        server {
                listen 80;
                server_name www.devyk.cn;
                return  301 https://$server_name$request_uri;
        }
        server {
                root /root/nginx/nginx-1.17.8/html;
                index index.php index.html index.htm;
                listen      443 ssl;
                #騰訊雲證書
                #ssl_certificate /root/nginx/nginx-1.17.8-http-rtmp/ssl/rtc.crt;
                #ssl_certificate_key /root/nginx/nginx-1.17.8-http-rtmp/ssl/rtc.key;
                #自簽名證書
                ssl_certificate /cert/cert.pem;
                ssl_certificate_key /cert/key.pem;
                server_name 49.235.159.44;
                location / {
                        proxy_pass http://roomserver$request_uri;
                        proxy_set_header Host $host;
                }
                location ~ .php$ {
                        fastcgi_pass unix:/var/run/php5-fpm.sock;
                        fastcgi_index index.php;
                        include fastcgi_params;
                }
        }
        }

11.2.3 啓動 nginx

#啓動
bin/sbin/nginx
#重啓
bin/sbin/nginx -s reload

搭建中遇見的問題

  • 瀏覽器通話跨域問題 :pushState

    vim /root/webrtc/apprtc/out/app_engine/js/apprtc.debug.js
    #全局搜索  pushState 增加:
    roomLink=roomLink.substring("http","https");

  • Websocket open error:

    Messages:  
    WebSocket open error: WebSocket error.
    WebSocket register error: WebSocket error.

    PC 上如果遇見這個問題,一般需要檢查 apprtc 、 constants.py 、簽名的配置信息。

  • 自簽名證書只能在瀏覽器上使用,不能用於瀏覽器與 Android 等端進行通信。

總結

整個服務搭建下來,坑確實太多了。目前由於沒有證書,所以只能用於 app2app 、web2web 測試了,等證書申請下來在來更新替換過程。

以上搭建只要按照文中步驟肯定是可以成功的,希望可以幫助到你。

參考

關於我

掃碼關注我的公衆號,讓我們離得更進一些!

相關文章