nginx-rtmp之直播視頻流的推送


  一、RTMP是Real Time Messaging Protocol(實時消息傳輸協議)的首字母縮寫。該協議基於TCP,是一個協議族,包括RTMP基本協議及RTMPT/RTMPS/RTMPE等多種變種。RTMP是一種設計用來進行實時數據通信的網絡協議,主要用來在Flash/AIR平台和支持RTMP協議的流媒體/交互服務器之間進行音視頻和數據通信。支持該協議的軟件包括Adobe Media Server/Ultrant Media Server/red5等。

  RTMP(Real Time Messaging Protocol)實時消息傳送協議是Adobe Systems公司為Flash播放器和服務器之間音頻、視頻和數據傳輸 開發的開放協議。

  它有多種變種:
  1)RTMP工作在TCP之上,默認使用端口1935;
  2)RTMPE在RTMP的基礎上增加了加密功能;
  3)RTMPT封裝在HTTP請求之上,可穿透防火牆
  4)RTMPS類似RTMPT,增加了TLS/SSL的安全功能;
  二、上面介紹了RTMP協議主要用來干什么的,下面說明一下NGINX-RTMP主要的作用。我們在做視頻流的推送的時候,一般都是采用rtmp的協議進行視頻流的推送工作。而這里我們主要說道的是nginx提供的一套視頻流的解決方案,主要插件為nginx-rtmp-module。他提供RTMP/HLS/MPEG-DASH這幾種方式,下面我具體說一下安裝部署過程,當然可以參考官方文檔。
  三、我們來做種寫一下實現過程,這里面涉及到很多的文檔,需要自己動手查看官方文檔等,下面的環境基本都是在linux上面完成。當然可以使用其他環境,根據自己需要修改
  1)安裝nginx和nginx-rtmp-module模塊
  nginx下載地址:http://nginx.org/download/nginx-1.17.3.tar.gz   nginx-rtmp-module下載地址:https://github.com/arut/nginx-rtmp-module(直接使用git下載然后解壓即可)
  
  解壓
# tar -zxf nginx-1.17.3.tar.gz # unzip nginx-rtmp-module-master.zip
  

  修改nginx-rtmp-module-master為nginx-rtmp-module

# mv nginx-rtmp-module-master nginx-rtmp-module
  安裝,官方提供的方式
cd nginx-1.17.3
./configure --add-module=/usr/local/nginx-rtmp-module make make install

  少依賴的錯誤解決:

apt-get install libpcre3 libpcre3-dev

apt-get install openssl libssl-dev

  成功過后我們看見nginx依賴包有

sudo apt-get install zlib1g-dev

  接下來就是執行上面的安裝步驟,完成時在/usr/local/下面會產生一個nginx目錄

   2)在nginx中配置rtmp服務

worker_processes 1;
events { worker_connections 1024; }
rtmp { server { listen
1935; chunk_size 4000; application play { play /usr/local/nginx/html/play; } application hls { live on; hls on; hls_path /usr/local/nginx/html/hls; hls_fragment 1s; hls_playlist_length 4s; } application live { live on; } } } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 8000; server_name localhost; location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { # XML stylesheet to view RTMP stats. # Copy stat.xsl wherever you want # and put the full directory path here root /usr/local/nginx-rtmp-module; } location /hls { # Serve HLS fragments types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } root /usr/local/nginx/html; add_header Cache-Control no-cache; } } }

   說明:

  a、rtmp配置:

    play為視頻播放配置,靜態文件播放。

    hls為通過推送的方式,保存視頻片段ts文件,通過m3u8來播放。

    live就只是單純的視頻流推送。

  其中hls的配置相對復雜,主要涉及延時優化的功能,一般采用如下配置:

hls_fragment 1s;
hls_playlist_length 4s;

   b、http配置:

       stat和stat.xsl主要訪問視頻推送概況,注意目錄指向

    hls主要是配置視頻流的訪問(m3u8格式視頻)

  3)啟動:

# ./sbin/nginx -c conf/nginx.conf

  4)測試(測試工具VLC):

  a、第一種,play

   鏈接:

rtmp://192.168.5.23:1935/play/test.mp4

 

   b、第二種、hls這里我們需要一個推流軟件obs來測試,obs下載

   根據推送的地址,我們有兩種測試方式,一種為rtmp,一種為m3u8

  rtmp地址:

rtmp://192.168.5.23:1935/hls/test

   可以看出現在是存在一些延遲,但是延遲不是很大可以接受。

  m3u8地址:

http://192.168.5.23:8000/hls/test.m3u8

 

   這里可以看出延遲就很高了,如果對於延遲較小的方式這種方式就不是很適合了

   c、第三種方式,live(這種方式和rtmp的第一種是一樣的,只是沒有了hls的方式來緩存)

  鏈接:

