# 录像与存储

云瞰 默认本地分段录像，可选挂 115 网盘做云备份。本章讲解录像机制、保留策略、和 115 接入。

## 录像怎么写

云瞰 把每路相机的视频按时间切成一段段标准 MP4 文件，**每段固定 60 秒**。MediaMTX 先写出 fMP4 分段，每段写完瞬间被 `runOnRecordSegmentComplete` hook 调起，由 ffmpeg 原地 `-c copy` remux 成带 `faststart` 的标准 MP4（moov 在头部），各家播放器都能直接 seek。落盘路径：

```text
data/recordings/
  <camera_id>/
    2026-05-18_14-30-00.mp4
    2026-05-18_14-31-00.mp4
    2026-05-18_14-32-00.mp4
    ...
```

> ℹ️ 分段录像让回放可以精确 seek 到任意时间点。如果一段坏了（断电、网络抖动），最多丢 60 秒，相邻段不受影响。文件名里的时间戳就是该段的起始时刻（本地时区）。

> **ℹ️ 归档后的路径**
>
> **本地存储**模式下，每段录像被入库并打上 `archived` 状态后，会被原子 `rename` 到 `data/recordings/_archive/<camera_id>/` 下，目录结构和文件名完全镜像，方便和正在写入的 inbox 区分开。`_archive/` 前缀是约定，uploader 的 discovery 扫描会跳过它，避免归档文件被反复处理。**115 网盘**模式下本地是否保留由 `delete_after_upload` 设置决定（默认上传成功即删）。

## 本地存储路径

录像写在 `/app/data/recordings`（嵌套挂载，可单独指到大盘 / NAS），数据库 / cookies / 日志等小状态在 `/app/data`，AI 模型已内置在镜像里、不落数据目录。生产部署务必把录像目录指到容量充足的大盘，不要跟系统盘挤在同一个分区——录像满了会让你的服务器开不了机。

```bash
# 推荐：录像单独挂一块大盘 / NAS（小状态留在 data/）
sudo mkdir -p /mnt/recordings
# 一键脚本：--recordings-dir 指到大盘
curl -fsSL https://cdn.yun-kan.com/yunkan-install.sh | bash -s -- --recordings-dir /mnt/recordings
# 或手动 docker run 时嵌套挂录像卷
docker run -v $(pwd)/data:/app/data -v /mnt/recordings:/app/data/recordings ...
```

## 保留策略与磁盘空间

网页后台 → 设置 → 录像保留 启用并配置自动清理（默认关闭，需手动开启）。开启后下面两条规则**同时生效**，任一命中即删，**只清理已归档（已上传成功或本地模式）的录像**，pending / uploading / failed 状态绝不动：

- **按天数**：超过保留天数（默认 30 天）的录像 → 删；填 0 = 不按时间触发
- **按容量**：磁盘使用率超过阈值（默认 90%）→ 从最旧录像开始删；填 100 = 不按空间触发

> **ℹ️ 默认关闭**
>
> 首次安装 `[cleanup]` 服务默认 enabled=false——不开就一直留着，磁盘满了写入会失败但 云瞰 不主动删。家用部署强烈建议开起来，按上面两条规则把后顾之忧交给系统。

| 分辨率 | 码率 | 1 路 24 小时大致占用 |
| --- | --- | --- |
| 1080p H.264 | 2 Mbps | 约 21 GB / 天 |
| 1080p H.265 | 1 Mbps | 约 10 GB / 天 |
| 4K H.265 | 4 Mbps | 约 42 GB / 天 |

> **💡 估容量公式**
>
> **总磁盘 ≈ 路数 × 单路日占用 × 保留天数 × 1.2（缩略图 + 数据库余量）**。10 路 1080p H.265 保 30 天 ≈ 3.6 TB。

## 115 网盘云存储（可选）

把本地录像异步上传到 115 网盘，相当于 "云端 NVR"。秒传支持下，已有的录像不耗带宽。

1. **扫码登录**

   网页后台 → 115 → 显示二维码，用 115 手机 App 扫码授权。云瞰 把登录信息加密保存到 data 目录里。

2. **选目标文件夹**

   在 115 里建一个空文件夹（例如 "云瞰录像"），返回 云瞰 选这个文件夹作为上传目的地

3. **切存储后端**

   设置 → 存储 → 选 115 → 保存。切换是热切换，**不重启进程**，下一次上传就生效

4. **验证生效**

   Web Admin 目前**没有上传队列 / 进度面板**。要确认录像在传，三种办法任选：① **设置 → 115** 页面看 VIP 状态、剩余容量是否正常；② **日志**页（侧栏 → 日志）左侧选 `uploader` 服务，能实时看到每段上传的开始 / 完成 / 失败行；③ 直接打开 115 App 或网页进目标文件夹，看新录像有没有进来。

