視頻服務器(6) Kurento[1] rtsp2webrtc

目錄

一、安裝Kurento

二、播放rtsp調研

三、播放RTSP實現

四、wsl(ubuntu)安裝使用


官網:https://www.kurento.org/

參考:Kurento流媒體開發環境搭建流程以及連接海康威視攝像頭

參考:Kurento流媒體開發環境搭建流程

安裝:https://doc-kurento.readthedocs.io/en/6.12.0/user/installation_dev.html

環境:Win10系統,安裝VM,虛擬機Ubuntu18

一、安裝Kurento

1.1 ubuntu(或者虛擬機)安裝

參考:https://doc-kurento.readthedocs.io/en/6.12.0/user/installation.html#local-installation

指令:

# 1.安裝相關指令
sudo apt-get update && sudo apt-get install --no-install-recommends --yes gnupg

# Run ONLY ONE of these lines:
DISTRO="xenial"  # KMS for Ubuntu 16.04 (Xenial)
DISTRO="bionic"  # KMS for Ubuntu 18.04 (Bionic)

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83
sudo tee "/etc/apt/sources.list.d/kurento.list" >/dev/null <<EOF
# Kurento Media Server - Release packages
deb [arch=amd64] http://ubuntu.openvidu.io/6.12.0 $DISTRO kms6
EOF

# 安裝
sudo apt-get update && sudo apt-get install --yes kurento-media-server
# 這裏我出現了Unable to fetch some archives,maybe run apt-get update or try with --fix-missing
# 然後我再執行了
# sudo apt-get update
# 和
# sudo apt-get install --yes kurento-media-server
# Unable to fetch問題,多試幾次,無法獲取的包會越來越少,最後安裝成功的。

# 2.啓動相關指令
sudo service kurento-media-server start
# sudo service kurento-media-server stop

# 3.測試啓動正常
ps -fC kurento-media-server
sudo netstat -tupln | grep -e kurento -e 8888
# 先安裝curl
curl -i -N \
    -H "Connection: Upgrade" \
    -H "Upgrade: websocket" \
    -H "Host: 127.0.0.1:8888" \
    -H "Origin: 127.0.0.1" \
    http://127.0.0.1:8888/kurento

--------------------------------------------------------------

在另一臺ubuntu電腦上安裝時,好像是中間死機了,出現了問題:

The following packages have unmet dependencies: gstreamer-...

參考:如何解決apt-get中Unmet dependencies問題

總之用下面的指令,就可以繼續安裝了

sudo apt --fix-broken install
sudo apt-get update
sudo apt-get upgrade

結果安裝完,在解壓時電腦又卡死了。

Upacking libdevmapper1.02.1:amd64 (2:1.02.145-4.1ubuntu3.18.10.1) over (2:1.02.145-4.1ubuntu3) ...

Preparing to unpack .../03-console-setup-linux_1.178ubuntu9.2_all.deb ...

Unpacking console-setup-linux (1.178ubuntu9.2) over (1.178ubuntu9) ...

就整個電腦卡着了

重啓後,還是不行。還是

sudo apt-get -y install kurento-media-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
kurento-media-server : Depends: gstreamer1.5-plugins-bad but it is not going to be installed
Depends: gstreamer1.5-plugins-ugly but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

參考了https://askubuntu.com/questions/564282/apt-get-unmet-dependencies-but-it-is-not-going-to-be-installed裏面的幾種方法,也沒用。

最後我發現電腦上的ubuntu版本居然是18.10 !!!! 版本代號是cosmic。

wsl和虛擬機裏面的版本都是18.04。

安裝教程裏面的改成cosmic,也是不行,暫時只能考慮是不支持18.10版本了。話說這個電腦裝了挺久的啊。重裝系統吧。幸虧這個ubuntu系統本身沒裝什麼東西。

重裝系統後,能夠裝上。

-----------------------------------------------------------------------------------------------------------

後來有次同事重裝了一個ubuntu電腦,安裝過程中碰到這樣的

下列軟件包有未滿足的依賴關係:
 ............
E: 無法修正錯誤,因爲您要求某些軟件包保持現狀,就是它們破壞了軟件包間的依賴關係。

是在輸入sudo apt-get update && sudo apt-get install --yes kurento-media-server時出現的

經過搜索,發現是沒有打開ubuntu的自動更新導致的

他在安裝ubuntu時跳過了自動更新

參考:E:無法修正錯誤,因爲您要求某些軟件包保持現狀,就是它們破壞了軟件包間的依賴關係

-------------------------------------------------------------------------------------------------------------

