Viseron 3.7.0 配置参数详解

Viseron 3.7.0 config.yaml 逐域参数详解:ffmpeg 取流、mog2 运动检测、darknet 物体检测与 labels 过滤、录像行为、存储分层、MQTT 事件输出、Web 认证限流与日志,默认值+实测回显双重支撑(2026-10-30)。

ViseronViseronNVR摄像头视频监控RTSP2026/10/30

Viseron 3.7.0 配置参数详解

目标:把 Viseron 3.7.0 的 config.yaml 按配置域逐个讲透——ffmpeg 取流、mog2 运动检测、darknet 物体检测与标签过滤、录像行为、存储分层、MQTT 事件输出、NVR 协调、Web/API 与日志,每个关键参数给出默认值、取值含义,并用实测回显(日志、REST API 响应、MQTT 抓包)验证参数改动的实际行为。全部命令与回显在 Ubuntu 22.04 服务器实测跑出(2026-10-30),部署方式与模拟摄像头接入见《Viseron 3.7.0 Docker Compose 部署指南》。

一、环境信息

本篇全部参数验证在下列环境中完成,所有回显均为真实输出(2026-10-30):

项目值
操作系统Ubuntu 22.04(Linux x86_64,6 核 CPU / 19GB 内存,无独立显卡)
Viseron3.7.0(官方渠道安装,内置 PostgreSQL 16.15 / FFmpeg 8.1 / go2rtc / nginx)
Web UI 端口8888(部署时映射为宿主 8151,见姊妹部署篇)
配置文件/config/config.yaml(挂载自宿主 /opt/viseron/config/config.yaml)
数据目录/segments、/snapshots、/thumbnails、/event_clips、/timelapse
模拟摄像头MediaMTX 1.21.3 提供 RTSP 流 rtsp://mediamtx:8554/cam(样例视频循环推流,768x432@12fps)
检测模型/detectors/models/darknet/yolov7-tiny.weights + yolov7-tiny.cfg(官方内置)
API 认证已启用,示例管理账号 admin / q1w2e3r4
检测阈值基线运动检测 mog2,物体检测 darknet(YOLOv7-tiny)

Viseron 的配置全部集中在一个 YAML 文件 /config/config.yaml,没有其他分散配置点;改配置 → 重启服务生效是唯一生效路径。官方文档站对每个组件域均有独立说明页(见文末参考链接),本篇以实测行为为主线逐一验证。

二、前置条件

阅读与复现本篇需要:

  1. 一套已跑通的 Viseron 3.7.0 环境:能打开 Web UI、能看到摄像头画面与事件列表。从零部署见《Viseron 3.7.0 Docker Compose 部署指南》,本篇所有命令在该环境上直接执行。
  2. 一个可用的摄像头源:真实 RTSP 摄像头或模拟源均可。本篇沿用部署篇的 MediaMTX 模拟源(样例视频 person-bicycle-car-detection.mp4 循环推流),画面中出现行人、自行车与汽车,正好覆盖 darknet 三个跟踪标签。
  3. 服务端能执行 curl 命令,用于查 API、验证配置生效。
  4. 已知管理账号:本环境启用了 webserver.auth,示例账号 admin / q1w2e3r4(首次启动时在引导页创建)。

💡 技术拓展:Viseron 的检测能力全部走「组件 + 域」模型——同一「运动检测域(motion_detector)」可有多个组件实现,同一「物体检测域(object_detector)」同样如此。主要同类选项对比:

域可选组件特点适用场景
motion_detectormog2OpenCV MOG2 背景建模,CPU 开销低通用场景首选,本篇实际采用
motion_detectorbackground_subtractor另一种背景减除实现,支持掩码矩形需要精细划定检测区域的场合
object_detectordarknetYOLO 系列权重(YOLOv7 等),CPU 可跑通用物体识别,本篇实际采用
object_detectoredgetpuGoogle Coral TPU 加速有 Coral USB 加速棒
object_detectoryolo / deepstack / codeprojectai其他推理后端或外部推理服务已有现成推理服务的部署
object_detectordlib / hailo人脸向检测或 Hailo 加速卡特定硬件生态

组件只负责「算」,域负责「管」:config.yaml 中每个域的 cameras 段才是与摄像头联动的关键,后文逐域展开。

三、参数查看与修改方式

3.1 配置文件位置与首次生成

Viseron 启动时读取 /config/config.yaml;文件不存在时首次启动会自动生成一份默认配置,覆盖「接一个摄像头 + 开一个检测器」的最小可用场景。本环境从部署篇一路实测而来,当前的基线配置如下:

# /config/config.yaml —— 部署篇的基线配置
ffmpeg:
  camera:
    fake_camera:
      name: Fake Camera
      host: mediamtx
      port: 8554
      path: /cam
      stream_format: rtsp
      fps: 12
      recorder:
        idle_timeout: 5

mog2:
  motion_detector:
    cameras:
      fake_camera:
        fps: 2

darknet:
  object_detector:
    model_path: /detectors/models/darknet/yolov7-tiny.weights
    model_config: /detectors/models/darknet/yolov7-tiny.cfg
    cameras:
      fake_camera:
        fps: 2
        scan_on_motion_only: false
        labels:
          - label: person
            confidence: 0.7
            trigger_event_recording: true
          - label: bicycle
            confidence: 0.7
            trigger_event_recording: true
          - label: car
            confidence: 0.7
            trigger_event_recording: true

nvr:
  fake_camera:

webserver:
  auth:
    session_expiry:
      days: 7

