如何用Python调用gphoto2实现DSLR每秒定时拍照及视频录制?
问题1:Python实现gphoto2每秒一张照片(存储至相机SD卡)
已知命令行gphoto2 --I 2 -F 5 --capture-image-and-download可实现间隔2秒拍摄5张照片,但需在Python中实现间隔1秒拍摄、照片保存至相机SD卡的需求。当前使用--trigger-capture虽比--capture-image速度更快,但无法精准控制间隔,且实际间隔均超过1秒,现有代码如下:
#!/usr/bin/env python3 import subprocess import time from datetime import datetime from sh import gphoto2 as gp import signal, os, subprocess #kill gphoto2 process that occurs whenever connect camera def killgphoto2(): p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) out,err = p.communicate() for line in out.splitlines(): if b'gvfsd-gphoto2' in line: #kill process pid = int(line.split(None, 1)[0]) os.kill(pid, signal.SIGKILL) triggerCommand = ["--trigger-capture"] killgphoto2() start_time = time.time() for i in range(5): gp(triggerCommand) end_time = time.time() print(end_time - start_time)
解决方案
方案1:直接调用gphoto2自带的间隔拍摄参数(推荐)
利用gphoto2原生的--interval(简写-I)和--frames(简写-F)参数,由相机端控制拍摄间隔,比Python循环更精准,且无需手动处理延迟:
#!/usr/bin/env python3 import subprocess import signal, os def killgphoto2(): p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) out, err = p.communicate() for line in out.splitlines(): if b'gvfsd-gphoto2' in line: pid = int(line.split(None, 1)[0]) os.kill(pid, signal.SIGKILL) killgphoto2() # 间隔1秒拍摄5张,照片直接存相机SD卡 subprocess.run([ 'gphoto2', '--interval', '1', '--frames', '5', '--trigger-capture' ])
方案2:手动控制循环与间隔(适用于需中途执行额外逻辑)
若需要在拍摄间隙执行其他操作,可通过计算拍摄耗时动态调整睡眠时长,尽量保证间隔接近1秒:
#!/usr/bin/env python3 import subprocess import time import signal, os def killgphoto2(): p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) out, err = p.communicate() for line in out.splitlines(): if b'gvfsd-gphoto2' in line: pid = int(line.split(None, 1)[0]) os.kill(pid, signal.SIGKILL) killgphoto2() trigger_cmd = ['gphoto2', '--trigger-capture'] total_shots = 5 target_interval = 1 # 目标间隔1秒 for i in range(total_shots): shot_start = time.time() # 执行拍摄,屏蔽输出避免干扰 subprocess.run(trigger_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # 计算剩余睡眠时间,减去拍摄耗时 elapsed = time.time() - shot_start sleep_time = max(0, target_interval - elapsed) # 最后一次拍摄后无需睡眠 if i < total_shots - 1: time.sleep(sleep_time)
注意:若相机单次拍摄处理时间超过1秒,无法达到每秒一张的间隔,需确认相机连拍性能是否支持该需求。
问题2:树莓派利用相机SD卡录制原生分辨率/帧率视频
当前用OpenCV录屏帧率不稳定,希望通过gphoto2或其他工具让相机直接在SD卡录制原生参数视频。
解决方案
通过gphoto2控制相机原生录像功能,树莓派仅发送开始/停止命令,录像全程由相机处理,完全使用相机原生分辨率、帧率与编码:
1. 先确认相机的录像控制参数
执行命令查看相机支持的配置项:
gphoto2 --list-config
不同品牌相机参数名不同:
- 佳能相机:通常为
eosremoterecord(1=开始,0=停止) - 尼康相机:可能为
movie(on=开始,off=停止)
2. Python实现代码示例(以佳能相机为例)
#!/usr/bin/env python3 import subprocess import signal, os import time def killgphoto2(): p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) out, err = p.communicate() for line in out.splitlines(): if b'gvfsd-gphoto2' in line: pid = int(line.split(None, 1)[0]) os.kill(pid, signal.SIGKILL) killgphoto2() # 开始录像 subprocess.run(['gphoto2', '--set-config', 'eosremoterecord=1']) # 录制10秒(可根据需求调整时长) time.sleep(10) # 停止录像 subprocess.run(['gphoto2', '--set-config', 'eosremoterecord=0'])
此方式完全规避树莓派的性能瓶颈,录像质量与相机原生录像一致。
内容的提问来源于stack exchange,提问作者Benjy
相关产品推荐
相关产品推荐