二、播放rtsp調研

在kurento的文檔中沒有找到rtsp的東西,有rtp何srtp的

參考:RTSP/RTP/RTCP之間的關係

那其實kurento應該能對接rtsp的啊,爲什麼官方的例子裏面沒有呢

官方有兩個文章,https://www.kurento.org/tags/rtsp

說實話 看不懂 並且沒有操作教程 。

先再找找有操作的教程,不行再來啃一啃。

-------------------------------------------------------------------------------------------------------------------

具體的例子,稍微查一下就能查到這個 https://github.com/lulop-k/kurento-rtsp2webrtc

相關指令有:

# Be sure to have installed Node.js in your system:
curl -sL https://deb.nodesource.com/setup | sudo bash -
#上面這個執行的話,有彈出提示,感覺像是說不要用了。
sudo apt-get install -y nodejs

# Also be sure to have installed Bower in your system:
sudo npm install -g bower
#bower已經過時了

# To launch the demo, run:
cd kurento-rtsp2webrtc
bower install

# An HTTP server is required for these demos. A very simple way of doing this is by means of a NodeJS server. This server can be installed as follows:
sudo npm install -g http-server

# Then, in each demo folder execute this command:

http-server
# Finally, open this URL in your browser: http://localhost:8080/

但是從實際來看這個是5年前的,而且運行執行教程的指令過程中發現很多都是過時了的。

到bower install那執行不下去了

從git上下載下代碼,它自己的note.txt裏面的git地址都不見了的。

--------------------------------------------------------------------------------------------------------------------------------------------

查了一些,都指向這個例子,打開下載下來的index.html

我都在懷疑用kurento作rtsp方式是否正確了,資料怎麼這麼少啊,這麼舊啊。

--------------------------------------------------------------------------------------------------------------

又查到一個資料,關於直播的技術整理2,雖然還是那個例子,但這裏提到了例子中的2s延遲的解決辦法。

同時看了一下前面的rtsp的英文的文章的內容,似乎對kurento來說,rtsp2webrtc很好實現。

代碼(僞代碼):

var pipeline = ...//Use Kurento Client API for obtaining your pipeline.

//Create the PlayerEndpoint for receiving from the IP camera. HTTP and RTSP uris are supportd
pipeline.create("PlayerEndpoint", {uri: "rtsp://your.rtsp.address"}, function(error, playerEndpoint){

    //Create the WebRtcEndpoint
    pipeline.create("WebRtcEndpoint", function(error, webRtcEndpoint){

    //If working with trickle ice, some code for candidate management is required here.

        //Connect playerEndpoint to webRtcEndpoint. This connection activates the agnostic media
        //capability and the appropriate transcodings are configured and activated.
  	playerEndpoint.connect(webRtcEndpoint, function(error){

                //Media starts flowing ... enjoy
  		player.play(function(error){
  		});
  	});
    });
});

現在的問題是這些代碼是什麼?哪裏來的?

pipeline,PlayerEndpoint,WebRtcEndpoint,play....

Java嗎?要找官方Demo看看了。

----------------------------------------------------------------------------------------------------------------------------

三、播放RTSP實現

下載Demo代碼,地址:https://github.com/Kurento/kurento-tutorial-java

用IDEA啓動,需要先安裝IDEA。參考:Ubuntu18.04 安裝 Idea 2018.2 Ultimate

我安裝後虛擬機死機了,然後就沒有了快捷方式,現在啓動都要進入目錄,啓動idea.sh........

下載安裝Java18,參考:ubuntu18.04 安裝java

Ubuntu自帶的Java不行,會出現問題什麼 java:error:option -source can not ... togather with -release。

安裝好Java18後,修改項目SDK,再啓動,就沒有錯誤了。

另外在沒有安裝Kurento環境下啓動,或者沒有啓動kurento服務,也是會報錯的。

----------------------------------------------------------------------------------

學習用的demo選擇兩個helloworld和player,因爲上面的PlayerEndpoint

現在的問題是,idea正常啓動了,頁面怎麼進去啊?沒有提示啊?

 

application.properties的內容是

# LOGGING
logging.level.root=INFO
logging.level.org.apache=WARN
logging.level.org.springframework=WARN
logging.level.org.kurento=INFO
logging.level.org.kurento.tutorial=INFO

# OUTPUT
# Terminal color output; one of [ALWAYS, DETECT, NEVER]
spring.output.ansi.enabled=DETECT


# ----------------------------------------
# WEB PROPERTIES
# ----------------------------------------