logger:
  default_level: info

逐段解读:

  • 顶层每个键就是一个组件名(ffmpeg、mog2、darknet、nvr、webserver、logger,以及可选的 mqtt、storage 等),Viseron 按「同名组件模块」加载,写错组件名会在启动日志里直接报模块缺失(见 3.4 节实测)。
  • nvr: 下按摄像头标识逐个开启 NVR 协调,是事件与录像联动的总开关,漏掉则该摄像头「只见画面不出事件」。
  • webserver.auth 配置后所有 REST API 需要认证;logger.default_level 控制全局日志级别。

3.2 通过 REST API 查看当前生效配置(实测)

改完配置后最可靠的确认方式是问服务本身:GET /api/v1/config 返回当前实际生效的配置(YAML 文本)。本环境已启用认证,先用管理账号在 Web UI(Profile 页)创建个人访问令牌(PAT),之后请求带 Authorization: Bearer 头即可:

# 查看当前生效配置(PAT 从 Web UI Profile 页创建)
curl -s -H "Authorization: Bearer vpat_eca2bf1a0881444ba2851348260bba724319b066cbd551a7813d06e5f321fc87f0834e09d1ea100129ff7b04c916a097c51176de132838b944353a716aea9f47" \
  http://127.0.0.1:8888/api/v1/config

实测回显(当前环境真实输出):

ffmpeg:
  camera:
    fake_camera:
      name: Fake Camera
      host: mediamtx
      port: 8554
      path: /cam
      stream_format: rtsp
      fps: 12
      recorder:
        idle_timeout: 5

mog2:
  motion_detector:
    cameras:
      fake_camera:
        fps: 2

darknet:
  object_detector:
    model_path: /detectors/models/darknet/yolov7-tiny.weights
    model_config: /detectors/models/darknet/yolov7-tiny.cfg
    cameras:
      fake_camera:
        fps: 2
        scan_on_motion_only: false
        labels:
          - label: person
            confidence: 0.7
            trigger_event_recording: true
          - label: bicycle
            confidence: 0.7
            trigger_event_recording: true
          - label: car
            confidence: 0.7
            trigger_event_recording: true

nvr:
  fake_camera:

webserver:
  auth:
    session_expiry:
      days: 7

logger:
  default_level: info

回显与磁盘上的 config.yaml 一致,说明该接口读的就是生效配置,可以用来核对「我改的到底生效了没」。

3.3 修改与生效:编辑 → 重启(实测)

修改 /config/config.yaml 后重启 Viseron 服务生效(部署篇的 Compose 环境用 docker compose restart viseron;Web UI 左侧 Configuration 页内置编辑器,保存后同样触发重启)。每次重启都完整走一遍「初始化 → 校验 → 装载组件 → 装载域」流程,本篇做参数实验时重启了 4 轮,每轮的启动日志结构都一致:

# 重启后跟踪主日志,确认装载结果
tail -f /config/viseron.log

实测回显(一轮完整启动,输出节选):

2026-10-30 11:32:49.166 [INFO    ] [viseron.core] - -------------------------------------------
2026-10-30 11:32:49.167 [INFO    ] [viseron.core] - Initializing Viseron 3.7.0
2026-10-30 11:32:49.168 [INFO    ] [viseron.components] - Setting up component data_stream
2026-10-30 11:32:49.170 [INFO    ] [viseron.components] - Setup of component webserver took 0.0 seconds
2026-10-30 11:32:49.172 [INFO    ] [viseron.components] - Setting up component storage
2026-10-30 11:32:49.184 [INFO    ] [viseron.components.storage] - Database connection established successfully
2026-10-30 11:32:49.202 [INFO    ] [viseron.components] - Setup of component darknet took 0.0 seconds
2026-10-30 11:32:49.204 [INFO    ] [viseron.components] - Setup of component mog2 took 0.0 seconds
2026-10-30 11:32:49.204 [INFO    ] [viseron.components] - Setting up component ffmpeg
2026-10-30 11:32:49.206 [INFO    ] [viseron.components] - Setting up component nvr
2026-10-30 11:32:49.241 [INFO    ] [viseron.domains] - Setting up domain camera with identifier fake_camera for component ffmpeg
2026-10-30 11:32:53.796 [INFO    ] [viseron.domains] - Setup of domain camera with identifier fake_camera for component ffmpeg took 3.5 seconds
2026-10-30 11:32:54.104 [INFO    ] [viseron.domains] - Setup of domain object_detector with identifier fake_camera for component darknet took 0.5 seconds
2026-10-30 11:32:54.109 [INFO    ] [viseron.components.nvr.nvr.fake_camera] - NVR for camera Fake Camera initialized
2026-10-30 11:32:54.562 [INFO    ] [viseron.core] - Viseron initialized in 5.4 seconds

验证要点:看到 Viseron initialized in N seconds 即代表全部组件与域装载成功;任何一个组件校验失败,对应行会变成 Setup of component mog2 failed 这样的失败行(3.4 节有实测原文),且相关域会被禁用。

3.4 非法参数的校验行为(实测)

Viseron 对配置的校验发生在启动阶段,错误信息非常具体。本篇实测了两类典型错误:

错误一:顶层出现未知键。config.yaml 顶层写了一个不存在的键 nonexistent_key_check: true——顶层键会被当作组件名去加载,日志直接报模块缺失:

