You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:10:30