# EMBEDDED SERVER CONFIGURATION
server.port=${demo.port}
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=kurento
server.ssl.key-store-type=JKS
server.ssl.key-alias=kurento-selfsigned

通過在banner.txt裏面添加

${server.port}

打印出端口8443,在網頁中輸入http://127.0.0.1:8443,結果

查到8443端口是 tomcat的SSL端口,

用https測試,結果可以。

中間會彈出一個不安全,是否要繼續的界面。

點擊Start,能夠播放視頻,但是有些慢,接下來理解並修改代碼。

這個頁面其實就是我要的功能了。

修改下面的播放視頻的地址爲公司的攝像頭的rtsp地址,結果能夠成功播放!

到這裏,算是完成了第一階段。確認技術可行性。

播放效果有些延遲,還有丟幀,說啥話不如前面的go語言的方案的效果。

但是至少比shinobi好,是用webrtc的。

-------------------------------------------------------------------------------------------------------------------------

瀏覽器支持情況

Chrome和Firefox支持,

Edge不支持,最後提示一個 

Timeout for addRemoteCandidate. Consider sending an end-of-candidates notification

就沒有播放出來了。

用IE打開頁面,提示需要安裝 Temasys WebRTC Plugin插件,下載、安裝、刷新,可以播放。

另外多個瀏覽器同時打開也是支持的,這點比前面的go好。

接下來是延遲問題、純js客戶端。

-----------------------------------------------------------------------------------------------------------------------------

代碼分析:

在官方文檔裏(https://doc-kurento.readthedocs.io/en/6.12.0/_static/client-javadoc/index.html)PlayerEndpoint是支持RTSP的,就相當於一個播放器了,他來播放,然後結合WebRtcEndpoint,就能轉換到webrtc上了。

kurento-player例子裏面的PlayerHandler的代碼:

確實和前面猜測的一樣,這rtsp2webrtc的功能kurento很好實現。

但是爲什麼找到的資料都指向那個老的例子(https://github.com/lulop-k/kurento-rtsp2webrtc)呢,明明這個kurento-player纔是啊。

不過這個是java的例子,純js的例子還要看看。

-------------------------------------------------------------------------------------------------

處理延遲問題

參考前面的關於直播的技術整理2裏面的

pipeline.create("PlayerEndpoint", {networkCache: 0, uri: address.value}, function(error, player){...

還有官方文檔中的Class PlayerEndpoint.Builder下面的

修改java代碼

 final PlayerEndpoint playerEndpoint = new PlayerEndpoint.Builder(pipeline, videourl).withNetworkCache(0).build();

結果,延遲和丟幀問題都好了,效果很滿意

-------------------------------------------------------------------------------------

還有個useEncodedMedia

從說明來看,使用這個方法後,能減少一個解碼(decode)的過程,降低cpu利用率,提高延遲(應該),但是對於丟幀、視頻質量無法保證,不建議使用。

實際加上後測試,感覺快了那麼一點點,不知道是不是心理原因。

final PlayerEndpoint playerEndpoint = new PlayerEndpoint.Builder(pipeline, videourl)
            .useEncodedMedia()
            .withNetworkCache(0)
            .build();

後續實際生產環境再測試一下。另外這些都可以作爲配置項開放出來,這樣就不用改代碼了。

-----------------------------------------------------------------------------------------------------

四、wsl(ubuntu)安裝使用

試着在wsl裏面安裝,出現問題 

E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/f/fftw3/libfftw3-double3_3.3.7-1_amd64.deb  Connection timed out [IP: 91.189.88.173 80]
E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/universe/s/spandsp/libspandsp2_0.0.6+dfsg-0.1_amd64.deb  Connection timed out [IP: 91.189.88.149 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

發現多試幾次 sudo apt-get install --yes kurento-media-server,後面的沒獲取到的包越來越少,最後就能安裝上了。應該是網絡的問題。這個過程vpn倒是不需要使用的。

另外wsl安裝總感覺比較慢一點。

在wsl安裝好kurento,啓動服務後,用ps查看進程馬上就能找到了,因爲就那幾個啓動着,不需要查找。

啓動服務後查詢端口監聽,發現在wsl裏面沒有端口,在windows裏面有監聽端口,而且kurento-media-server在任務管理器裏面也作爲一個進程顯示出來了。

滿心歡喜的去啓動idea,啓動項目,結果啓動失敗了。

執行看提示

The Tomcat connector configured to listen on port 8443 failed to start. The port may already be in use or the connector may be misconfigured.

查找佔用8443的進程,發現是vmnat.exe,想起來VMware做了一些8443端口映射,爲了在外面訪問虛擬機裏面的服務。

刪除那個映射後,IDEA就能啓動項目了,然後也能進入網頁(https://127.0.0.1:8443)播放視頻了!

雖然console裏面最後提示有錯誤,視頻播放是正常的。

在idea中打印有錯誤

2019-11-07 14:33:53.454 ERROR 17924 --- [nio-8443-exec-5] o.kurento.tutorial.player.PlayerHandler  : 
Exception handling message {"id":"onIceCandidate","candidate":{"candidate":"candidate:2628012269 1 udp 2113937151 77b31313-368c-41b5-8f55-c62ecf5eb6d6.local 64065 typ host generation 0 ufrag dl6M network-cost 999","sdpMid":"1","sdpMLineIndex":1}} in sessionId 452f1e30-eeb8-9409-2069-c8826ed2286c

org.kurento.client.internal.server.KurentoServerException: Error adding candidate (Code:40401, Type:null, Data: {"type":"ICE_ADD_CANDIDATE_ERROR"})
	at org.kurento.client.internal.transport.jsonrpc.RomClientJsonRpcClient.sendRequest(RomClientJsonRpcClient.java:264) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.transport.jsonrpc.RomClientJsonRpcClient.invoke(RomClientJsonRpcClient.java:117) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.transport.jsonrpc.RomClientJsonRpcClient.invoke(RomClientJsonRpcClient.java:99) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.client.RomManager.invoke(RomManager.java:162) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.client.RemoteObject.invoke(RemoteObject.java:186) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.client.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:182) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.client.RemoteObjectInvocationHandler.internalInvoke(RemoteObjectInvocationHandler.java:142) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at org.kurento.client.internal.client.DefaultInvocationHandler.invoke(DefaultInvocationHandler.java:39) ~[kurento-client-6.11.1-20191014.135655-5.jar:6.11.1-SNAPSHOT]
	at com.sun.proxy.$Proxy65.addIceCandidate(Unknown Source) ~[na:na]
	at org.kurento.tutorial.player.PlayerHandler.onIceCandidate(PlayerHandler.java:259) ~[classes/:na]
	at org.kurento.tutorial.player.PlayerHandler.handleTextMessage(PlayerHandler.java:93) ~[classes/:na]
	at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) [spring-websocket-5.1.7.RELEASE.jar:5.1.7.RELEASE]
	at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.19.jar:9.0.19]
	at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_202]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_202]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_202]

