樹莓派搭建影片監控平台
上一次用樹莓派搭建了Nexus私服,終於讓樹莓派不再成為吃灰派了,這次用樹莓派搭建影片監控平台,並實現影片畫面推流到流媒體伺服器。
1. 安裝nginx
要實現將影片畫面推動到媒體伺服器,需要搭建一個流媒體伺服器,這裡選擇nginx + flv module 來搭建,需要用到的源碼包如下:
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。
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配置。
cd /usr/local/nginx
sudo mv nginx.conf nginx.conf.def
sudo vim nginx.conf
自己的nginx.conf如下:
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推流
ffmpeg.exe -ss 0 -i out.mp4 -acodec copy -f flv rtmp://192.168.1.26:1935/live/t1
最後用VLC播放影片流,如果以上所有操作沒有出現錯誤,將可以在VLC中看到影片畫面。
3. 測試攝影機
要搞影片監控還需要一個攝影機,這裡使用的是樹莓派CSI介面中的攝影機,如果攝影機功能沒有開啟的話需要在樹莓派開啟。
sudo raspi-config
選擇 1. Interfacing Options
然後再選擇 P1 Camera
選擇「是」,然後重啟樹莓派。
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="//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中指定的平台訪問埠
啟動成功後,可以在電腦上訪問平台:
//192.168.1.26:8080
然後填寫推流地址,點擊開始監控即可。
這樣,基於樹莓派的影片監控平台就部署好了。如果要關閉影片監控,只需要點擊頁面上的 斷開監控 即可。
6. 拓展玩法
這裡為了實踐我是自己在樹莓派上搭建了一個基於nginx + flv module 的流媒體伺服器,當然還有很多玩法。
比如:
a. 在線上伺服器搭建流媒體伺服器,然後將影片流推送到線上伺服器,這樣就可以實現遠程影片監控。
b. 另外也可以將影片流推送到直播平台,實現直播。
=========================================================
項目源碼可關注公眾號 「HiIT青年」 發送 「raspi-video」 獲取。
關注公眾號,閱讀更多文章。