前言 前几天我一朋友问我有关webrtc的事,简单了解了下相关知识,搭建了一个webrtc的服务,以及经历的各种踩坑事件,感觉踩坑主要是Python、Node、OpenSSL等版本问题和证书问题导致。本来以为很简单的搭建,但在搭建的过程中遇到各种阻碍,写一篇文章梳理一下。
WebRTC 简介 WebRTC,名称源自网页即时通信(英语: Web Real-Time Communication )的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的 API。2010 年 5 月,Google 以 6820 万美元收购 VoIP 软件开发商 Global IP Solutions 的 GIPS 引擎,并改为名为 “WebRTC”。在 2011 年 6 月 1 日开源 WebRTC 并在 Google、Mozilla、Opera 支持下被纳入万维网联盟的 W3C 推荐标准。
WebRTC的Demo项目: https://github.com/webrtc/apprtc
基于 WebRTC 的 1v1 视频实时通话架构 从大的方面可以分为 3 部分:
1 2 3 4 5 6 1. WebRTC 终端 负责音视频采集、编解码、NAT 穿越、音视频数据传输 2. Signal 服务器 负责信令处理,如加入房间、离开房间、媒体协商消息的传递等 3. STUN/TURN 服务器 负责获取 WebRTC 终端在公网的 IP 地址,以及 NAT 穿越失败后的数据中转
架构图:
安装 WebRTC 服务器 运行环境准备
操作系统:Ubuntu 16.04
语言环境:NodeJS、Python、Golang
其他软件:git、tar、wget、unzip
命令安装:
1 2 3 apt-get update apt-get upgrade apt install -y nodejs-legacy npm python python-webtest golang-go unzip git-core tar wget
安装依赖服务 安装google_appengine:
1 2 3 4 cd /root/webrtc wget https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.40.zip unzip google_appengine_1.9.40.zip echo "export PATH=$PATH:/root/webrtc/google_appengine" >> /etc/profile
安装libevent:
1 2 3 4 5 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 && make install
安装信令(Signal)服务 1 2 3 4 5 6 7 8 9 10 mkdir -p /root/webrtc/goWorkspace/src echo "export GOPATH=/root/webrtc/goWorkspace" >> /etc/profile source /etc/profile cd /root/webrtc git clone git://github.com/webrtc/apprtc.git 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 go get collidermain go install collidermain
安装STUN/TURN服务 1 2 3 4 5 6 cd /root/webrtc 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 ./configure make install
安装WebRTC 终端服务 通过修改配置文件 /root/webrtc/apprtc/src/app_engine/constants.py
来设备好ICE配置(与STUN/TURN服务交互)和WebSocket配置(与信令服务交互)。然后再
配置好ICE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ICE_SERVER_OVERRIDE = [ { "urls": [ "turn:47.105.214.21:3478?transport=udp" , "turn:47.105.214.21:3478?transport=tcp" ], "username": "flyer" , "credential": "123456" }, { "urls": [ "stun:47.105.214.21:3478" ] } ] ICE_SERVER_BASE_URL = 'https://webrtc.zhaoweiguo.com'
配置好信令服务 1 2 3 4 5 6 7 8 9 10 WSS_INSTANCE_HOST_KEY = 'webrtc.zhaoweiguo.com:8089' WSS_INSTANCE_NAME_KEY = 'vm_name' WSS_INSTANCE_ZONE_KEY = 'zone' WSS_INSTANCES = [{ WSS_INSTANCE_HOST_KEY: 'webrtc.zhaoweiguo.com:8089' , WSS_INSTANCE_NAME_KEY: 'wsserver-std' , WSS_INSTANCE_ZONE_KEY: 'us-central1-a' }]
安装相关依赖 1 2 3 4 5 6 7 8 9 10 11 # 1. 升级npm npm install -g n n stable hash -r # (for bash, zsh, ash, dash, and ksh) # or rehash (for csh and tcsh) # 2. 安装node构建工具:grunt npm -g install grunt-cli@1.3.2 # 3. 安装 coffeescript npm install --dev coffeescript
安装apprtc 1 2 3 cd /root/webrtc/apprtc npm install --no-fund grunt build
证书生成 生成私有证书 1 2 3 4 5 6 7 8 openssl req -x509 -out /cert/cert.crt -keyout /cert/key.pem \ -newkey rsa:2048 -nodes -sha256 \ -subj '/CN=webrtc.zhaoweiguo.com' \ && cat /cert/key.pem > /cert/cert.pem \ && cat /cert/cert.crt >> /cert/cert.pem \ && chmod 600 /cert/cert.pem /cert/key.pem /cert/cert.crt # 注意:把-subj '/CN=webrtc.zhaoweiguo.com' 中的域名改成你自己的域名
使用certbot生成免费的Let’s Encrypt证书 安装certbot:
1 2 3 4 # Debian apt-get install certbot # Docker docker pull certbot/certbot
前提:
1 2 3 1. 执行此命令必须使用 root 用户获得文件夹的权限2. 域名能访问并且有绑定的公网 IP3. 必须在此域名绑定的服务器上运行
基于 Nginx 生成证书:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 安装插件: apt-get install python-certbot-nginx 执行命令: $ sudo certbot certonly --nginx Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator nginx, Installer nginx Which names would you like to activate HTTPS for? - - - - - - - - - - - - - - - - - - - - - - - - 1: zhaoweiguo.com 2: knowledge.zhaoweiguo.com 3: www.zhaoweiguo.com - - - - - - - - - - - - - - - - - - - - - - - - 选择你要生成证书的域名,根据提示一步步执行就好了
不基于webserver直接生成证书
1 2 3 4 5 6 7 8 9 10 1. 直接命令执行 certbot certonly --standalone --email admin@zhaoweiguo.com -d webrtc.zhaoweiguo.com 2. 使用Docker执行 docker run -it -p 80:80 --rm --name certbot \ -v "/etc/letsencrypt:/etc/letsencrypt" \ -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ certbot/certbot certonly --standalone \ --email admin@zhaoweiguo.com -d webrtc.zhaoweiguo.com 注意:80端口不可被占用,它会启动80端口的一个服务用于验证你的合法性
证书生成成功界面
1 2 3 4 5 6 7 8 9 10 11 - Congratulations! Your certificate and chain have been saved at: /etc/ letsencrypt/live/ webrtc.zhaoweiguo.com/fullchain.pem Your key file has been saved at: /etc/ letsencrypt/live/ webrtc.zhaoweiguo.com/privkey.pem Your cert will expire on 2023 -03 -19 . To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https:/ /letsencrypt.org/ donate Donating to EFF: https:
启动服务 设定环境变量 1 2 3 4 # 本地IP地址 export LOCAL_IP=xx.xx.xx.xx # 外网IP地址 export SERVER_IP=xx.xx.xx.xx
启动STUN/TURN服务 1 nohup turnserver -L $LOCAL_IP -a -u flyer:123456 -v -f -r nort.gov &
检查是否启动成功:
1 2 3 4 5 6 7 lsof -i:3478 # 出现如下信息即为成功: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME turnserve 14754 root 16u IPv4 112232 0t0 UDP instance-5i00bk4l:3478 turnserve 14754 root 17u IPv4 112233 0t0 UDP instance-5i00bk4l:3478 turnserve 14754 root 32u IPv4 112263 0t0 TCP instance-5i00bk4l:3478 (LISTEN) turnserve 14754 root 33u IPv4 112267 0t0 TCP instance-5i00bk4l:3478 (LISTEN)
启动信令服务 启动命令:
1 2 cd /cert # 这个目录里面有前面生成的域名证书和密钥 nohup $GOPATH/bin/collidermain -port=8089 -tls=true -room-server="https://$SERVER_IP:8080" &
检查是否启动成功:
1 2 3 4 lsof -i:8089 # 出现如下信息即为成功: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME colliderm 14817 root 3u IPv6 112969 0t0 TCP *:8089 (LISTEN)
出现如下打印日志即为启动成功:
1 2022 /03 /11 02 :09 :00 Starting collider: tls = true, port = 8089 , room-server=https://47.253.204.204:8080
启动WebRTC 终端服务 1 nohup dev_appserver.py --host=$LOCAL_IP /root/webrtc/apprtc/out/app_engine --skip_sdk_update_check &
这时候在你的浏览器输入 http://服务器公网IP:8080/ 如果能顺利打开,那么恭喜你环境算是基本搭建成功啦!!!
配置Nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 upstream roomserver { server 本机ip:8080 ; } server { root /usr/share/nginx/html; index index.php index.html index.htm; listen 443 ssl; ssl_certificate /cert/cert.pem; ssl_certificate_key /cert/key.pem; server_name webrtc.zhaoweiguo.com; // 改成你自己的域名 location / { proxy_pass http://roomserver$request_uri; proxy_set_header Host $host; } }
加载Nginx:
运行效果 打开浏览器,输入 https://webrtc.zhaoweiguo.com
,页面显示如下:
点击连接(JOIN),后
可以看到下面等待其他人加入的链接。使用另一台电脑(手机)浏览器打开这个链接(如图我自己手机打开)
点击「JOIN」后,显示连接成功页面
Docker版实现 如果你只想快速验证使用,最简单的方法是使用Docker方式,我已经把大部分的工作封装到 镜像zhaowg/webrtc:new2
中了,可以直接使用,不过使用时注意网络要使用Docker的宿主网络模式(host)
:
1 2 3 # 注:使用--net=host使用宿主网络模式,如果使用默认的bridge模式会多一层Nat转换 # 在使用STUN/TRUN时会有问题 docker run -e "SERVER_IP=xx.xx.xx.xx" -e "LOCAL_IP=172.17.0.2" --net=host -it zhaowg/webrtc:new2 bash
按上面文档说明修改成你自己的的域名、证书、ip等信息,然后执行
踩坑记录
WebSocket connection failed
1 2 3 4 5 6 7 8 9 打开连接页面点击「JOIN 」时报下面错 WebSocket connection to 'wss://webrtc.zhaoweiguo.com:8089/ws' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID 这时,「信令服务」日志报: 2022 /03/ 11 02 :13 :22 http: TLS handshake error from 111.205 .43.248 :15029 : remote error: unknown certificate解决方案: 修改AppRTC服务的配置中的WSS_INSTANCE_HOST_KEY选项 即修改文件/root/ webrtc/apprtc/ src/app_engine/ constants.py 把WSS_INSTANCE_HOST_KEY选项的值设置为对应证书的域名(而不是用IP)
各种OpenSSL问题
1 2 这种问题我的解决方案是使用指定的OS版本 比如这儿用Ubuntu 16.04
Failed to execute 'pushState' on 'History'
1 2 3 4 5 6 运行都成功,但就是在点击连接时报错 解决方法是: 修改文件 ``./src/ web_app/js/ appcontroller.js`` 中的 ``AppController.prototype.pushCallNavigation_`` 函数 在此函数最开始增加一句代码: roomLink = roomLink.replace("http" , "https" ); 参考自:https://gi thub.com/ISBX/ apprtc-node-server/issues/ 7
grunt build报错
1 2 3 4 原因: 主要是npm 、grunt版本问题 解决方法: 升级npm ,使用指定的grunt版本
go get collidermain命令失败
1 2 3 4 5 6 7 8 9 10 11 原因: collidermain依赖项目golang.org/x/ net/websocket 而执行go get collidermain命令时,会请求golang.org/x/ net/websocket 而这个请求在国内默认不可访问 解决方案: 1 . 解决请求golang.org网站的问题2 . 执行如下命令mkdir -p $GOPATH /src/g olang.org/x/ cd $GOPATH /src/g olang.org/x/ git clone git://gi thub.com/golang/ net.git net go install net
附录:Dockerfile文件内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 FROM ubuntu:16.04 RUN apt-get update && apt-get upgrade && apt install -y nodejs-legacy npm python python-webtest golang-go unzip wget git-core RUN npm -g install grunt-cli@1.3 .2 RUN mkdir -p /root/ webrtc/goWorkspace/ src && cd /root/ webrtc && wget https:// storage.googleapis.com/appengine-sdks/ featured/google_appengine_1.9.40 .zip && unzip google_appengine_1.9.40 .zip RUN wget https://gi thub.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 && make install ENV GOPATH=/root/ webrtc/goWorkspace ENV PATH=$PATH :/root/ webrtc/google_appengine WORKDIR /root/ webrtc RUN git clone git://gi thub.com/webrtc/ apprtc.git && 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 && go get collidermain && go install collidermain RUN 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 && ./ configure && make install WORKDIR /root/ webrtc/apprtc RUN npm install -g n && n stable && RUN npm install --no-fund && npm install --dev coffeescript && grunt build WORKDIR /root/ webrtc RUN echo "nohup turnserver -L $LOCAL_IP -a -u flyer:123456 -v -f -r nort.gov &" >> ./start.sh && echo 'nohup $GOPATH/ bin/collidermain -port=8089 -tls=true -room-server="https:/ /$SERVER_IP:8080" &' >> ./ start.sh && echo "nohup dev_appserver.py --host=$LOCAL_IP /root/webrtc/apprtc/out/app_engine --skip_sdk_update_check &" >> start.sh && chmod +x start.sh
参考
极客时间-从 0 打造音视频直播系统: https://time.geekbang.org/column/intro/100031801
维基百科-WebRTC: https://zh.wikipedia.org/wiki/WebRTC
博客-WebRTC 之服务器搭建: https://www.jianshu.com/p/df300071d8d6