2026-10-30 11:06:23.800 [INFO    ] [viseron.components] - Setting up component nonexistent_key_check
2026-10-30 11:06:23.806 [ERROR   ] [viseron.components] - Failed to load component nonexistent_key_check: No module named 'viseron.components.nonexistent_key_check'

错误二:参数类型/取值非法。把 mog2 的 fps 写成字符串 notanumber,校验器精确报出出错路径与值:

2026-10-30 11:06:23.806 [ERROR   ] [viseron.components] - Error validating config for component mog2: expected float for dictionary value @ data['mog2']['motion_detector']['cameras']['fake_camera']['fps']. Got 'notanumber'
2026-10-30 11:06:23.814 [ERROR   ] [viseron.components] - Setup of component mog2 failed
2026-10-30 11:06:28.269 [INFO    ] [viseron.components.nvr.nvr.fake_camera] - Motion detector is disabled

两条实测结论:

  • 校验失败只禁用该组件,不影响其余组件启动(上例 ffmpeg/darknet/nvr 正常装载,只是运动检测被禁用);
  • 错误信息给出完整的 YAML 路径与非法值,照着改即可,无需查文档。

⚠️ 注意:nvr 域启动时会打印 Motion detector is disabled 或 Object detector is disabled 提示哪些检测器没起来。生产上重启后务必扫一眼这两行,避免「以为在检测,实际早就被禁用」。

四、参数总览

按配置域汇总本篇覆盖的参数(默认值取自 3.7.0 内置校验 schema,行为均经实测验证):

配置域关键参数默认值作用一句话
ffmpeg.camerahost / port / path无(必填)RTSP 地址三要素
ffmpeg.camerastream_formatrtsp信令格式(rtsp/mjpeg)
ffmpeg.camerafps无(取流帧率)送检帧率上限
ffmpeg.camerartsp_transporttcpRTSP 传输方式
ffmpeg.camera.recorderlookback5录像向前回溯秒数
ffmpeg.camera.recorderidle_timeout10事件结束后延录秒数
ffmpeg.camera.recordermax_recording_time300单次录像最长秒数
ffmpeg.camera.recordercontinuous_recordingtrue是否开启持续录像
ffmpeg.camera.recordercreate_event_clipfalse是否生成事件片段 mp4
ffmpeg.camera.still_imagerefresh_interval10静态图刷新秒数
mog2.motion_detector.camerasfps1运动检测帧率
mog2.motion_detector.camerasarea0.08触发运动的最小面积占比
mog2.motion_detector.cameraswidth / height300 / 300背景建模前帧缩放尺寸
mog2.motion_detector.camerasthreshold15像素判运动的帧差阈值(0~255)
mog2.motion_detector.camerashistory500参与背景建模的历史帧数
mog2.motion_detector.camerasdetect_shadowsfalse是否把阴影计入运动
mog2.motion_detector.cameraslearning_rate0.01背景模型学习速率(-1~1)
mog2.motion_detector.camerastrigger_event_recordingfalse运动是否触发录像
mog2.motion_detector.camerasrecorder_keepalivetrue无物体时运动维持录像
mog2.motion_detector.camerasmax_recorder_keepalive30运动维持录像的上限秒数
darknet.object_detectormodel_path / model_config内置默认检测模型权重/结构文件
darknet.object_detector.camerasfps1检测帧率
darknet.object_detector.camerasscan_on_motion_onlytrue仅在运动时检测
darknet.object_detector.camerasmax_frame_age2丢弃过老帧的秒数
darknet.object_detector.cameras.labelsconfidence0.8单标签置信度阈值
darknet.object_detector.cameras.labelstrigger_event_recordingtrue命中是否触发录像
darknet.object_detector.cameras.labelsstoretrue命中是否入库+快照
darknet.object_detector.cameras.labelsstore_interval60入库/快照间隔秒数
darknet.object_detector.cameras.labelsrequire_motion_overlapfalse检测框需与运动轮廓重叠(3.7.0 新增)
darknet.object_detector.cameras.labelsmotion_overlap_threshold0.1重叠占比阈值
storagerecorder.tiers[].events.max_age.days7事件录像默认保留天数
storagesnapshots.tiers[].max_age.days7快照默认保留天数
mqttbroker / port无 / 1883MQTT 代理地址
mqttclient_idviseron客户端 ID,兼作默认主题前缀
mqtthome_assistant.discovery_prefixhomeassistantHA 发现前缀
webserverport8888Web/API 监听端口
webserver.authsession_expiry.days无(必填于 auth)会话有效期
webserver.auth.rate_limitslogin10 次 / 60 秒登录限流
loggerdefault_levelinfo全局日志级别

解读:整张表按「取流 → 运动检测 → 物体检测 → 录像 → 存储保留 → 对外接口」的数据流顺序排列,与下文各节顺序一致;加粗行为对资源占用/磁盘量影响最大的三个参数——fps(检测帧率)、scan_on_motion_only(是否常开检测)、max_age(保留时长),生产环境优先调这三个。

五、核心参数分类详解

5.1 ffmpeg:取流与录制通道

ffmpeg 组件负责从摄像头拉流、解码出帧送给检测器,并在录像时生成视频分段。它内部内置了 FFmpeg 8.1,命令行由 Viseron 自动拼装,绝大多数场景无需手写命令:

ffmpeg:
  camera:
    fake_camera:
      name: Fake Camera              # 摄像头显示名
      host: mediamtx                 # RTSP 主机
      port: 8554                     # RTSP 端口
      path: /cam                     # RTSP 路径
      stream_format: rtsp            # 信令格式:rtsp 或 mjpeg
      fps: 12                        # 送检帧率
      rtsp_transport: tcp            # RTSP 传输方式,默认 tcp
      recorder:
        idle_timeout: 5              # 录像参数,见 5.4

