树莓派使用 Python 控制手机上的 DroidCam 自动拍照
需求
新买了个盆栽,想要关注盆栽的生长情况。如果是摄像,“代价”又有点大。想到了 DroidCam 这个软件,能够让手机变成监控摄像头。于是,可以利用它做一个自动拍照的延时摄影。
前期准备
- 手机(IOS、Android 均可) + DroidCam 软件
- 树莓派(常年开机的小主机,能用 Python就行)
- 其他重要的内容:
- 手机支架
- 手机充电的电源
大致效果如图
v1.0
在搭建完基本的设施之后,首先测试拍照功能,命令如下所示,将 $IP_ADDR 换成手机 IP 地址即可,DroidCam 主界面也会显示。默认端口是 4747
1 | wget "http://$IP_ADDR:4747/cam/1/frame.jpg" -O $(date +"%s").jpg |
然而,在把这行命令放到树莓派上的定时任务中时,遇到了几个问题
晚上光线暗
打开手机摄像头的闪光灯,命令如下所示
1 | curl "http://$IP_ADDR:4747/cam/1/led_toggle" \ |
没有对焦
自动对焦命令如下所示
1 | af_cmd = f"""curl "http://$IP_ADDR:4747/cam/1/af" \ |
这两个问题算是可以通过软件本身进行解决。但引发了一个新问题就是,不能知道手机是否已经开启闪光灯、是否已经对焦。前者可以通过时间判断,如果是白天则不开,但后者没办法控制。DroidCam 的逻辑是,每次只能有一个客户端打开网址,如果有多个客户端打开,后者会把前者踢下线,且状态为止。因此,最后决定每次拍两张照片,用照片大小来判断图片质量。
DroidCam 要求启动摄像头后,才能拍照
一个比较大的问题是,DroidCam 要求启动摄像头后,才能拍照。而如果没有客户端打开网址,则摄像头不会启动。因此,需要在请求前,去开启网址。
1 | def start_func(): |
如果长时间没有启动 DroidCam,手机则会自动息屏,导致之后的拍照全部失败。
实现
见下面代码的 take_picture.py
部分,只需将其设置为定时任务即可
*/10 * * * * cd /root/pics && /usr/bin/python3 take_picture.py
。每
10 分钟会去拍一次照,且会拍两张,以时间戳保存在 /root/pics
目录下。
v2.0
照片数据问题解决了,接下来就要处理照片的删除、处理、合成逻辑了。
见上面代码的 process.py
部分
简单来说分为三个部分:
- 获取当前文件夹下所有的图片,以时间戳进行排序,时间戳间隔小于 60 秒的照片,只保留一张(以图片大小定)。
- 按照日期进行移动,并打包成 zip 文件。
- 在 PC 端运行
python3 process.py --convert
,会拉取树莓派的压缩包,并解压 zip 文件,最后合成视频。(为什么不在树莓派上,性能太弱,很慢)
ffmpeg 合并命令如下所示,会预先按照时间戳排序,写入到
input.txt
文件中,然后合并成视频。
1 | ffmpeg -f concat -i input.txt -vf "fps=25" $OUTPUT |