树莓派变身监控摄像头:用raspivid+Motion实现24小时录像(含断电保护方案)
树莓派变身监控摄像头:用raspivid+Motion实现24小时录像(含断电保护方案)
你是否想过,手边那块小小的树莓派,除了跑跑代码、做个智能家居中枢,还能承担更“硬核”的任务?比如,成为你家门口或工作间里一位不知疲倦的“哨兵”。没错,我们今天要聊的,就是如何将树莓派彻底改造为一台功能完备、稳定可靠的24小时监控摄像头。这不仅仅是简单调用一个录制命令,而是涉及硬件选型、软件协同、存储策略乃至应对突发断电的完整解决方案。对于智能家居DIY爱好者来说,这既是一次充满乐趣的技术实践,也是一个能切实解决安防、宠物看护或环境监测需求的落地项目。我们将从最基础的摄像头连接开始,一步步深入到如何让raspivid与开源监控软件Motion默契配合,并最终攻克连续录制中最令人头疼的存储管理和断电续录难题。整个过程,你会看到命令行工具的强大与开源软件的灵活,最终收获的,将是一套完全由你掌控、成本极低且扩展性极强的专属监控系统。
1. 硬件准备与系统环境搭建
在软件开始“施展魔法”之前,稳固的硬件基础是确保系统长期稳定运行的前提。很多人低估了24小时不间断运行对树莓派这个小身板的考验。
首先,摄像头模块的选择至关重要。树莓派官方摄像头模块(包括标准版和HQ高画质版)因其原生驱动支持和优秀的兼容性,无疑是首选。它们通过排线直接连接到树莓派的CSI接口,带宽充足,延迟极低。如果你手头有USB摄像头,理论上也能用,但需要额外考虑USB端口的供电稳定性以及驱动兼容性问题,对于追求极致稳定的监控场景,官方CSI摄像头是更稳妥的选择。
注意:连接CSI摄像头排线时,务必确保树莓派已完全断电。排线卡扣需要轻轻拉起,将排线金属触点朝远离HDMI接口的方向插入,再按下卡扣锁紧。一个接触不良的排线是后期所有诡异问题的根源。
接下来是树莓派本体。对于7x24小时监控任务,散热是第一个拦路虎。尤其是在夏季或通风不佳的角落,过热会导致CPU降频,进而可能引起raspivid进程卡顿甚至Motion服务崩溃。强烈建议为你的树莓派(尤其是3B+、4B或更高型号)配备一个被动散热片或小型主动散热风扇。一个简单的铝制散热片就能显著改善核心温度。
# 在树莓派上实时查看CPU温度
vcgencmd measure_temp
供电则是第二个关键点。监控系统最怕的就是意外断电导致录像中断,以及不稳定的电源导致SD卡文件系统损坏。请务必使用官方推荐或质量可靠的5V/3A电源适配器。劣质电源的电压波动,是SD卡“暴毙”的元凶之一。为了应对计划外断电,我们会在软件方案部分详细讨论,但硬件上,一块不间断电源(UPS)模块或大容量充电宝作为后备电源,能为系统提供宝贵的关机缓冲时间,是专业级方案的标配。
最后是存储介质。持续录像产生的数据量是惊人的。以1080p@30fps,中等码率计算,每小时可能产生1GB以上的数据。因此,一张高速、高耐久度的Micro SD卡(建议Class 10或UHS-I以上,容量至少32GB)是基础。但对于真正的长期部署,强烈推荐将录像存储转移到USB外接移动硬盘或网络存储(NAS) 上。这不仅能提供海量存储空间,还能避免频繁读写对SD卡寿命的损耗,毕竟SD卡损坏意味着整个系统需要重装。
2. 核心工具:raspivid的深度参数调优
raspivid是树莓派官方的视频编码捕获工具,它直接调用GPU进行H.264编码,效率极高。但把它当作一个简单的录制命令就大材小用了。在监控场景下,我们需要对其参数进行精细调整,以在画质、文件大小和系统负载之间找到最佳平衡点。
基础的录制命令大家可能都见过:
raspivid -o video.h264 -t 10000
这个命令录制10秒的H.264原始流到video.h264文件。但对于监控,我们需要它持续运行,并作为Motion服务的“视频源”。这时,-t 0参数让录制无限进行,并通过管道将数据输出到标准输出(stdout)是关键。
# 将raspivid的实时视频流输出到标准输出,供其他程序使用
raspivid -t 0 -w 1280 -h 720 -fps 15 -b 1500000 -o -
让我们拆解一下这些为监控优化过的参数:
-t 0: 无限时录制。-w 1280 -h 720: 分辨率设置为720p。对于大多数室内监控场景,1080p固然清晰,但产生的数据量是720p的2倍多。720p在保证人脸、物体可辨识度的同时,能极大减轻存储和网络(如果远程查看)压力。-fps 15: 帧率设为15帧/秒。电影是24fps,监控15fps已经非常流畅,相比30fps,能减少一半的数据量,同时对动态变化的记录完全足够。-b 1500000: 比特率设为1.5 Mbps。这是控制视频体积和画质的核心。更高的比特率画质更好但文件更大。1.5Mbps对于720p@15fps是一个经验值,可以在清晰度和存储间取得良好平衡。-o -: 这是精髓所在。-代表将视频流输出到标准输出,而不是文件。这样,其他程序(如Motion)就能通过管道实时获取这个视频流进行处理。
此外,还有一些提升体验的参数:
--rotation 180: 如果你的摄像头是倒着装(比如装在屋顶),用这个参数旋转画面。--exposure night: 在夜间或低光照环境下,可以尝试切换曝光模式为night,但注意这可能会增加画面噪点。通常auto模式已足够智能。--annotate 12: 在视频画面上叠加时间戳(12表示显示日期和时间)。这对于取证至关重要。
为了更直观地对比不同场景下的参数选择,可以参考下表:
| 应用场景 | 推荐分辨率 | 推荐帧率 (fps) | 推荐比特率 | 关键考量 |
|---|---|---|---|---|
| 室内静态监控 (如看护物品) | 720p (1280x720) | 10-15 | 1 - 1.5 Mbps | 节省存储,画面变化少 |
| 室内动态监控 (如门口、客厅) | 720p 或 1080p | 15-20 | 1.5 - 2.5 Mbps | 平衡动态清晰度与存储 |
| 低光照环境 | 720p | 10-15 | 1 - 2 Mbps | 提高比特率补偿噪点,可尝试--exposure night |
| 需要细节辨识 (如车牌) | 1080p (1920x1080) | 20-25 | 3 - 5 Mbps | 优先保证关键画面清晰度 |
调优完成后,你可以先单独测试raspivid的输出是否正常:
# 测试10秒,将流保存为文件查看
raspivid -t 10000 -w 1280 -h 720 -fps 15 -b 1500000 -o test.h264
# 使用vlc或omxplayer播放测试文件
omxplayer test.h264
3. 智能监控中枢:Motion的配置与集成
raspivid提供了稳定优质的“原料”(视频流),而Motion则是负责加工和响应的“大脑”。它是一个轻量级、开源的运动检测程序,能分析视频流,当画面发生变化时触发录像、拍照或执行其他命令。
首先安装Motion。在树莓派上,通常可以通过包管理器直接安装:
sudo apt update
sudo apt install motion
安装完成后,需要重点配置/etc/motion/motion.conf文件。这个文件选项众多,但针对与raspivid的集成和监控优化,以下几个部分是核心:
1. 守护进程与基本设置:
daemon on
# 让Motion以守护进程模式运行
process_id_file /var/run/motion/motion.pid
# 设置进程ID文件路径
logfile /var/log/motion/motion.log
# 设置日志文件路径,便于排查问题
2. 视频设备配置(关键!):
这里我们不是使用普通的/dev/video0设备,而是使用raspivid产生的视频流。
videodevice /dev/video0
# 对于raspivid流,这个通常不用,但可以保留或注释掉
input -1
# 输入设为-1,表示从标准输入读取数据
width 1280
height 720
framerate 15
# 这里的宽、高、帧率必须与前面raspivid命令的参数完全一致!
3. 运动检测与输出设置:
threshold 1500
# 运动检测灵敏度。值越低越敏感,但也更容易因光线变化误报。需要根据环境调整。
event_gap 10
# 事件间隔(秒)。两次独立运动事件之间的最短时间,小于此间隔会合并为一个事件。
output_pictures off
# 关闭输出静态图片,如果只需要录像的话。
ffmpeg_output_movies on
# 使用ffmpeg将检测到的运动事件录像,并封装成更通用的格式(如MP4)。
ffmpeg_bps 1500000
# 输出视频的比特率,建议与raspivid输入流一致。
movie_filename %Y-%m-%d/%H-%M-%S
# 录像文件命名格式。这里示例按`年-月-日/时-分-秒`创建文件夹和文件,非常清晰。
target_dir /mnt/usbdrive/motion_captures
# **重要**:指定录像存储目录。强烈建议指向外接USB硬盘或网络挂载的目录,而非SD卡。
4. 将raspivid与Motion联动:
我们需要创建一个系统服务,让两者协同工作。创建一个新的服务文件,例如/etc/systemd/system/raspivid-motion.service:
[Unit]
Description=Raspivid feed to Motion
After=network.target
[Service]
Type=simple
User=motion
ExecStart=/bin/bash -c '/usr/bin/raspivid -t 0 -w 1280 -h 720 -fps 15 -b 1500000 -rot 180 -o - | /usr/bin/motion -n'
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
这个服务文件做了几件重要的事:
- 以
motion用户身份运行,提升安全性。 ExecStart命令使用管道|:raspivid将视频流输出到标准输出,然后直接通过管道传递给motion的标准输入。Restart=always和RestartSec=5确保了无论哪个进程意外退出,系统都会在5秒后自动重启整个服务,极大增强了稳定性。
启用并启动这个服务:
sudo systemctl daemon-reload
sudo systemctl enable raspivid-motion.service
sudo systemctl start raspivid-motion.service
# 检查服务状态和日志
sudo systemctl status raspivid-motion.service
sudo journalctl -u raspivid-motion.service -f
现在,你的树莓派已经成为一个能自动检测运动并触发录像的智能摄像头了。所有录像文件都会按照日期组织在你指定的目录下。
4. 存储管理与循环录制策略
24小时不间断录像,即使只录制运动事件,日积月累也会占用大量空间。如果没有管理策略,硬盘再大也会被撑满。我们需要实现自动清理旧文件的功能。
最优雅的方式是利用Linux自带的logrotate工具,它本用于轮转日志,但处理录像文件同样得心应手。在/etc/logrotate.d/目录下创建一个配置文件,比如motion-videos:
/mnt/usbdrive/motion_captures/*/*.mp4 {
daily
# 每天检查一次
rotate 7
# 保留最近7天的文件
compress
# 压缩旧文件以节省空间(注意:压缩H.264视频效果有限,但可压缩元数据)
delaycompress
# 延迟压缩,在下次轮转时才压缩上一次的文件
missingok
# 如果目录或文件不存在,不报错
notifempty
# 如果文件为空,不轮转
create 0640 motion motion
# 轮转后创建新文件时的权限和属主
postrotate
# 可以在这里重启motion服务或发送通知(可选)
# systemctl restart raspivid-motion.service
endscript
}
这个配置会每天检查,删除超过7天的录像文件(.mp4)。rotate 7表示保留7份,结合daily就是保留7天。你可以根据硬盘大小和录制频率调整这个数字,比如rotate 30保留一个月。
然而,logrotate是按时间周期清理。对于监控,另一种常见需求是按磁盘空间清理:当硬盘使用率达到一定阈值(如90%)时,自动删除最旧的录像文件,直到使用率下降到安全线以下。这可以通过一个简单的Shell脚本配合cron定时任务来实现:
#!/bin/bash
# 文件:/usr/local/bin/cleanup_motion.sh
TARGET_DIR="/mnt/usbdrive/motion_captures"
USAGE_THRESHOLD=90
# 获取目标目录所在磁盘的使用率
USAGE=$(df "$TARGET_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$USAGE" -gt "$USAGE_THRESHOLD" ]; then
echo "$(date): Disk usage $USAGE% > $USAGE_THRESHOLD%, cleaning old files..."
# 按时间排序,删除最老的一些文件,直到使用率低于阈值
# 这里采用简单的删除最旧日期目录的方式,更精细可以删除具体文件
find "$TARGET_DIR" -type f -name "*.mp4" -printf '%T+ %p\n' | sort | head -n 50 | awk '{print $2}' | xargs rm -f
# 记录清理日志
echo "$(date): Cleanup performed." >> /var/log/motion_cleanup.log
fi
然后赋予脚本执行权限,并添加到crontab,例如每小时检查一次:
sudo chmod +x /usr/local/bin/cleanup_motion.sh
sudo crontab -e
# 在crontab中添加一行:
0 * * * * /usr/local/bin/cleanup_motion.sh
结合时间周期(logrotate)和空间触发(cron脚本)两种策略,你的监控系统的存储管理就变得非常健壮和自动化了。
5. 应对意外断电:实现录像不间断与安全关机
断电是监控系统最大的敌人之一,它可能导致两个问题:一是正在录制的视频文件损坏;二是SD卡文件系统因突然断电而出现错误,导致系统无法启动。我们的目标是:1. 确保断电瞬间的录像不丢失;2. 给系统争取安全关机的时间。
方案一:利用文件系统的特性。 我们可以配置Motion,将录像先写入一个临时目录,这个目录位于内存(tmpfs) 中。内存读写速度极快,且断电后内容会丢失,但这正是我们想要的——我们只把已完成的录像事件文件,定期从内存移动到永久存储(USB硬盘)。这样,即使突然断电,损失的也只是内存中尚未移走的、最近几秒或几分钟的缓存数据,而之前已保存的事件都是完整的。修改Motion配置:
target_dir /tmp/motion_cache
# 临时缓存目录,指向内存文件系统
# 在/etc/fstab中添加一行,确保重启后挂载:
# tmpfs /tmp/motion_cache tmpfs defaults,size=100M 0 0
# 然后 sudo mount -a
再编写一个脚本,每隔一段时间(如1分钟)将/tmp/motion_cache中已完成的文件移动到永久目录,并确保文件名按日期归类。这个脚本同样由cron驱动。
方案二(更彻底):硬件UPS + 软件监控。 这是更专业的方案。为树莓派配备一个微型UPS模块(如通过GPIO或USB连接的电池模块)。当检测到外部电源断开(UPS开始供电)时,触发一个脚本。这个脚本首先应立即通知Motion停止录制新事件(可以通过发送信号SIGTERM给进程),然后等待正在进行的录像完成(这很快),最后在UPS电量耗尽前执行安全关机 (sudo shutdown -h now)。
实现这个功能需要UPS模块提供电源状态检测(通常通过一个GPIO引脚的高低电平变化)。你可以编写一个Python脚本,使用RPi.GPIO库监控这个引脚。当检测到断电信号时,脚本执行以下流程:
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
import subprocess
import os
UPS_PIN = 17 # 假设UPS状态引脚接在GPIO17
GPIO.setmode(GPIO.BCM)
GPIO.setup(UPS_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
try:
while True:
if GPIO.input(UPS_PIN) == GPIO.LOW: # 引脚变低,表示市电断开
print("主电源断开,UPS供电中。准备安全关机...")
# 1. 停止Motion服务,让其完成当前录像
subprocess.run(["sudo", "systemctl", "stop", "raspivid-motion.service"])
time.sleep(10) # 等待10秒,确保录像文件写入完成
# 2. 同步文件系统,确保所有数据写入磁盘
os.sync()
# 3. 安全关机
subprocess.run(["sudo", "shutdown", "-h", "now"])
break
time.sleep(1) # 每秒检查一次
except KeyboardInterrupt:
GPIO.cleanup()
将这个脚本设置为开机自启,它就会在后台默默守护。当市电恢复,树莓派重新启动后,监控服务也会自动恢复,实现了真正的“断电续录”。
我在自己的车库监控项目上就采用了方案二,配合一个支持GPIO信号的UPS模块。有一次小区检修停电数小时,系统平稳关机,来电后自动重启,录像记录中间只缺失了关机前最后几秒的画面,之前的录像文件全部完好无损。这种安心感,是任何纯软件方案都无法比拟的。硬件投入不大,但换来了整个系统可靠性的质的提升。
更多推荐

所有评论(0)