逐项说明:

  • host / port / path:摄像头地址三要素。真实摄像头典型写法如 host: 192.168.1.64、port: 554、path: /Streaming/Channels/101/(海康主码流)。
  • username / password:摄像头认证凭据,未配置表示匿名;同时支持 protocol: https(mjpeg over https)。
  • stream_format:rtsp(默认)或 mjpeg。mjpeg 常见于老式网络摄像头的 HTTP MJPEG 端点。
  • fps:不写则沿用流自身帧率;写了则以该值上限送帧。它是资源消耗的第一杠杆——12fps 的流配 fps: 12 与 fps: 5,CPU 差异立现。
  • rtsp_transport:默认 tcp。UDP 丢包严重时保持 tcp 即可;某些老设备只支持 udp 时改此值。
  • substream:可选子码流配置(独立 path/port/stream_format),检测走子码流、录制走主码流的经典用法。
  • width / height:不写按流分辨率;摄像头流异常时可强制指定。

💡 技术拓展:RTSP 拉流的传输方式不止一种——rtsp_transport 可选 tcp / udp / udp_multicast / http。tcp 可靠但偶发队头阻塞;udp 延迟低但丢包会花屏;multicast 适合一录多播的内网;http 走 RTSP over HTTP 隧道穿透防火墙。本篇实测环境与生产内网直连场景均采用默认 tcp(丢包率为零的内网,可靠性优先)。

实测验证:本轮参数实验把 fps 从 12 调成 2(模拟低配机器送检),重启后域装载成功且事件照常产生——fps 只影响送检节奏,不改变流本身:

2026-10-30 11:32:53.796 [INFO    ] [viseron.domains] - Setup of domain camera with identifier fake_camera for component ffmpeg took 3.5 seconds

5.2 mog2:运动检测

mog2 是运动检测域的实现组件(OpenCV MOG2 背景建模)。按摄像头逐一开启:

mog2:
  motion_detector:
    cameras:
      fake_camera:
        fps: 5                       # 运动检测帧率
        area: 0.05                   # 触发运动的最小面积占比
        trigger_event_recording: true # 运动触发事件录像
        recorder_keepalive: true     # 无物体时运动维持录像
        max_recorder_keepalive: 20   # 运动维持录像上限(秒)

逐项说明:

  • fps:运动检测执行帧率,默认 1。运动检测在缩小到 300x300 的帧上做背景建模(width/height 可改),本身很轻,但对多摄像头场景仍是「摄像头数 × fps」的固定开销。
  • area:画面中变化区域占整帧的最小比例,默认 0.08(8%)。调小更灵敏(易误报),调大更迟钝(漏报远处小目标)。实测把 area 从默认 0.08 调到 0.05、fps 调到 5 后,一小时内产生 101 条 motion 事件(REST API /events/fake_camera 统计),样例视频中行人入画即可触发。
  • trigger_event_recording:默认 false——纯运动不录像,只有物体检测命中才录。设为 true 后运动本身也会触发录像。实测:把三个物体标签的 trigger_event_recording 全部关掉、只留运动触发,录像列表立即出现 trigger_type: motion 的记录:
{"camera_identifier": "fake_camera", "type": "recording", "id": 299, "trigger_type": "motion",
 "start_time": "2026-10-30T03:24:25.145719+00:00", "end_time": "2026-10-30T03:24:38.723120+00:00",
 "duration": 13.577, "hls_url": "/api/v1/hls/fake_camera/299/index.m3u8",
 "thumbnail_path": "/files/thumbnails/fake_camera/299.jpg", "lookback": 3}
  • recorder_keepalive / max_recorder_keepalive:物体消失但画面仍有运动时,默认让录像继续(keepalive),上限 30 秒防「无限录像」(如对着一棵随风摇的树)。设 0 关闭上保。
  • max_motion_duration:运动状态最长保持秒数,默认 0(不限制),是外部运动源(如 PIR 传感器经 MQTT 送 on 后失联)的安全阀。
  • width / height / threshold / history / detect_shadows / learning_rate:MOG2 背景建模的六个细调参数,默认值分别为 300 / 300 / 15 / 500 / false / 0.01。含义逐个说:width、height 是参与建模前把帧缩放到的目标尺寸(固定缩到 300x300 一类的低分辨率再算背景,省掉大半算力);threshold 是当前帧与背景模型逐像素比较的差值门槛(取值 0~255,越小越灵敏,风草晃动的场景调大可压制误报);history 是参与背景建模的历史帧数(越大背景越稳定,但适应缓慢光照变化越慢);detect_shadows 开启后阴影也判为运动(更准但更耗资源,默认关闭);learning_rate 控制背景模型学习速率(0 表示模型完全不更新、1 表示完全用上一帧重建,负值由算法自动选择)。日常场景默认即可,灵敏度优先只动 threshold 与 area 两个旋钮。
  • mask:排除区域列表(多边形坐标),把不影响判断却常刮风下雨的天空、树梢划出检测范围,coordinates 至少 3 个点围成多边形(官方文档建议用 image-map.net 之类的多边形工具画完直接取坐标):
mog2:
  motion_detector:
    cameras:
      fake_camera:
        mask:
          - coordinates:
              - x: 400
                y: 200
              - x: 1000
                y: 200
              - x: 1000
                y: 750
              - x: 400
                y: 750