對我來說,能播放就行,這個問題如果不影響播放,就可以不處理了。

 

-------------------------------------------------------------------------------------------------------------------------

用https://127.0.0.1:8443測試沒問題後,打算用其他電腦連接測試,結果,在自己電腦上用https://192.168.1.16:8443進入就不行了。

而用https://192.168.6.12:8443,則和127.0.0.1一樣最後有兩個錯誤提示,但是沒有視頻。

攝像頭是在192.168.1.134的和6不是一個網段,有關係嗎?

後來127.0.0.1也不行了......

然後發現,重啓一次kurento-media-server,就可以播放視頻,播放後,刷新頁面或者停止播放,然後就不能播放了,必須再次重啓服務。

192.168.6.12和127.0.0.1是可以播放的。

而192.168.1.16則是出於websocket無法發送信息的階段,根本進不了後端的代碼。

----------------------------

後來更是出現,怎麼重啓都無法播放的情況-------我的電腦有兩個網卡,一個連接內網,一個連接外網,攝像頭是在內網上的,假如把外網網卡禁掉,怎麼重啓都無法播放視頻。難道它必須連接外網嗎?

-------------------------------

發現虛擬機裏面的,無論外網網卡是否啓動,都能播放視頻。而外網網卡禁用時,外面電腦訪問虛擬機裏面的網頁會出現

Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
    at sendMessage (https://192.168.136.129:8443/js/index.js:263:5)
    at WebRtcPeerRecvonly.onIceCandidate (https://192.168.136.129:8443/js/index.js:140:2)
    at WebRtcPeerRecvonly.EventEmitter.emit (https://192.168.136.129:8443/js/kurento-utils.js:737:17)
    at RTCPeerConnection.iceCandidateFunction (https://192.168.136.129:8443/js/kurento-utils.js:275:26)

192.168.136.129是虛擬機的ip

-----------------------

糾結.....最理想還是不要放到虛擬機裏面,影響性能。最明顯的就是能看到延遲。

-----------------------

在另一臺電腦上安裝kurento,運行java項目,結果不會出現Error。

先繼續下一步吧。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章