樹莓派搭建視頻監控平臺

上一次用樹莓派搭建了Nexus私服,終於讓樹莓派再也不成爲吃灰派了,此次用樹莓派搭建視頻監控平臺,並實現視頻畫面推流到流媒體服務器。css

樹莓派相關文章:html

  1. 樹莓派搭建nexus2.x私服
  2. 樹莓派搭建視頻監控平臺(本文)
  3. 樹莓派視頻監控平臺實現錄製歸檔
  4. 樹莓派實現人臉打卡機

1. 安裝nginx

要實現將視頻畫面推進到媒體服務器,須要搭建一個流媒體服務器,這裏選擇nginx + flv module 來搭建,須要用到的源碼包以下:java

nginx1.15.4.tar.gz
nginx-http-flv-module-1.2.6.tar.gz
openssl-1.1.0j.tar.gz
pcre-8.40.tar.gz

將上面全部的源碼在/usr/local/src下面解壓,而後配置並編譯安裝nginx。nginx

cd nginx1.15.4
sudo ./configure \
--sbin-path=/usr/local/nginx/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--add-module=../nginx-http-flv-module-1.2.6 \
--with-http_flv_module --with-http_mp4_module \
--with-http_ssl_module \
--with-pcre=../pcre-8.40 \
--with-http_ssl_module \
--with-openssl=../openssl-1.1.0j

sudo make
sudo make install

安裝完成後會在/usr/local/中多一個nginx目錄,這裏就是安裝好的nginx,這裏備份默認nginx配置nginx.conf,而後編寫本身的nginx配置。web

cd /usr/local/nginx
sudo mv nginx.conf nginx.conf.def
sudo vim nginx.conf

本身的nginx.conf以下:shell

worker_processes  1;
events {
    worker_connections  1024;
}
rtmp {
  server {
    listen 1935;
    application live {
      live on;
    }
  }
}

2. 測試推流

nginx + flv module 搭建完後能夠是用 ffmpeg 測試推流,首先啓動nginx。數據庫

cd /usr/local/nginx
sudo ./nginx

而後在windows平臺中使用ffmpeg推流vim

ffmpeg.exe -ss 0 -i out.mp4 -acodec copy -f flv rtmp://192.168.1.26:1935/live/t1

最後用VLC播放視頻流,若是以上全部操做沒有出現錯誤,將能夠在VLC中看到視頻畫面。windows

raspi-ffmpeg

3. 測試攝像頭

要搞視頻監控還須要一個攝像頭,這裏使用的是樹莓派CSI接口中的攝像頭,若是攝像頭功能沒有開啓的話須要在樹莓派開啓。服務器

sudo raspi-config

選擇 5. Interfacing Options

raspi5

而後再選擇 P1 Camera

raspip1

選擇「是」,而後重啓樹莓派。

sudo reboot

樹莓派重啓以後,能夠執行下面指令用攝像頭截圖,若是截圖成功說明攝像頭配置成功。

sudo modprobe bcm2835-v4l2
sudo raspistill -v -o camera.jpg

4. 平臺開發

全部環境準備完成後,剩下的就是開發一個能夠管理攝像頭推流的平臺了,這裏選用JavaCV + JFinal來開發視頻監控管理平臺。

下載JFinal demo

從JFinal官網下載JFinal 4.9 demo for maven的源碼,導入Eclipse開發工具,刪除不須要的代碼包括數據庫配置等。

只留下咱們須要的代碼:

DemoConfig.java
IndexController.java
index.html

開發攝像頭推流器

使用OpenCV採集攝像頭的視頻幀,而後使用FFmpeg推流,編碼方式採用H264,幀率是25。

package com.demo.stream;
/**
 * @author itqn
 */
public class StreamSender implements Runnable {

  private static final int FPS = 25;
  private String rtmpUri;
  private OpenCVFrameGrabber grabber;
  private FFmpegFrameRecorder recorder;
  private boolean running = false;

  public int width;
  public int height;

  public StreamSender(String rtmpUri) {
    this.rtmpUri = rtmpUri;
    this.init();
  }

  @Override
  public void run() {
    running = true;
    long startTime = System.currentTimeMillis();
    long timestamp = 0;
    while (running) {
      timestamp = 1000 * (System.currentTimeMillis() - startTime);
      if (timestamp > recorder.getTimestamp()) {
        recorder.setTimestamp(timestamp);
      }
      try {
        recorder.record(grabber.grab());
      } catch (Throwable e) {
        close();
      }
      try {
        TimeUnit.MILLISECONDS.sleep(1000 / FPS);
      } catch (Exception ignore) {}
    }
  }
  