> **⚠️ 115 登录会过期**
>
> 约 30 天左右需要重新扫码。失效时 云瞰 会发推送通知，及时重扫即可，期间录像继续往本地写不丢。

> **ℹ️ 不是 115 用户怎么办**
>
> 目前只支持本地 + 115 两种后端。后续会接阿里云盘 / S3 等，有特定云盘需求可以发工单告知优先级。

## 下载 / 导出

回放页支持「按时间区间导出」——选定起止时间，后端重编码裁剪成单 MP4 给客户端下载，起止时间**帧级精度** (<40ms 误差)。**自动选硬件**:NVIDIA NVENC(50-200x 实时,RTX 几十秒/小时)→ Intel iGPU VAAPI(25-50x,N100 一两分钟/小时)→ libx264 软编(1.5-3x,十几分钟/小时)。任何一级失败自动降级到下一级。**Web Admin、Android、iOS 三端都支持**。

1. **进回放页**

   选要导出的摄像头和日期。把时间轴拖到目标区间附近，让中心刻度落在那一段录像上。

2. **点导出按钮**

   Web Admin：播放控制条最右边的 ⬇ 图标；Android / iOS：播放控制条「速度」按钮右侧的「导出」。弹出区间选择面板，默认是当前播放位置 ±30 秒。

3. **调整起止时间 → 提交**

   面板里改起止时间，会实时算出预计大小（1080p H.264 约 250 KB/s）。单次最长 **1 小时**，超过会拒绝。点「开始导出」。

4. **看进度**

   右下角（Web）/ 控制条下方（Android/iOS）会出现进度卡片。Web 走 SSE 实时刷新，移动端走 2 秒轮询。任务一旦排上号通常几秒到几十秒完成（取决于段数 + 是否需要从 115 拉云端段）。

5. **下载**

   进度卡片变成「下载」按钮后点它：Web 直接走浏览器下载；Android 走系统 DownloadManager 保存到 `Downloads/SkyView/`，状态栏有通知；iOS 弹 ShareSheet 让你选「存到 Files / Photos」或分享给微信。

> **ℹ️ 自动选硬件加速 NVENC > VAAPI > libx264**
>
> 进程启动时自动探测,按速度从快到慢优先级排:
>
> - **NVENC**(NVIDIA 独显):需要 cuda 镜像变体 + `--gpus all`,RTX 30/40 系 1h 视频 ~30-60 秒
> - **VAAPI**(Intel/AMD 集显):需要 openvino/all-in-one 镜像 + 透传 `/dev/dri`,N100 等 1h 视频 ~1-2 分钟
> - **libx264**(纯 CPU):无 GPU 时兜底,1h 视频 ~20-40 分钟(取决于 CPU)
>
> 任何一级运行时失败(driver 不兼容、session 上限等)自动降级到下一级。手动强制走某一种走 `recording.export.hwaccel = "nvenc" / "vaapi" / "none"`。

> **ℹ️ 起止时间是帧级精度**
>
> 三条编码路径(NVENC / VAAPI / libx264)起止时间都精确到帧 (<40ms)。质量参数对齐:NVENC `qp=23` / VAAPI `qp=23` / libx264 `crf=23` —— 跨硬件输出视觉上基本一致(NVENC 文件可能略大 <10%)。配置 `recording.export.{nvenc,vaapi}_qp` 可单独调质量(0-51,越小质量越高)。

> **ℹ️ 115 网盘存储模式也支持**
>
> 如果录像在 115 上，后端会先把区间内每段从 115 流式拉到服务器临时目录再拼接，完成后清临时文件。受 115 限速影响，1 小时云端段可能要等几分钟，可以先去做别的事，导出任务在服务端独立跑，关 App 也不影响。

> **💡 导出文件保留 24 小时**
>
> 拼好的 MP4 落在服务器 `data/recordings/_exports/<job_id>.mp4`，默认 24 小时后被 cleanup 自动删（避免吃满磁盘）。这窗口内任意时刻 / 任意端可以重复点「下载」拿同一份文件。超时再要就重新发起。

> **ℹ️ 想绕过 UI 直接拿原始段**
>
> 原始 60 秒段在 `data/recordings/<camera_id>/<YYYY-MM-DD_HH-MM-SS>.mp4`（本地归档后在 `data/recordings/_archive/<camera_id>/` 下），每段都是标准 MP4。也可以 `GET /api/recordings/<id>/download` 带 JWT 拿单段。

---

来源:https://yun-kan.com/ja/docs/recording