rtmp://192.168.5.23:1935/live/test

  四、上面只是對於視頻流的推送做了很多配置,下面我們通過實例的方式來呈現工程中的應用。
  1)說一下架構,基本采用springboot,videojs實現。目錄結構為
  

 

   2)springboot的配置基本沒啥,主要是通過videojs提供的方式去實現流的讀取

  m3u8(hls.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hls</title>
    <link href="css/video-js.css" rel="stylesheet">
    <script src="js/video.js"></script>
    <script src="js/hls/videojs-contrib-hls.js"></script>

</head>
<body>
<h1>hls</h1>

<!--常用-->
<video class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="460" height="256" data-setup='{}'>
    <source src="http://192.168.5.23:8000/hls/test.m3u8" type="application/x-mpegURL">
</video>

<!--video-js標簽-->
<video-js class="vjs-default-skin vjs-big-play-centered" controls preload="auto" width="460" height="256" data-setup='{}'>
    <source src="http://192.168.5.23:8000/hls/test.m3u8" type="application/x-mpegURL">
</video-js>

<!--選擇器-->
<video id="test" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="460" height="256">
    <source src="http://192.168.5.23:8000/hls/test.m3u8" type="application/x-mpegURL">
</video>

<script>
    // {}和data-setup一樣,function為回調函數
    var player = videojs("test", { "autoplay":true }, function (res) { console.log(res) }); player.play(); </script>
</body>
</html>

  m3u8(stream.html)

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8 />
    <title>stream</title>
    <link href="css/video-js.css" rel="stylesheet">
    <script src="js/video.js"></script>
    <script src="js/stream/videojs-http-streaming.js"></script>
</head>
<body>
<h1>stream</h1>
<video class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="1366" height="768" data-setup='{}'>
    <source src="http://192.168.5.23:8000/hls/test.m3u8" type="application/x-mpegURL">
</video>
</body>
</html>

  rtmp(rtmp.html)

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>rtmp</title>
    <link href="css/video-js.css" rel="stylesheet">
    <script src="js/video.js"></script>
    <script src="js/rtmp/videojs-flash.min.js"></script>
</head>
<body>
<h1>rtmp</h1>
<video class="video-js vjs-default-skin vjs-big-play-centered" width="1366" height="768" data-setup='{"techOrder":["flash"], "autoplay":true}'>
    <source src="rtmp://192.168.5.23:1935/hls/test" type="rtmp/flv">
</video>
<script> videojs.options.flash.swf="js/rtmp/video-js.swf"; </script>
</body>
</html>

  3)為了更加接近項目我這里使用了攝像頭的來達到想過,實現方式通過ffmpeg進行攝像頭流的推送

  ffmpeg安裝

# apt-get install ffmpeg

  rtsp推送方式:

ffmpeg -rtsp_transport tcp -i 'rtsp://admin:admin1234@192.168.112.252:554/cam/realmonitor?channel=1&subtype=0' -stimeout '3000000' -vcodec copy -acodec copy -f flv -y 'rtmp://localhost:1935/hls/test'
package com.cetc.ffmpeg; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @Component public class InitCamera implements CommandLineRunner{ private static Logger logger  = LoggerFactory.getLogger(InitCamera.class); @Override public void run(String... args) throws Exception { String shell = 
      "ffmpeg -rtsp_transport tcp -i 'rtsp://admin:admin1234@192.168.112.252:554/cam/realmonitor?channel=1&subtype=0' -stimeout '3000000' -vcodec copy -acodec copy -f flv -y 'rtmp://localhost:1935/hls/test'"; String[] cmd = new String[] {"sh", "-c", shell};
     ThreadLocal<String[]> threadLocal = new ThreadLocal<>();
new Thread(new Runnable() { @Override public void run() { threadLocal.set(cmd); while (true) { try { Process process = Runtime.getRuntime().exec(threadLocal.get()); new Thread(() -> { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); String str; try { logger.info("start"); while ((str = bufferedReader.readLine()) != null) { logger.info(str); } logger.info("exit"); process.exitValue(); } catch (IOException e) { e.printStackTrace(); } }).start(); process.waitFor(); logger.info("ffmpeg restart"); } catch (Exception e) { e.printStackTrace(); } } } }).start(); } }

  4)通過springboot,maven插件打成jar包,運行

java -jar spring-nginx-rtmp-1.0-SNAPSHOT.jar &

  5)測試結果

  特別說明:videojs這類視頻流的方式不能使用本地html的測試方式,必須使用容器啟動,比如(tomcat,node,jetty等)
  我這里使用的springboot框架,底層還是tomcat支持,請熟知。
  五、參考的相關文檔
  1)nginx-rtmp-module安裝及配置:https://github.com/arut/nginx-rtmp-module
  2)nginx-rtmp-module配置詳情:https://github.com/arut/nginx-rtmp-module/wiki/Directives
  3)videojs:
    https://blog.videojs.com/ 官方博客
    https://docs.videojs.com/tutorial-options.html videojs的相關參數配置
  4)ffmpeg:http://ffmpeg.org/ffmpeg.html
  六、Javaweb端源碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM