目录
一、安装 TURN server(尝试失败)。
二、使用免费TURN
三、Chrome不能播放WebRtc视频的问题
3.1 服务端分析
3.2 客户端分析
3.3 解决方案
前面碰到的公网,firefox无法播放视频的问题,提示
ICE failed, add a TURN server and see about:webrtc for more details
现在测试环境是:有两个服务器,一个有外围ip,一个只有内网ip的。
现在的问题是纯js客户端(没有放在http服务器上的html文件),firefox情况下,连接外网或者内网的kurento服务器都是ice faild的。chrome连接内网,能够播放,连接外网,第一次能播放,后面就不行了。
其实可以先把unity部署到springboot中,不用纯js客户端的方式连接试试。
---------------------------------------------------------------------
查到的资料都是安装coturn,实际操作一下看看。
参考:coturn穿透服务器搭建
git clone https://github.com/coturn/coturn
cd coturn
./configure
不按照步骤先安装libevent的话,会提示
我的系统是ubuntu18.4,不能用yum安装,
参考:Ubuntu18.04安装Openssl-1.1.1进行安装,
安装过程中出现 Authentication failure,参考:Linux下切换root用户提示Authentication failure错误的解决方法
回到上面的coturn,在生成密钥时碰到问题,输入指令openssl req -x509 ....,后提示,req:Use -help for summary,好像这个语句有问题。
其他教程没有这个,是拷贝的文件的,参考:Ubuntu下安装配置coturn
------------------------------------------
另外还有个教程提示要安装,sqlite,参考:webrtc笔记(1): 基于coturn项目的stun/turn服务器搭建
这个教程里面提示直接用apt-get安装libevent,参考:Ubuntu 下 coturn 配置实现 TURN 中继传输媒体数据
好吧,不同的环境,不同的教程,我一开始可能就不应该参考那个centos环境下的。
----------------------------------------
另外可以用网上免费的stun服务器,参考:webrtc之三 iceServer
https://gist.github.com/yetithefoot/7592580里面的
{
url: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: '[email protected]'
}
似乎能使用,进入http://numb.viagenie.ca/,发现
-------------------------------------------
查一下openssl -req 的信息,参考:OpenSSL指令---req
用里面的最后的例子,可以的
产生一个自签名的根证书: openssl req -x509 -newkey rsa:1024 -keyout key.pem -out req.pem
至少第一次时会要求
Enter PEM pass phrase
随便输入了一个123456,后面的其他信息也随便输入。
在这个基础上改成
sudo openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 –nodes
难道是拷贝的和手动输入的不一样吗.....
继续吧。
--------------------------------------------------------------
内网电脑配置:
relay-device=enp6s0 #与前ifconfig查到的网卡名称一致
listening-ip=192.168.6.16 #内网IP
listening-port=3478
tls-listening-port=5349
relay-ip=192.168.6.16 #内网IP
external-ip=192.168.6.16 #公网IP
relay-threads=50
lt-cred-mech
cert=/etc/turn_server_cert.pem
pkey=/etc/turn_server_pkey.pem
pidfile="/var/run/turnserver.pid"
min-port=49152
max-port=65535
user=cww:123456 #用户名密码,创建IceServer时用
#创建IceServer
IceServer turnIceServer = new IceServer("turn:192.168.6.16:3478","cww","123456");
IceServer stunIceServer = new IceServer("stun:47.107.110.212:19302","","");
vim无法复制粘贴,手动输入了,但是因为没有外围ip,不知道怎么测试。
--------------------------------------------------------------------
用免费的在https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/做了下测试,和https://www.cnblogs.com/yjmyzz/p/how-to-install-coturn-on-ubuntu.html的最后的结果一样,接下来用那个来配置一下kurento先吧,从看到的资料,turn应该是安装在某个公网电脑上的。
{
url: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: '[email protected]'
}
接下来要设置kurento,发现官网(https://doc-kurento.readthedocs.io/en/6.12.0/user/installation.html#stun-and-turn-servers)也是推荐用numb和Coturn的。
还有Coturn的安装说明(https://doc-kurento.readthedocs.io/en/6.12.0/user/faq.html)
---------------------------------------------------------------------------
1.在服务器上加上turn设置
[email protected]:[email protected]:3478
说实话不知道有没有用,有两个@ .....
2.在客户端的kurento-player的js代码中加上turn的设置:
var iceservers={
"iceServers":[
{url:'stun:stun.xten.com'},
{
url: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: '[email protected]'
}
]
}
var options = {
remoteVideo : video,
mediaConstraints : userMediaConstraints,
onicecandidate : onIceCandidate,
configuration: iceservers
}
结果还是出不来:
ICE failed, see about:webrtc for more details
才想到这个【about:webrtc】和chrome的【chrome://webrtc-internals/】一样,是个调试界面。。。。
从html文件打开:
而从网页打开并播放时是
我的电脑是双网卡的,192.168.1.16连接内网,192.168.6.12连接外网。
从网页打开时Websocket连接的是内网的"ws://192.168.1.150:8444/player",似乎它居然用6.12的ip去连接1.150。1.16呢,干嘛不用1.16尝试?
把外围网卡网线拔了,果然,html也能播放了。插上还是不行。
chrome没有这个问题,说明chrome对多网卡的处理比firefox好一些?
chrome也有自己的的问题(外围时服务端的addicecandidate要5s)。
尝试用html连接192.168.6.16(是192.168.1.150电脑的内网ip),能够播放。
神奇的是这时再用html去连接192.168.1.150,也能播放。而且连接的是两个6网段的ip,而不是1网段的。
好像有学习能力一样的。不是学习到自己有1网段的ip,去连接对方的1网段,而是学习都有6网段的ip。
我原本还想看看代码,能不能让它在有两个网卡的情况下从1连接1,结果它自己转到6了。
重启一下电脑,还是可以,换一台电脑,也是可以。
奇怪了,最早的问题(用6网段连接1网段)又是怎么回事呢。
-----------------------------------------------------------------------------
连接外网服务器,http://60.191.23.20:8443/#,可以
这个115.204.230.177应该是我们这个局域网的对外网关ip了吧。
将webgl部署到bootstrap上,也就是kurento所在电脑上,用网页打开,firefox可以播放视频。
客户端提示的原因是ICE_ADD_CANDIDATE_ERROR,服务端对应的代码是
private void onIceCandidate(String sessionId, JsonObject jsonMessage) {
UserSession user = users.get(sessionId);
if (user != null) {
JsonObject jsonCandidate = jsonMessage.get("candidate").getAsJsonObject();
IceCandidate candidate =
new IceCandidate(jsonCandidate.get("candidate").getAsString(), jsonCandidate
.get("sdpMid").getAsString(), jsonCandidate.get("sdpMLineIndex").getAsInt());
user.getWebRtcEndpoint().addIceCandidate(candidate);
}
}
这里的addIceCandidate部分会出异常。
加入打印语句
发现start和end之间的时间有问题
在Firefox里面播放时是很快的直接就一起的
而在Chrome里面则是无论是否有异常,start和end之间都查了5s。addIceCandidate里面用时5s。
另外就是Chrome的发送的sdpOffer很长要16310,而Firefox的只有2083。看来下sdpOffer的内容,chrome的有4个mid。
具体内容,完全看不懂。
参考:WebRTC56版本SDP详细解析,WebRTC 中的 SDP 协议(这个还有对应的腾讯视频课程)
-------------------------------------------------------------------------------------
查资料过程中发现,在使用代理的情况下,chrome播放视频16s,没有代理31s,没代理时可能播放不了,启动代理的情况下基本都能播放。
-------------------------------------------------------------------------------------
试着把Firefox的candidate保存起来(手动一个个保存起来),在Chrome环境下发送,结果可以播放,也很快,3s左右,说明是candidate的问题。
注释掉sendMessage里面的发送部分,在不发送任何消息的情况下,查看chrome的oncandidate的内容,发现
1.没有使用turn的情况下,只有2个
视频出不来的。
2.使用turn的情况下,有6个,最后两个里面的158.69.221.198是numb.viagenie.ca的ip。
3.曾经在没有使用turn,开着代理的情况下。
有时能出来4个,那种情况下,视频是能出来的,16s左右。
另外把这些candidate手动保存下来后,不发送前两个(包含20e66a9b-b883-43c4-b8c2-1fb6a8de9cab.local),的情况下,3s,左右视频就出来了,发送的话16s,同时服务端addCandidate时会报错,就是前面两个的错误。
1.添加turn iceServers
var iceservers={
"iceServers":[
{url:'stun:stun.xten.com'},
{
url: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: '[email protected]'
}
]
}
var options = {
remoteVideo : player.video,
mediaConstraints : userMediaConstraints,
//....
configuration: iceservers
}
player.webRtcPeer = new kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options,
function(error) {
if (error)
return console.error(error);
player.webRtcPeer.generateOffer(function(error, offerSdp){
player.onOffer(error,offerSdp);
});
});
2.缓存发送offer和candidate,同时要过滤.local的candidate
KurentoPlayer.prototype.onOffer=function(error, offerSdp) {
console.info("******************************* onOffer",this);
if (error)
return console.error('Error generating the offer');
console.info('Invoking SDP offer callback function ' + location.host);
var message = {
id : 'start',
sdpOffer : offerSdp,
videourl : this.config.videoUrl
}
//this.sendMessage(message);
this.pushBUfferMessage(message);//缓存起来,到oncandidategatheringdone时一起发送出去
}
KurentoPlayer.prototype.onIceCandidate=function(candidate) {
var player=this;
player.candidateCount++;
console.error('['+player.candidateCount+'][onIceCandidate : Local candidate]',JSON.stringify(candidate));
player.sendCandidate(candidate);
};
KurentoPlayer.prototype.sendCandidate=function(candidate) {
var isLocal=candidate.candidate.indexOf('.local');
if(isLocal!=-1){//过滤,不发送
console.error("sendCandidate isLocal",candidate,isLocal);
return;
}
var message = {
id : 'onIceCandidate',
candidate : candidate
}
//this.sendMessage(message);
this.pushBUfferMessage(message);
};
3.在oncandidategatheringdone一起发送
var options = {
//...
oncandidategatheringdone:function(evt){
console.error("oncandidategatheringdone",evt);
player.flushBUfferMessage();//一起发送
},
configuration: iceservers
}
注意如果不缓存offer,只是缓存candidate,一起发送后服务端会出错,最终导致playEnd。