让我们使用树莓派4和GStreamer来创建一个流媒体服务器
做的事情
使用树莓派4(Raspberry Pi 4,内存4GB)连接摄像头创建流媒体环境。由于树莓派上没有麦克风,因此只能传输无声音的图像。另外,经确认也可以在树莓派3(Raspberry Pi 3 model B+)上安装该环境。
如果你暫時需要這份檔案的話
如果您没有建立流媒体服务器,但想要.m3u8、.ts文件,请从这里下载。
我会将HLS直播流数据存放在测试用途上。
1. 参考一下
ラズパイを映像展示用デバイスにした話
ラズパイにNodejsインストール
[メモ]video.jsでHLS配信をやってみた
Video.jsの使い方
Raspberry Pi + Node.jsでSkyWayを動かしてみる
GStreamerのインストール
图示
通过使用GStreamer和Nodejs将连接了摄像头的树莓派转变为流媒体服务器。
此外,还会设置CORS并使得流媒体数据能够在另一台WEB服务器上使用。
环境
-
- ラズパイ
Raspberry Pi 4 Model B 4GB
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 10 (buster)
Release: 10
Codename: buster
- カメラ
请参考指示参照原文。
相机支持的格式。
$ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'YU12' (Planar YUV 4:2:0)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[1]: 'YUYV' (YUYV 4:2:2)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[2]: 'RGB3' (24-bit RGB 8-8-8)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[3]: 'JPEG' (JFIF JPEG, compressed)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[4]: 'H264' (H.264, compressed)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[5]: 'MJPG' (Motion-JPEG, compressed)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[6]: 'YVYU' (YVYU 4:2:2)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[7]: 'VYUY' (VYUY 4:2:2)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[8]: 'UYVY' (UYVY 4:2:2)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[9]: 'NV12' (Y/CbCr 4:2:0)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[10]: 'BGR3' (24-bit BGR 8-8-8)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[11]: 'YV12' (Planar YVU 4:2:0)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[12]: 'NV21' (Y/CrCb 4:2:0)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
[13]: 'BGR4' (32-bit BGRA/X 8-8-8-8)
Size: Stepwise 32x32 - 2592x1944 with step 2/2
请按照这样的方式连接到树莓派。(图片仅为参考,显示的是非树莓派4的基板)
让我们安装GStreamer。
请安装GStreamer应用程序以进行流媒体传输。只需执行以下两个命令即可完成安装。(费了很大努力才明白这一点)
$ sudo apt install autoconf automake libtool
$ sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
让我们验证GStreamer的运行情况
我会立即创建流式数据。
$ mkdir test
$ cd test
$ sudo gst-launch-1.0 -v -e v4l2src device=/dev/video0 \
! video/x-h264,width=640,height=480,framerate=15/1 \
! h264parse ! mpegtsmux \
! hlssink max-files=8 target-duration=5 \
location=./segment%05d.ts \
playlist-location=output.m3u8 \
playlist-root=./
执行时的情况如下。
执行后,将会生成.m3u8和.ts文件。
$ ls
output.m3u8 segment00000.ts segment00001.ts segment00002.ts
让我们检查一下GStreamer的输出文件。
在.m3u8文件中,记录了与.ts文件的相对路径。要确认实际相对路径是否正确(我之前没有注意到这一点,所以遇到了一些麻烦)。
$ cat output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:9
#EXTINF:8.7807645797729492,
./segment00000.ts
#EXTINF:7.9985880851745605,
./segment00001.ts
#EXTINF:6.8206477165222168,
./segment00002.ts
我们来查看.ts文件。
将.ts文件复制到Windows上并双击运行。如果相机画面播放成功,则操作完成。(原来.ts文件是视频数据呀,真有趣)
让我们安装Node.js
现在我能使用GStreamer创建流数据。为了能在Web浏览器中打开这些数据,需要安装Node.js并将树莓派设置为Web服务器。
# npmを更新
sudo npm install npm@latest -g
# npmのバージョン確認
$ npm -v
# -> 6.13.4
$ sudo apt update
$ sudo apt install curl
$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
$ sudo apt install nodejs -y
# nodejsのバージョン確認
$ node -v
# -> v12.14.0
既然已经安装了Nodejs,我们来创建一个项目。
$ mkdir nodejs
$ cd nodejs
$ npm init
$ npm install --save express
$ touch app.js
$ mkdir wwwroot
$ touch wwwroot/test.html
把app.js文件设定为以下方式。
var express = require('express');
var app = express();
app.use(express.static('wwwroot'));
var port = 3000;
app.listen(port,function(){
console.log("サーバがポート%dで起動しました。モード:%s",port,app.settings.env)
});
将test.html文件设置如下。
<!DOCTYPE html>
<html><head></head><body>
TEST
</body></html>
我们将试运行以作为Web服务器运行。
$ pwd
/home/pi/nodejs
$ node app.js
サーバがポート3000で起動しました。モード:development
在浏览器中打开http://<树莓派的IP地址>:3000/test.html,如果网站成功打开,则表示成功。
让我们把它变成流媒体服务器吧!
我已经创建了流式数据并准备好Web服务器。我将使用这两个来搭建一个流媒体服务器。
具体来说,我们将使流媒体数据能够在HTML的标签中进行显示。为此,我们将使用video.js模块,以便在Chrome浏览器中也能够进行显示。
我已经将必要的文件(除了.m3u8和.ts文件)放置在Github上。请将它们存放在wwwroot文件夹下。
https://github.com/zgw426/GStreamerSample/tree/master/sample01
确保每个文件都以这样的方式进行配置,包括流数据。
$ pwd
/home/pi/nodejs/wwwroot
$ tree
.
├── output.m3u8
├── segment00056.ts
├── segment00057.ts
├── segment00058.ts
├── segment00059.ts
├── segment00060.ts
├── segment00061.ts
├── segment00062.ts
├── segment00063.ts
├── static
│ ├── css
│ │ └── video-js.min.css
│ └── js
│ ├── video.min.js
│ ├── videojs-contrib-hls.min.js
│ └── videojs-contrib-media-sources.min.js
└── streamtest.html
让我们打开一个流媒体网站试试看。
打开http://<树莓派的IP地址>:3000/streamtest.html,将显示此类画面。
只要能够播放视频,并能将连接到树莓派的摄像头画面显示为视频,那就是成功的。
现在,流媒体服务器已经完成了。
让跨域资源共享生效
我們會選擇第二種結構,根據前面的引言。
可以准备一个Web服务器,在那里可以进行流媒体传输。为了实现这一点,需要启用CORS(跨域资源共享)。
如果CORS未启用,则无法从’ http://yyy ‘源访问到 ‘http://xxx’ 的XMLHttpRequest被CORS策略阻止:所请求的资源上没有’Access-Control-Allow-Origin’头,因此无法再生。
无法进行CORS就会变成这样。 pic.twitter.com/bEVYQpEojs— j4amountain (@zsipparu) December 21, 2019
让我们在Node.js中安装CORS模块吧。
为了在树莓派的Node.js上启用CORS,需要安装一个模块。
$ npm install cors
将app.js文件修改如下。这样,CORS设置就完成了。
请注意:
这种设置使得资源可以从任何服务器访问,从安全角度来看,是非常危险的状态。理应只允许特定服务器访问,限制访问范围最小化。
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
app.use(express.static('wwwroot'));
var port = 3000;
app.listen(port,function(){
console.log("サーバがポート%dで起動しました。モード:%s",port,app.settings.env)
});
启用CORS后,使得其他计算机的Web服务器也能进行流媒体传输。
stream.html可以通过复制streamtest.html并按以下方式进行编辑来创建。
【更改前】
【更改后】
额外福利:延迟测试
在进行流媒体直播时会存在一定的延迟。为了验证延迟在长时间直播时会如何变化,我进行了16小时连续直播的测试。结果表明延迟并未显著增加,我个人对其满意。
结果