目錄
前面碰到的公網,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客戶端的方式連接試試。
---------------------------------------------------------------------
一、安裝 TURN server(嘗試失敗)。
查到的資料都是安裝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)
---------------------------------------------------------------------------
二、使用免費TURN
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可以播放視頻。
三、Chrome不能播放WebRtc視頻的問題
3.1 服務端分析
客戶端提示的原因是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。
而且很奇怪的是打印時間裏的秒都是5的倍數。
另外就是Chrome的發送的sdpOffer很長要16310,而Firefox的只有2083。看來下sdpOffer的內容,chrome的有4個mid。
具體內容,完全看不懂。
參考:WebRTC56版本SDP詳細解析,WebRTC 中的 SDP 協議(這個還有對應的騰訊視頻課程)
-------------------------------------------------------------------------------------
3.2 客戶端分析
查資料過程中發現,在使用代理的情況下,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時會報錯,就是前面兩個的錯誤。
3.3 解決方案
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。