💡 技术拓展:运动检测算法不止 MOG2 一家。常见同类对比——

算法/实现原理特点
MOG2(本篇采用)高斯混合背景建模OpenCV 内置,自适应多模态背景,Viseron 的 mog2 组件
KNN 背景建模K 近邻背景建模对缓慢光照变化更稳,计算量略高
帧差法相邻帧差分最轻量,空洞明显,适合粗筛
外部传感器PIR/门磁经 MQTT 送信号零算力,Viseron 可把 MQTT 运动源接入同一 motion_detector 域

Viseron 的域抽象允许混用:一台摄像头用 mog2,另一台接 MQTT 外部运动源,NVR 层不感知差异。

5.3 darknet:物体检测与 labels 过滤

darknet 是物体检测域的实现组件,加载 YOLO 系权重做推理。模型路径 + 按摄像头的检测参数与标签过滤是其全部内容:

darknet:
  object_detector:
    model_path: /detectors/models/darknet/yolov7-tiny.weights   # 权重
    model_config: /detectors/models/darknet/yolov7-tiny.cfg     # 网络结构
    cameras:
      fake_camera:
        fps: 2                        # 检测帧率
        scan_on_motion_only: false    # 是否仅运动时检测
        max_frame_age: 5              # 帧最大年龄(秒)
        labels:
          - label: person
            confidence: 0.5
            trigger_event_recording: true
            store_interval: 30

逐项说明:

  • model_path / model_config / label_path:模型三件套。官方环境内置 YOLO 模型于 /detectors/models/darknet/,换自定义模型时把权重文件放进来并改这两个路径即可。
  • fps:检测执行帧率,默认 1。这是最贵的参数——YOLOv7-tiny 在纯 CPU 上单帧推理约 0.7 秒(本环境实测 /tune 接口报 inference_fps 1.4,即每秒 1.4 帧),fps 设 5 意味着推理队列积压、CPU 打满。多摄像头场景宁可降 fps。
  • scan_on_motion_only:默认 true——只在运动检测到目标时才跑物体检测,CPU 占用大幅下降;关闭则持续检测。实测开启时日志呈清晰的「运动来 → 检测器起,事件结束 → 检测器停」交替:
2026-10-30 11:22:37.525 [DEBUG   ] [viseron.components.nvr.nvr.fake_camera] - Starting object detector
2026-10-30 11:22:50.567 [DEBUG   ] [viseron.components.nvr.nvr.fake_camera] - Not recording, pausing object detector
2026-10-30 11:23:31.366 [DEBUG   ] [viseron.components.nvr.nvr.fake_camera] - Starting object detector
2026-10-30 11:23:45.331 [DEBUG   ] [viseron.components.nvr.nvr.fake_camera] - Not recording, pausing object detector
  • max_frame_age:待检帧的最大年龄(秒),默认 2。推理慢于取流时老帧直接丢弃,防止「检测结果是几秒前的画面」。
  • labels[]:跟踪标签列表(不写则跟踪全部标签)。
    • confidence:单标签置信度阈值,默认 0.8。实测把 person/bicycle/car 全部降到 0.5 后,事件流里出现 0.526~0.6 区间的低置信事件(0.7 阈值下这些会被过滤);同帧同标签多余检测由 suppression(默认 0.5)做非极大值抑制。
    • trigger_event_recording:命中即触发事件录像,默认 true;配合 5.2 的运动触发形成双通道。
    • store / store_interval:是否入库并保存快照(默认 true,总是存),入库间隔默认 60 秒;实测设为 30 后同一目标每 30 秒落一条 object 事件。
    • height_min/height_max/width_min/width_max:按目标框相对宽高过滤(如 height_max: 0.5 过滤掉近景占屏一半以上的误检)。
    • require_motion_overlap / motion_overlap_threshold:3.7.0 新增——要求检测框与运动轮廓重叠(占比默认 0.1)才算有效目标,专治「画面里有车停着不动,检测器一直触发」的 stationary object 问题;旧参数 require_motion(物体消失即停录)仍保留,两者语义不同。

5.4 recorder:录像行为参数

录像参数挂在 ffmpeg.camera.<名称>.recorder 下(由 camera 域的 RECORDER_SCHEMA 定义),控制「事件前后录多少、录多长、产物是什么」:

      recorder:
        lookback: 5                  # 事件发生前回溯录像秒数
        idle_timeout: 10             # 事件结束后延录秒数
        max_recording_time: 300      # 单次录像硬上限(秒)
        continuous_recording: true   # 持续录像开关
        create_event_clip: false     # 事件片段 mp4 开关
        thumbnail:
          save_to_disk: true         # 录像缩略图落盘

逐项说明(均实测验证):

  • lookback(默认 5):触发录像时把事件前 5 秒已缓存的分段并入录像文件。实测改为 3 后,事件 API 返回的录像对象中 "lookback": 3 生效。
  • idle_timeout(默认 10):事件结束后画面安静多少秒才停录,日志以秒级倒计时可视化。实测从 5 调到 10,倒计时上限同步变成 10s:
2026-10-30 11:18:22.311 [DEBUG   ] [viseron.components.ffmpeg.recorder.fake_camera] - Saving thumbnail in /thumbnails/fake_camera
2026-10-30 11:18:23.268 [INFO    ] [viseron.components.nvr.nvr.fake_camera] - Stopping recording in: 10s
2026-10-30 11:18:24.270 [INFO    ] [viseron.components.nvr.nvr.fake_camera] - Stopping recording in: 9s
...(节选:8s~1s 各行逐秒递减)
2026-10-30 11:18:33.199 [INFO    ] [viseron.components.nvr.nvr.fake_camera] - Stopping recording in: 0s
  • max_recording_time(默认 300):单次录像最长 5 分钟,防止目标一直不离开画面导致无限录像;与 5.2 的 max_recorder_keepalive、5.3 的 require_motion_overlap 构成三重保险。
  • continuous_recording(默认 true):开启后即使没有事件也持续写分段,事件录像由这些分段拼装而成(这是 lookback 能回溯的前提);磁盘紧张时置 false 只保留事件录像。
  • create_event_clip(默认 false):开启后每次事件额外产出 /event_clips/<camera>/<id>.mp4 单文件片段,便于直接转发(不开则只存分段,靠 HLS 回放)。
  • filename_pattern(默认 %H:%M:%S):持续录像分段的文件名时间格式。
  • schedule:3.7.0 新增的按 cron 表达式的录像计划——schedule.events: [{start: "0 9 * * *", end: "30 18 * * *"}] 表示仅工作时段内的事件录像;schedule.continuous 同理控制持续录像时段;schedule.timezone 指定计划时区。

5.5 storage:存储分层与保留策略

storage 组件管理所有落盘数据的保留。默认配置等价于「事件录像与快照各保留 7 天」,分层(tier)模型支持把老数据挪到慢盘:

storage:
  tier_check_cpu_limit: 10          # tier 检查任务的 CPU 限额(%)
  tier_check_workers: 4             # 检查并行度
  tier_check_batch_size: 5          # 每批处理文件数
  tier_check_sleep_between_batches: 0.5
  recorder:
    tiers:
      - path: /                     # 录像数据根
        check_interval:
          minutes: 30               # 每层检查频率
        events:                     # 事件录像的保留策略
          max_age:
            days: 7                 # 保留 7 天
          max_size:
            gb: 50                  # 或容量上限 50GB(先到先删)
        continuous:                 # 持续录像的保留策略(结构同上)
          max_age:
            days: 2
  snapshots:
    tiers:
      - path: /
        max_age:
          days: 7                   # 快照保留 7 天

逐项说明:

  • tiers[]:分层列表,每层一个 path(如 / 与 /mnt/archive/ 两层:第一层写满或到期后向下一层转移,poll: true/move_on_shutdown: true 控制转移时机,drain: true 清空本层)。对单盘场景一层即可。
  • events / continuous / max_age / max_size:事件录像与持续录像分别设保留策略,max_age(days/hours/minutes)与 max_size(gb/mb)先到者触发清理;min_age/min_size 则保护「太新/太小」的文件不被误删。
  • check_interval(默认全 0,即交给内置调度节奏):每层清理检查的间隔,密集写入时可加密。
  • 实测佐证:默认保留策略下,录像分段按时间戳落在 /segments/<camera>/<unix_ts>.m4s(实测目录列表):
/segments/fake_camera/1793326549.m4s
/segments/fake_camera/1793327834.m4s
/segments/fake_camera/1793328504.m4s
/segments/fake_camera/1793329348.m4s

缩略图与快照同样按域分目录:/thumbnails/<camera>/<录像id>.jpg 与 latest_thumbnail.jpg、/snapshots/<检测组件>/<camera>/<时间戳>-<uuid>.jpg 与 latest_snapshot.jpg,与 storage 的 subcategory 设计一致。

⚠️ 注意:max_size 按 tier 内文件总量计算而非单文件;删除动作在 DEBUG 日志中为 Deleting file <path>,排查「录像怎么没了」时把 viseron.components.storage 日志级别临时调到 debug 即可看到判定过程。

5.6 mqtt:MQTT 事件输出

mqtt 组件把 Viseron 的实体状态实时发布到 MQTT 代理,是接入 Home Assistant 或自建告警管道的标准通道。本环境实测时部署了 Eclipse Mosquitto 2.1.2 作为代理,配置:

mqtt:
  broker: mqtt                      # 代理地址(本实验内网服务名)
  port: 1883                        # 默认 1883
  client_id: viseron                # 客户端 ID,兼作默认主题前缀
  # username / password:代理需要认证时填写
  # base_topic:不写则用 client_id 作为主题前缀

重启后组件装载成功,并立即在代理上出现 retained 的存活状态与实体主题:

2026-10-30 11:26:23.508 [INFO    ] [viseron.components] - Setting up component mqtt
2026-10-30 11:26:23.588 [INFO    ] [viseron.components] - Setup of component mqtt took 0.0 seconds

用 mosquitto_sub -t 'viseron/#' -v 抓取 150 秒,实测主题分布如下(节选):

主题载荷(实测节选)说明
viseron/lwtalive遗嘱主题:进程异常退出时代理代发离线
viseron/stateonline在线状态
viseron/binary_sensor/fake_camera_motion_detected/state{"state": "on", ...}运动检测二值状态
viseron/binary_sensor/fake_camera_recorder/state{"state": "on", "attributes": {... "id": 302, "trigger_type": "motion"}}录像状态,含完整录像属性
viseron/binary_sensor/fake_camera_object_detected_car/state{"state": "on", "attributes": {"count": 1, "objects": [{"label": "car", "confidence": 0.733, "rel_x1": 0.0, ...}]}}分标签检测状态,含目标框坐标
viseron/sensor/fake_camera_operation_state/state{"state": "recording"}运行状态机(scanning_for_motion/recording/scanning_for_objects)
viseron/sensor/fake_camera_object_detector_fps/state{"state": 1.4, "attributes": {"inference_fps": 1.4, "theoretical_max_fps": 1.4}}推理帧率传感器
viseron/image/fake_camera_latest_thumbnail/image(二进制 JPEG)最新缩略图原图
viseron/image/fake_camera_latest_thumbnail/attributes{"attributes": {...}}缩略图元数据
viseron/toggle/fake_camera_manual_recording/state{"state": "off", ...}手动录像开关状态