  public void close() {
    running = false;
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (Exception ignore) {}
    destroy();
  }

  private void init() {
    try {
      grabber = new OpenCVFrameGrabber(0);
      grabber.start();
      Frame frame = grabber.grab();
      width = frame.imageWidth;
      height = frame.imageHeight;
    
      recorder = new FFmpegFrameRecorder(rtmpUri, width, height);
      recorder.setFormat("flv");
      recorder.setFrameRate(FPS);
      recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
      recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
      recorder.setVideoOption("preset", "slow");
      recorder.setVideoOption("tune", "zerolatency");
      recorder.start();
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }
  
  private void destroy() {
    try {
      recorder.close();
    } catch (Throwable ignore) {}
    try {
      grabber.close();
    } catch (Throwable ignore) {}
  }
}

編寫控制接口

調整一下IndexController的代碼,新增啓動監控和中止監控的接口。

public void start() {
  String rtmpUri = get("rtmpUri");
  if (StrKit.isBlank(rtmpUri)) {
    redirect("/?e=1");
    return;
  }
  try {
    StreamManager.INSTANCE.startSender(rtmpUri);
    redirect("/");
  } catch (Throwable e) {
    redirect("/?e=2");
  }
}

public void stop() {
  StreamManager.INSTANCE.stopSender();
  redirect("/");
}

編寫播放頁面

rtmp流播放採用videojs這個庫

<!DOCTYPE html>
<html>
<head>
<title>樹莓派視頻監控</title>
<link href="/css/video-js.css" rel="stylesheet">
<script src="/js/video.js"></script>
</head>
<body>
  <video id="video" class="video-js vjs-default-skin" controls
     poster="http://vjs.zencdn.net/v/oceans.png" preload="auto"
     width="#(width)" height="#(height)" data-setup="{}">
    <source src="#(streamUri)" type="rtmp/flv">
  </video>
  <br>
  <br>
  <div style="color: #ff0000">#(e)</div>
  <div>
    <form action="/start">
      推流地址 : 
      <input name="rtmpUri" value="#(streamUri??'rtmp://127.0.0.1:1935/hls/test')"/>
      <br><br>
      <button>開啓監控</button>
    </form>
    <br>
    <form action="/stop">
      <button>斷開監控</button>
    </form>
  </div>
</body>
</html>

5. 部署平臺

平臺開發完成後須要將平臺部署到樹莓派中運行起來便可,JFinal默認的demo已經提供了啓停腳本,因此只須要在Eclipse中執行 mvn install 便可。

打包成功後,在項目的target目錄下面會有以下結構:

jfinal_demo_for_maven-release
\jfinal_demo_for_maven
\-\config
\-\lib
\-\webapp
\-\jfinal.sh
# 另外咱們須要將target目錄下的jfinal_demo_for_maven-4.9.jar複製到lib目錄下。

將上面的jfinal_demo_for_maven整個目錄FTP上傳到樹莓派中,啓動平臺:

sudo ./jfinal.sh start
# 這裏能夠改動jfinal.sh中指定的平臺訪問端口

啓動成功後,能夠在電腦上訪問平臺:

http://192.168.1.26:8080

而後填寫推流地址,點擊開始監控便可。

raspi-stream

這樣,基於樹莓派的視頻監控平臺就部署好了。若是要關閉視頻監控,只須要點擊頁面上的 斷開監控 便可。

6. 拓展玩法

這裏爲了實踐我是本身在樹莓派上搭建了一個基於nginx + flv module 的流媒體服務器,固然還有不少玩法。

好比:

a. 在線上服務器搭建流媒體服務器,而後將視頻流推送到線上服務器,這樣就能夠實現遠程視頻監控。

b. 另外也能夠將視頻流推送到直播平臺,實現直播。

=========================================================
項目源碼可關注公衆號 「HiIT青年」 發送 「raspi-video」 獲取。

HiIT青年
關注公衆號,閱讀更多文章。

!文章被用戶(百度帳號:cuixiaoyande)抄襲,同時在頭條號(頭條號:cuixiaoyande)上也被此用戶抄襲。
百家號文章
頭條舉報結果

相關文章
相關標籤/搜索