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

如何用OpenCV录制无加速的1080x720@30fps 10秒触发视频?

问题解决指南:PIR触发摄像头录制时长/分辨率问题

核心问题分析

  1. 录制时长加速:本质是帧率不匹配或计时逻辑错误——用time.sleep(10)无法保证录够300帧(30fps×10s),摄像头实际输出帧率与VideoWriter设置值不一致时,播放器会按设置帧率解码,导致时长压缩。
  2. 分辨率设置后视频损坏:一是使用了摄像头不支持的非标准分辨率(你提到的1080×720不是罗技C920的标准支持规格,它的720p是1280×720);二是VideoWriter的分辨率与摄像头实际输出分辨率不匹配;三是编码格式兼容性问题。

分步解决方案

一、修复录制时长问题

  • 放弃time.sleep,用帧计数控制时长:计算需要录制的总帧数(目标帧率×时长),循环读取并写入帧直到达到总帧数,确保实际时长准确。
  • 强制匹配摄像头帧率:先设置摄像头帧率,再读取实际生效的帧率传给VideoWriter,避免解码时的速度偏差。

二、解决分辨率与视频播放问题

  1. 使用摄像头支持的标准分辨率:罗技C920支持的主流规格是:
    • 720p: 1280×720@30fps
    • 1080p: 1920×1080@30fps
      不要使用非标准的1080×720,摄像头会自动降为兼容分辨率,导致VideoWriter参数不匹配。
  2. 正确设置分辨率的顺序:部分USB摄像头需要先设置帧率,再设置分辨率,否则参数不生效。
  3. 保证VideoWriter与摄像头分辨率完全一致:设置完摄像头参数后,必须读取实际生效的分辨率,再传给VideoWriter,不能硬写目标值。
  4. 选择兼容的编码格式:优先用MJPG编码(兼容性最强,对应.avi后缀),避免因系统缺少编码库导致视频损坏。

完整可运行代码

import cv2
import time
from pyfirmata import Arduino, util

# 初始化Arduino与PIR传感器
board = Arduino('COM3')  # 替换为你的Arduino串口
pir_pin = board.get_pin('d:2:i')
it = util.Iterator(board)
it.start()
pir_pin.enable_reporting()

# 目标参数(使用C920支持的标准规格)
TARGET_FPS = 30
TARGET_DURATION = 10
TOTAL_FRAMES = TARGET_FPS * TARGET_DURATION
TARGET_WIDTH = 1280  # 标准720p宽度
TARGET_HEIGHT = 720

# 初始化摄像头
cap = cv2.VideoCapture(0)
# 先设置帧率,再设置分辨率
cap.set(cv2.CAP_PROP_FPS, TARGET_FPS)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, TARGET_WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, TARGET_HEIGHT)

# 读取实际生效的参数,避免硬写不匹配
actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
actual_fps = cap.get(cv2.CAP_PROP_FPS)
print(f"实际运行参数:分辨率{actual_width}×{actual_height},帧率{actual_fps:.1f}fps")

# 初始化视频写入器(MJPG编码兼容性最优)
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('motion_record.avi', fourcc, actual_fps, (actual_width, actual_height))

try:
    while True:
        pir_state = pir_pin.read()
        if pir_state:
            print("检测到运动,启动录制...")
            frame_count = 0
            start_time = time.time()
            while frame_count < TOTAL_FRAMES:
                ret, frame = cap.read()
                if not ret:
                    print("读取帧失败,终止录制")
                    break
                out.write(frame)
                frame_count += 1
                # 可选:实时预览录制画面
                cv2.imshow('Recording', frame)
                if cv2.waitKey(1) == ord('q'):
                    break
            print(f"录制完成,共录制{frame_count}帧,实际时长{time.time()-start_time:.1f}秒")
            # 延迟避免PIR重复触发
            time.sleep(2)
        if cv2.waitKey(1) == ord('q'):
            break
finally:
    # 资源释放
    cap.release()
    out.release()
    cv2.destroyAllWindows()
    board.exit()

额外排查点

  • USB供电检查:C920在高分辨率下需要足够供电,建议使用USB3.0端口,避免因供电不足降规格。
  • 摄像头占用检查:确保没有其他软件(如视频会议工具)占用摄像头,否则OpenCV无法获取正确参数。
  • 编码库验证:如果需要使用H.264编码,Windows需安装OpenCV扩展包,Linux可安装libx264-dev,macOS通过brew安装ffmpeg。

内容的提问来源于stack exchange,提问作者leuji241

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:54:51