试用 Laravel + 树莓派搭建视频监控,并支持线上访问
上周受 YouTube 视频 的刺激,买了个树莓派,原作者用 Next.js 演示的,我买的是树莓派 5 的 8GB 版本的,跑 Laravel 肯定没问题。
树莓派搭建 Laravel 运行环境
树莓派是基于 Debian 的发行版,使用 APT 和 Systemd,我采用 PHP FPM + Caddy 方案,首先安装:
sudo apt install composer php-fpm caddy
安装成功后,PHP-FPM 和 Caddy 服务会自动运行,更新下 Caddy 配置:
# /etc/caddy/Caddyfile
:80 {
root * /srv/learn-raspi-laravel/public
php_fastcgi unix//run/php/php-fpm.sock
file_server
}
安装 Laravel 项目时会提示缺少一些 PHP 扩展,按照报错提示安装即可。
调用相机拍照
我买的套餐中包含了一个相机,有 500 万像素(我并不懂这个数字是啥意思),这是第一代树莓派相机,现在已经到第三代了,这是最便宜的,效果自然也最差。
像机连上主板就能拍照录像了,树莓派系统预装了 rpicam-apps 包,用命令 rpicam-jpeg
拍照、 rpicam-vid
录像,比如:
# 拍照
$ rpicam-jpeg --output frame.jpg
# 录像(默认5秒)
$ rpicam-vid -o video.mp4
简单封装下 rpicam-jpeg
, 就能给 Laravel 使用了:
<?php
// app/Http/Controllers/CameraController.php
class CameraController extends Controller
{
public function jpeg()
{
$path = Storage::disk('public')->path('frame.jpeg');
Process::run(sprintf('rpicam-jpeg -n -v 0 --width 640 --height 480 -o "%s"', $path))->throw();
return response()->file($path);
}
}
// web.php
Route::get('/jpeg', [CameraController::class, 'jpeg']);
这样每次访问 /jpeg
就能拍一张照片了,HTML 中使用 <img src="/jpeg">
就能显示了。
用 M-JPEG 实现视频直播
M 指 Motion,即动态的JPEG,服务器把一帧帧 JPEG 图片,按顺序发送,浏览器的 <img
标签原生支持,非常类似 SSE,这是最简单的播放视频直播的方案了,只是很好理解。
下面用 magick
演示下 M-JPEG 在 PHP 下的实现,效果是显示当前的时间会一直更新:
class MjpegController extends Controller
{
private function frame()
{
$path = storage_path('app/frame.jpeg');
Process::run(
sprintf(
'magick -size 300x100 xc:white -gravity center -pointsize 20 -annotate 0 "%s" %s',
now()->format('Y-m-d H:i:s'),
$path
)
)->throw();
return $path;
}
public function stream()
{
$response = response()->stream(null, 200, [
'Age' => 0,
'Cache-Control' => 'no-cache, private',
'Pragma' => 'no-cache',
'X-Accel-Buffering' => 'no',
'Content-Type' => 'multipart/x-mixed-replace; boundary=FRAME',
]);
$response->sendHeaders();
while (true) {
$path = $this->frame();
echo "--FRAME\r\n";
echo "Content-Type: image/jpeg\r\n";
echo 'Content-Length: '.filesize($path)."\r\n";
echo "\r\n";
readfile($path);
echo "\r\n";
if (ob_get_level() > 0) {
ob_flush();
}
flush();
sleep(0.2);
}
}
}
可惜的是,我准备把上面的 magick
替换成 rpicam-jpeg
,但是我发现这个命令是在是太慢了,一张图片需要5s,压根就没法儿用。
还是老老实实用 Python API 的实现,比命令行高效很多,虽然我不懂 Python,但是官方的例子直接就能跑:
- github.com/raspberrypi/picamera2/b... (默认 8000 端口)
为了方便后续代理到公网使用,把 http://localhost:8000/stream.mjpg
代理到 /stream.mjpg
:
# Caddyfile
:80 {
root * /home/xcy/learn-raspi-laravel/public
php_fastcgi unix//run/php/php-fpm.sock
file_server
@stream {
path /stream.mjpg
}
reverse_proxy @stream http://localhost:8000
}
然后在 Laravel 模版中使用 <img src="/stream.mjpg">
就能看到直播了。
用 Expose 公网访问
Expose 是一个用 PHP/Laravel Zero 开发的 ngrok 替代品,支持自托管。分享到公网:
expose share --subdomain=pi http://localhost;
Expose 代理非常容易内存溢出,特别是我们使用的 M-JPEG 方式,溢出之后会自动退出,为了避免退出,可以用简单的反噬重启下:
while true; do expose share --subdomain=pi http://localhost; done
大佬厉害啊
已经被你玩出花了 :+1:
学习了兄弟
牛。。。学习了
学习了兄弟
有点东西啊
当时也用树莓派做了一个视频监控,通过ssh数据转发实现线上访问,自己玩玩可以,要想达到专业监控那样的稳定性还差很多。
6哇
没有音频吗?
其实用golang玩树莓派更丝滑。
膜。。。膜拜大佬!直播的话可以搭建srs,或者webrtc,还能有音频。
我也准备买个树莓派玩一下,大家什么建议么?以免踩坑
老哥还是很厉害的,学习一下
在哪买的?有推荐吗?全套开发版那种也行