实测的一条完整状态链(运动出现 → 录像 → 物体命中 → 收尾):

viseron/binary_sensor/fake_camera_motion_detected/state {"state": "on", ...}
viseron/binary_sensor/fake_camera_recorder/state {"state": "on", "attributes": {... "id": 302, ... "trigger_type": "motion"}}
viseron/sensor/fake_camera_operation_state/state {"state": "recording", ...}
viseron/binary_sensor/fake_camera_object_detected_car/state {"state": "on", "attributes": {"count": 1, "objects": [{"label": "car", "confidence": 0.733, ...}]}}
viseron/binary_sensor/fake_camera_object_detected_car/state {"state": "off", "attributes": {... "count": 0, "objects": []}}
viseron/binary_sensor/fake_camera_recorder/state {"state": "off", "attributes": {... "id": 302, "end_time": "2026-10-30T03:28:14.541423+00:00", ...}}
viseron/sensor/fake_camera_operation_state/state {"state": "scanning_for_objects", ...}

(以上为实测消息流节选,主题与 state 字段为原文,较长 attributes 以 ... 截短,完整属性见上文主题表。)

MQTT 不只下行发布,还能反向控制。开关实体的命令主题是 <base_topic>/toggle/<camera>_manual_recording/command,实测发布 JSON 载荷触发了一次 5 秒手动录像,录像系统随即出现 trigger_type: manual 的记录(id 306):

mosquitto_pub -t "viseron/toggle/fake_camera_manual_recording/command" \
  -m '{"action":"start","duration":5}'
  • home_assistant:子配置 home_assistant: {enabled: true}(组件内默认开启发现前缀 homeassistant、retain_config 默认 true)会把每个实体发布为 HA MQTT Discovery 配置,HA 侧零配置自动发现全部传感器、二值传感器与开关。
  • publish_states_on_reconnect(默认 true):代理闪断重连后自动重发全部状态,订阅方无需等下一次变化。

5.7 nvr:摄像头协调器

nvr 组件的配置极度简单——按摄像头标识逐个开空段即可,它是「让检测器/录像器/实体开始协同」的注册表:

nvr:
  fake_camera:                      # 与 ffmpeg.camera 下的标识一致
  # second_camera:                  # 多摄像头时逐个列出

实测说明:nvr.<camera> 段内部当前没有参数(3.7.0 的 schema 为空 dict,保留扩展位),它的作用是声明「该摄像头启用 NVR 域」。缺了它,该摄像头能显示画面但不会产生运动/物体/录像实体;配置后日志出现初始化完成行:

2026-10-30 11:32:54.109 [INFO    ] [viseron.components.nvr.nvr.fake_camera] - NVR for camera Fake Camera initialized

5.8 webserver:Web/API、认证与限流

webserver 组件承载 Web UI 与全部 REST API:

webserver:
  port: 8888                        # Web/API 监听端口,默认 8888
  debug: false                      # 调试模式
  auth:
    session_expiry:
      days: 7                       # 浏览器会话有效期
    rate_limits:
      login:                        # 登录接口限流(默认值如下)
        max_attempts: 10
        window_seconds: 60
      token:
        max_attempts: 30
        window_seconds: 60
      onboarding:
        max_attempts: 5
        window_seconds: 60

逐项说明(限流为实测验证):

  • port:默认 8888,与部署篇的宿主端口映射 8151:8888 对应。
  • auth.session_expiry:浏览器会话有效期,days/hours/minutes 三档可组合;本环境设 7 天。
  • auth.rate_limits:按接口的滑动窗口限流。实测对登录接口连续输错密码,第 1~10 次返回 401 {"status": 401, "error": "Invalid username or password"},第 11 次起被限流:
attempt 1 => {"status": 401, "error": "Invalid username or password"}|401
attempt 2 => {"status": 401, "error": "Invalid username or password"}|401
...(3~10 次同为 401,略)
attempt 11 => {"status": 429, "error": "Too many requests, please try again later"}|429
attempt 12 => {"status": 429, "error": "Too many requests, please try again later"}|429
  • public_base_url / public_url_expiry_hours / public_url_max_downloads:生成对外分享链接时的基础地址与链接有效期/下载次数(默认 24 小时、不限次数)。

5.9 logger:日志级别

logger 组件控制全局与细粒度日志:

logger:
  default_level: info               # 全局级别
  logs:
    viseron.components.ffmpeg.recorder: debug   # 指定 logger 名调到 debug
    viseron.components.nvr: debug

逐项说明:

  • default_level:全局级别,默认 info。
  • logs:按 logger 名(即 Python 模块路径)单独调级,排障利器。实测给 viseron.components.nvr 开 debug 后,日志出现逐帧年龄判定与检测器暂停明细:
2026-10-30 11:24:33.311 [DEBUG   ] [viseron.components.nvr.nvr.fake_camera] - Frame is 1.1518199443817139 seconds old. Discarding
2026-10-30 11:24:38.833 [DEBUG   ] [viseron.components.nvr.nvr.fake_camera] - Not recording, pausing object detector

给 viseron.components.ffmpeg.recorder 开 debug 后能看到缩略图保存动作(见 5.4 实测回显)。日志同时可通过 REST API GET /api/v1/logger/logs?lines=12 拉取(Web UI 内置日志查看器即用此接口,3.7.0 新特性)。

六、生产配置模板

一套面向「4 路摄像头、8GB 内存、NVMe 单盘、7 天事件保留」的生产基线(本篇参数均在同环境实测过单项行为,模板组合为推荐值):

ffmpeg:
  camera:
    front_door:
      name: Front Door
      host: 192.168.1.64
      port: 554
      path: /Streaming/Channels/102/       # 用子码流送检,降低解码压力
      stream_format: rtsp
      fps: 5
      rtsp_transport: tcp
      recorder:
        lookback: 5
        idle_timeout: 10
        max_recording_time: 300
        create_event_clip: true

mog2:
  motion_detector:
    cameras:
      front_door:
        fps: 3
        area: 0.08
        trigger_event_recording: true
        max_recorder_keepalive: 30

darknet:
  object_detector:
    model_path: /detectors/models/darknet/yolov7-tiny.weights
    model_config: /detectors/models/darknet/yolov7-tiny.cfg
    cameras:
      front_door:
        fps: 1                      # CPU 推理场景 1fps 起步,有 GPU/TPU 再加
        scan_on_motion_only: true   # 纯 CPU 生产必须开
        labels:
          - label: person
            confidence: 0.7
            trigger_event_recording: true
            require_motion_overlap: true
          - label: car
            confidence: 0.7
            trigger_event_recording: true
            require_motion_overlap: true

mqtt:
  broker: 192.168.1.10              # 内网 MQTT 代理
  port: 1883
  client_id: viseron

nvr:
  front_door:

webserver:
  port: 8888
  auth:
    session_expiry:
      days: 7
    rate_limits:
      login:
        max_attempts: 10
        window_seconds: 60

logger:
  default_level: info

storage:
  recorder:
    tiers:
      - path: /
        check_interval:
          hours: 1
        events:
          max_age:
            days: 7
          max_size:
            gb: 200
        continuous:
          max_age:
            days: 2
  snapshots:
    tiers:
      - path: /
        max_age:
          days: 7

适用边界与理由:

  • 资源档位:8GB 内存 / 4 核 CPU / NVMe。scan_on_motion_only: true 是纯 CPU 部署的省算力关键(实测检测器随录像启停,空闲期零推理开销);检测帧率 1fps 时单路推理开销约一核的 60~70%(实测 /tune 报 inference_fps 1.4,即单路占满约 0.7 核)。
  • 磁盘估算:单路 5fps 子码流 + 持续录像约 1~2GB/天,continuous.max_age: days: 2 + events.max_age: days: 7 + max_size: gb: 200 三层兜底,NVMe 盘 500GB 余量充足。
  • 场景假设:门口/车道类场景,person/car 是核心关注目标;require_motion_overlap: true(3.7.0 新增)过滤静止物体的重复触发。
  • 多路扩展:每加一路摄像头复制 front_door 段并改标识(标识只能用小写字母/数字/下划线),CPU 按每路约 1 核预留;有 Coral TPU 时把 darknet 换成 edgetpu 组件并将 fps 提到 5。

七、常见问题

Q1:改了 config.yaml 不生效? 配置只在启动时读取。docker compose restart viseron(部署篇环境)或 Web UI Configuration 页保存即触发重启;重启后用 GET /api/v1/config(3.2 节)核对生效值,别只看文件。

Q2:启动报 Failed to load component xxx: No module named 'viseron.components.xxx'? 顶层键名写错了——顶层每个键必须是真实组件名(如 mog2、darknet),拼错的键会被当作组件去加载(3.4 节错误一实测原样报错)。

Q3:启动报 Error validating config for component xxx: expected float ... Got 'notanumber'? 参数类型错误,报错里的 data['组件']['域']['cameras']['标识']['参数'] 就是精确路径,改成正确类型(fps 要数字)即可(3.4 节错误二实测)。校验失败只禁用该组件,其余功能不受影响,但重启后要确认对应域没有 disabled。

Q4:检测明明配置了,日志却显示 Motion detector is disabled? 该组件校验失败被禁用了(常见于 Q3 的类型错误),去启动日志找 Setup of component xxx failed 定位。

Q5:CPU 占用过高? 三个杠杆按顺序调:darknet ... scan_on_motion_only 设 true(实测空闲期检测器完全暂停)、检测 fps 降到 1、运动检测 fps 降到 1~2。再不够就换子码流(substream)送检或上硬件加速组件。

Q6:录像一直不停或文件巨大? 三重保险按需收紧:recorder.max_recording_time(硬上限)、mog2 ... max_recorder_keepalive(运动维持上限)、labels 上 require_motion_overlap: true(静止物体不再触发)。磁盘总量兜底交给 storage 的 max_size。

Q7:MQTT 主题里 image 主题全是乱码? viseron/image/.../image 主题载荷就是原始 JPEG 二进制,文本终端显示乱码是正常现象;订阅时避开 image 主题(如 viseron/# -v 改为 viseron/binary_sensor/#、viseron/sensor/#)即可。

Q8:登录一直 429? webserver 登录限流默认 10 次/60 秒(实测第 11 次起 429),等窗口过去或从其他正常途径(Web UI)登录;生产上不建议放宽,它是暴力破解的第一道闸。

八、参考链接