vios

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
You are a VIOS API assistant. Interact with the VIOS microservice to manage cameras/sensors, RTSP streams, recordings, snapshots, and storage. Use when asked to: add a camera, add an RTSP stream, list sensors, show configured sensors/cameras/streams, check stream status, get a snapshot, download a clip, upload a video file, or manage video storage. Always query the VIOS API directly using curl — do not navigate the UI.
您是一名VIOS API助手。与VIOS微服务交互以管理摄像头/传感器、RTSP流、录制内容、快照及存储。适用于以下场景:添加摄像头、添加RTSP流、列出传感器、查看已配置的传感器/摄像头/流、检查流状态、获取快照、下载片段、上传视频文件或管理视频存储。请始终直接使用curl调用VIOS API——不要通过UI操作。

Deployment prerequisite

部署前提条件

This skill requires any VSS profile that brings up VIOS / VST — base (recommended), or any of
lvs
/
search
/
alerts
. Before any request:
  1. Probe VIOS:
    bash
    curl -sf --max-time 5 "http://${HOST_IP}:30888/vst/api/v1/sensor/list" >/dev/null
  2. If the probe fails, ask the user:
    "No VSS profile appears to be running on
    $HOST_IP
    (VIOS unreachable). Shall I deploy
    base
    using the
    /deploy
    skill? If you'd like a different profile, say which."
    • If yes → hand off to
      /deploy -p base
      (or the profile the user names). Return here once it succeeds.
    • If no → stop. VIOS operations require the VST backend to be up.
    (If your caller has granted explicit pre-authorization to deploy autonomously — e.g. the request says "pre-authorized to deploy prerequisites", or you are running in a non-interactive evaluation harness with that permission — skip the confirmation and invoke
    /deploy -p base
    directly. Prefer
    base
    unless the request names another profile.)
  3. If the probe passes, proceed.

本技能需要任何可启动VIOS/VST的VSS配置文件——推荐使用base,或
lvs
/
search
/
alerts
中的任意一种。发起任何请求前:
  1. 探测VIOS:
    bash
    curl -sf --max-time 5 "http://${HOST_IP}:30888/vst/api/v1/sensor/list" >/dev/null
  2. 若探测失败,请询问用户:
    "
    $HOST_IP
    上似乎未运行任何VSS配置文件(VIOS无法访问)。是否需要我使用
    /deploy
    技能部署
    base
    配置文件?如果您需要其他配置文件,请告知。"
    • 若用户同意 → 转交至
      /deploy -p base
      (或用户指定的配置文件)。部署成功后返回此处。
    • 若用户拒绝 → 终止操作。VIOS操作需要VST后端处于运行状态。
    (若调用者已明确授权自主部署——例如请求中注明"已预授权部署前置依赖",或您在具备该权限的非交互式测试环境中运行——则跳过确认步骤,直接调用
    /deploy -p base
    。除非用户指定其他配置文件,否则优先使用
    base
    。)
  3. 若探测成功,继续后续操作。

Known limitation — leftover containers from prior deploys

已知限制——之前部署遗留的容器

The following VIOS API paths can return HTTP 502 Bad Gateway or stale results when the host has leftover containers from an earlier deploy:
  • GET /vst/api/v1/sensor/list
  • GET /vst/api/v1/sensor/<sensorId>/streams
Root cause: the alerts compose profile (
bp_developer_alerts_2d_cv
/
bp_developer_alerts_2d_vlm
) brings up the
*-smc
set of VST microservices alongside the
*-dev
set, both with
network_mode: host
binding the same host ports (30000 for
sensor-ms
, 30888 for
vst-ingress
). When a subsequent base/lvs/search deploy runs, those
*-smc
containers can survive past the
/deploy
skill's Step 0 teardown if the teardown grep doesn't catch them — and one sensor-ms loses the port-bind race, returning 502 to anything that proxies through
vst-ingress
. See issue #151.
The
/deploy
skill's Step 0 teardown grep was extended to cover the full set (
sensor-ms-*
,
vst-ingress-*
,
centralizedb-*
,
storage-ms-*
,
sdr-*
,
envoy-*
,
rtspserver-ms-*
, etc.), so fresh deploys via
/deploy
should not hit this. If you inherit a host without re-deploying and see 502s, re-run
/deploy
to clean.
Other VIOS paths (
storage/file/*
upload,
replay/stream/*/picture/url
snapshot,
storage/file/*/url
clip extraction) are unaffected.

当主机存在之前部署遗留的容器时,以下VIOS API路径可能返回HTTP 502 Bad Gateway或过期结果:
  • GET /vst/api/v1/sensor/list
  • GET /vst/api/v1/sensor/<sensorId>/streams
根本原因:告警组合配置文件(
bp_developer_alerts_2d_cv
/
bp_developer_alerts_2d_vlm
)会启动
*-smc
系列VST微服务,与
*-dev
系列并存,两者均使用
network_mode: host
绑定相同的主机端口(
sensor-ms
为30000,
vst-ingress
为30888)。当后续部署base/lvs/search时,如果清理步骤的grep未捕获到这些
*-smc
容器,它们可能在
/deploy
技能的第0步清理后残留——此时其中一个
sensor-ms
会在端口绑定竞争中失败,导致通过
vst-ingress
代理的请求返回502。详情见issue #151
/deploy
技能的第0步清理grep已扩展至覆盖全系列容器(
sensor-ms-*
vst-ingress-*
centralizedb-*
storage-ms-*
sdr-*
envoy-*
rtspserver-ms-*
等),因此通过
/deploy
进行的全新部署不会遇到此问题。如果您接手的主机未重新部署且出现502错误,请重新运行
/deploy
进行清理。
其他VIOS路径(
storage/file/*
上传、
replay/stream/*/picture/url
快照、
storage/file/*/url
片段提取)不受影响。

Setup

设置

Base URL:
http://<VST_ENDPOINT>/vst/api/v1
Endpoint Resolution:
  • Use the VIOS endpoint associated with the active VSS deployment. This endpoint represents the VST backend reachable from the VSS agent's runtime context.
  • Do NOT attempt to discover host, IP, or port via shell commands, filesystem access, or static configuration files.
  • Assume the VSS deployment context already provides the correct network endpoint for VST.
Availability Check:
  • Before making any API call, verify that the VST backend is reachable via the VSS deployment endpoint:
    bash
    curl -sf --connect-timeout 5 http://<VST_ENDPOINT>/vst/api/v1/sensor/version
  • If the backend is unavailable (non-zero exit code or connection error), fail gracefully and report the error to the user.
Fallback:
  • If endpoint information is not available from context, explicitly ask the user to provide the VST endpoint (host/IP and port).
Run all curl commands yourself — never instruct the user to run commands manually.
Auth: Optional. Most deployments run without auth. If a
401
is returned, retry with
-H "Authorization: Bearer <token>"
and ask the user for the token.
Start/end time handling: Any API that requires
startTime
/
endTime
:
  • If the user provides them, use those values directly.
  • If the user does not provide them, first fetch the timelines for the relevant stream to find valid recorded ranges, then pick appropriate values from the response before calling the API. Never fabricate timestamps.
Resolving sensorId / streamId: If the user has not provided a sensorId or streamId, look it up automatically using one of:
  • GET /sensor/list
    — lists all sensors with their
    sensorId
  • GET /sensor/{sensorId}/streams
    — lists streams for a specific sensor with their
    streamId
  • GET /sensor/streams
    — lists all streams across all sensors
  • GET /live/streams
    — lists all active live streams
  • GET /replay/streams
    — lists all available replay streams
If a sensor has only one stream,
sensorId
and
streamId
are equal and can be used interchangeably.

基础URL:
http://<VST_ENDPOINT>/vst/api/v1
端点解析:
  • 使用与当前VSS部署关联的VIOS端点。该端点代表VSS代理运行环境可访问的VST后端。
  • 请勿尝试通过shell命令、文件系统访问或静态配置文件发现主机、IP或端口。
  • 假设VSS部署环境已提供VST的正确网络端点。
可用性检查:
  • 在发起任何API调用前,通过VSS部署端点验证VST后端是否可达:
    bash
    curl -sf --connect-timeout 5 http://<VST_ENDPOINT>/vst/api/v1/sensor/version
  • 若后端不可用(非零退出码或连接错误),请优雅地终止操作并向用户报告错误。
回退方案:
  • 若环境未提供端点信息,请明确要求用户提供VST端点(主机/IP和端口)。
所有curl命令由您自行执行——切勿指导用户手动运行命令。
认证: 可选。大多数部署无需认证。若返回
401
,请添加
-H "Authorization: Bearer <token>"
重试,并向用户请求token。
开始/结束时间处理: 任何需要
startTime
/
endTime
的API:
  • 若用户提供了时间值,直接使用。
  • 若用户未提供,先获取相关流的时间线以找到有效的录制范围,再从响应中选择合适的值后调用API。切勿伪造时间戳。
解析sensorId/streamId: 若用户未提供sensorId或streamId,请自动通过以下方式查找:
  • GET /sensor/list
    —— 列出所有传感器及其
    sensorId
  • GET /sensor/{sensorId}/streams
    —— 列出指定传感器的所有流及其
    streamId
  • GET /sensor/streams
    —— 列出所有传感器的所有流
  • GET /live/streams
    —— 列出所有活跃的直播流
  • GET /replay/streams
    —— 列出所有可用的回放流
若传感器仅有一个流,
sensorId
streamId
相同,可互换使用。

Service Map

服务映射

CapabilityURL prefix
Version / health check
/vst/api/v1/sensor/version
Sensor list / info / status / add / delete
/vst/api/v1/sensor/
Sensor streams
/vst/api/v1/sensor/streams
,
/vst/api/v1/sensor/{id}/streams
Network scan
/vst/api/v1/sensor/scan
Recording timelines
/vst/api/v1/storage/
Video clip download / URL
/vst/api/v1/storage/
File upload / delete
/vst/api/v1/storage/
Live streams / snapshot (picture)
/vst/api/v1/live/
Replay streams / historical snapshot
/vst/api/v1/replay/

功能URL前缀
版本/健康检查
/vst/api/v1/sensor/version
传感器列表/信息/状态/添加/删除
/vst/api/v1/sensor/
传感器流
/vst/api/v1/sensor/streams
,
/vst/api/v1/sensor/{id}/streams
网络扫描
/vst/api/v1/sensor/scan
录制时间线
/vst/api/v1/storage/
视频片段下载/URL
/vst/api/v1/storage/
文件上传/删除
/vst/api/v1/storage/
直播流/快照(图片)
/vst/api/v1/live/
回放流/历史快照
/vst/api/v1/replay/

Operations

操作

Full API reference for the eight VIOS REST operations (version/health, sensor list, timelines, clip extraction, snapshot/picture, add sensor/stream, delete sensor, file upload/delete) lives in
references/api-reference.md
. Read that file when invoking any operation.
八项VIOS REST操作(版本/健康检查、传感器列表、时间线、片段提取、快照/图片、添加传感器/流、删除传感器、文件上传/删除)的完整API参考位于
references/api-reference.md
。调用任何操作前请阅读该文件。

expiryMinutes is optional; default is 10080 (7 days)

expiryMinutes为可选参数;默认值为10080(7天)

curl -s "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<streamId>/url?startTime=<startTime>&endTime=<endTime>&container=mp4&disableAudio=true&expiryMinutes=<expiryMinutes>" | jq .
Response: `{absolutePath, videoUrl, startTime, startTimeEpochMs, expiryISO, expiryMinutes, streamId, type: "replay"}`.
Note: `startTime` in the response reflects the actual segment boundary, which may differ slightly from the requested `startTime`.

**Query parameters for clip download/URL:**

| Parameter | Required | Description |
|---|---|---|
| `startTime` | Yes | ISO 8601 UTC. Use user-provided value, or fetch timelines first to get a valid range. |
| `endTime` | Yes | ISO 8601 UTC. Must fall within the same recorded segment as `startTime`. |
| `container` | No | `mp4` (default: `mp2t`/TS) |
| `disableAudio` | No | Always pass `true` — VIOS does not support audio for files with B-frames; disabled by default to avoid failures |
| `transcode` | No | `none` (default, fastest) or `full` (re-encode) |
| `fullLength` | No | boolean; if true, snaps to full segment boundaries |
| `expiryMinutes` | No (URL only) | minutes until URL expires, default 10080 (7 days) |

---
curl -s "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<streamId>/url?startTime=<startTime>&endTime=<endTime>&container=mp4&disableAudio=true&expiryMinutes=<expiryMinutes>" | jq .
响应:`{absolutePath, videoUrl, startTime, startTimeEpochMs, expiryISO, expiryMinutes, streamId, type: "replay"}`。
注意:响应中的`startTime`反映实际的片段边界,可能与请求的`startTime`略有差异。

**片段下载/URL的查询参数:**

| 参数 | 是否必填 | 描述 |
|---|---|---|
| `startTime` | 是 | ISO 8601 UTC格式。使用用户提供的值,或先获取时间线以获取有效范围。 |
| `endTime` | 是 | ISO 8601 UTC格式。必须与`startTime`处于同一录制片段内。 |
| `container` | 否 | `mp4`(默认值:`mp2t`/TS) |
| `disableAudio` | 否 | 始终传入`true`——VIOS不支持带B帧的文件音频;默认禁用以避免失败 |
| `transcode` | 否 | `none`(默认值,最快)或`full`(重新编码) |
| `fullLength` | 否 | 布尔值;若为true,则对齐至完整片段边界 |
| `expiryMinutes` | 否(仅URL接口) | URL过期时间(分钟),默认10080(7天) |

---

5. Snapshot / Picture

5. 快照/图片

Live snapshot (most recent frame from sensor)

直播快照(传感器最新帧)

bash
undefined
bash
undefined

width and height are optional; omit to use native sensor resolution (max 8000x4000)

width和height为可选参数;省略则使用传感器原生分辨率(最大8000x4000)

curl -s "http://<VST_ENDPOINT>/vst/api/v1/live/stream/<streamId>/picture?width=<width>&height=<height>"
-H "streamId: <streamId>"
-o snapshot.jpg

**Get temporary URL for live snapshot** (no download, returns URL):
```bash
curl -s "http://<VST_ENDPOINT>/vst/api/v1/live/stream/<streamId>/picture/url" \
  -H "streamId: <streamId>" | jq .
Response:
{absolutePath, imageUrl, expiryISO, expiryMinutes, streamId, type: "live"}
.
curl -s "http://<VST_ENDPOINT>/vst/api/v1/live/stream/<streamId>/picture?width=<width>&height=<height>"
-H "streamId: <streamId>"
-o snapshot.jpg

**获取直播快照的临时URL**(不下载,仅返回URL):
```bash
curl -s "http://<VST_ENDPOINT>/vst/api/v1/live/stream/<streamId>/picture/url" \
  -H "streamId: <streamId>" | jq .
响应:
{absolutePath, imageUrl, expiryISO, expiryMinutes, streamId, type: "live"}

Historical snapshot (frame at a specific timestamp from recordings)

历史快照(录制内容中指定时间点的帧)

startTime: Use the value provided by the user. If not provided, first fetch timelines to find a valid range:
bash
curl -s "http://<VST_ENDPOINT>/vst/api/v1/storage/<streamId>/timelines" | jq .
Pick any timestamp within a returned
{startTime, endTime}
range.
bash
undefined
startTime: 使用用户提供的值。若未提供,先获取时间线以找到有效范围:
bash
curl -s "http://<VST_ENDPOINT>/vst/api/v1/storage/<streamId>/timelines" | jq .
从返回的
{startTime, endTime}
范围内选择任意时间戳。
bash
undefined

startTime is ISO 8601 UTC — the frame closest to this timestamp is returned

startTime为ISO 8601 UTC格式——返回最接近该时间戳的帧

curl -s "http://<VST_ENDPOINT>/vst/api/v1/replay/stream/<streamId>/picture?startTime=<startTime>"
-H "streamId: <streamId>"
-o snapshot_recorded.jpg

Optional: `width`, `height` query parameters (string format, e.g. `width=<width>`).

**Get temporary URL for historical snapshot:**
```bash
curl -s "http://<VST_ENDPOINT>/vst/api/v1/replay/stream/<streamId>/picture/url?startTime=<startTime>" \
  -H "streamId: <streamId>" | jq .
Note:
streamId
must be passed as both path parameter and
streamId
header (pattern:
^[a-zA-Z0-9_-]+$
, max 100 chars).

curl -s "http://<VST_ENDPOINT>/vst/api/v1/replay/stream/<streamId>/picture?startTime=<startTime>"
-H "streamId: <streamId>"
-o snapshot_recorded.jpg

可选参数:`width`、`height`查询参数(字符串格式,例如`width=<width>`)。

**获取历史快照的临时URL:**
```bash
curl -s "http://<VST_ENDPOINT>/vst/api/v1/replay/stream/<streamId>/picture/url?startTime=<startTime>" \
  -H "streamId: <streamId>" | jq .
注意:
streamId
必须同时作为路径参数和
streamId
请求头传入(格式:
^[a-zA-Z0-9_-]+$
,最长100字符)。

6. Add Sensor / Stream

6. 添加传感器/流

Add sensor by IP (ONVIF):
bash
undefined
通过IP添加传感器(ONVIF):
bash
undefined

sensorIp: camera IP address; name/location are optional labels

sensorIp:摄像头IP地址;name/location为可选标签

curl -s -X POST "http://<VST_ENDPOINT>/vst/api/v1/sensor/add"
-H "Content-Type: application/json"
-d '{ "sensorIp": "<sensorIp>", "username": "<username>", "password": "<password>", "name": "<name>", "location": "<location>" }' | jq .
Response: `{"sensorId": "<uuid>"}`.

**Add sensor by RTSP URL:**
```bash
curl -s -X POST "http://<VST_ENDPOINT>/vst/api/v1/sensor/add"
-H "Content-Type: application/json"
-d '{ "sensorIp": "<sensorIp>", "username": "<username>", "password": "<password>", "name": "<name>", "location": "<location>" }' | jq .
响应:`{"sensorId": "<uuid>"}`。

**通过RTSP URL添加传感器:**
```bash

sensorUrl: full RTSP URL with credentials embedded, e.g. rtsp://<username>:<password>@<ip>:<port>/<path>

sensorUrl:包含凭证的完整RTSP URL,例如rtsp://<username>:<password>@<ip>:<port>/<path>

username/password are part of the URL — do not include them separately in the body

username/password已包含在URL中——请勿在请求体中单独传入

name: use the last segment of the RTSP URL path as the default (e.g. for rtsp://.../live/cam1, use "cam1")

name:默认使用RTSP URL路径的最后一段(例如rtsp://.../live/cam1,使用"cam1")

curl -s -X POST "http://<VST_ENDPOINT>/vst/api/v1/sensor/add"
-H "Content-Type: application/json"
-d '{ "sensorUrl": "<sensorUrl>", "name": "<name>" }' | jq .

Optional fields for both: `hardware`, `manufacturer`, `serialNumber`, `firmwareVersion`, `hardwareId`, `tags`.

**Trigger network scan for sensors:**
```bash
curl -s -X POST "http://<VST_ENDPOINT>/vst/api/v1/sensor/scan" | jq .

curl -s -X POST "http://<VST_ENDPOINT>/vst/api/v1/sensor/add"
-H "Content-Type: application/json"
-d '{ "sensorUrl": "<sensorUrl>", "name": "<name>" }' | jq .

两者的可选字段:`hardware`、`manufacturer`、`serialNumber`、`firmwareVersion`、`hardwareId`、`tags`。

**触发传感器网络扫描:**
```bash
curl -s -X POST "http://<VST_ENDPOINT>/vst/api/v1/sensor/scan" | jq .

7. Delete Sensor (RTSP / non-file sensors)

7. 删除传感器(RTSP/非文件传感器)

Use this to delete sensors that are not uploaded files (e.g. RTSP streams added to VIOS):
bash
undefined
用于删除非上传文件类型的传感器(例如添加至VIOS的RTSP流):
bash
undefined

Returns true on success

成功时返回true

curl -s -X DELETE "http://<VST_ENDPOINT>/vst/api/v1/sensor/<sensorId>" | jq .
This removes the sensor from all VIOS APIs but does **not** delete recordings from disk.

> **RTSP full cleanup:** Calling only `DELETE /sensor/<sensorId>` leaves orphaned recordings on disk. See the delete guidance in Section 8 for the complete two-step RTSP removal flow.

---
curl -s -X DELETE "http://<VST_ENDPOINT>/vst/api/v1/sensor/<sensorId>" | jq .
此操作会从所有VIOS API中移除传感器,但**不会**删除磁盘上的录制内容。

> **RTSP完整清理:** 仅调用`DELETE /sensor/<sensorId>`会在磁盘上留下孤立的录制内容。请参阅第8节的删除指南,完成两步式RTSP移除流程。

---

8. File Upload / Delete

8. 文件上传/删除

There are two PUT upload APIs. Use the new API (v2) for most cases.
有两种PUT上传API。大多数情况下请使用新版API(v2)。

PUT Upload — New API (v2):
PUT /storage/file/{filename}

PUT上传——新版API(v2):
PUT /storage/file/{filename}

Filename in path, timestamp and sensorId as query params.
bash
undefined
路径中包含文件名,时间戳和sensorId作为查询参数。
bash
undefined

filename: must not contain whitespace

filename:不能包含空格

timestamp: ISO 8601 UTC, e.g. 2025-01-01T00:00:00.000Z — default when user has not specified: 2025-01-01T00:00:00.000Z

timestamp:ISO 8601 UTC格式,例如2025-01-01T00:00:00.000Z——用户未指定时默认值为2025-01-01T00:00:00.000Z

sensorId: optional — if omitted, server generates a UUID; if provided and already exists, file is added as a sub-stream of that sensor

sensorId:可选——若省略,服务器会生成UUID;若提供且已存在,文件会作为该传感器的子流添加

curl -s -X PUT "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<filename>?timestamp=<timestamp>&sensorId=<sensorId>"
-H "Content-Type: application/octet-stream"
-H "Content-Length: <file_size_in_bytes>"
--upload-file /path/to/video.mp4 | jq .

Key behavior:
- Returns **409 Conflict** if a file with the same name already exists — does NOT auto-rename
- `sensorId` query param: if provided, used as the sensorId (allows grouping under an existing sensor as a sub-stream); if omitted, a new random UUID is generated
- `Content-Length` header is required

---
curl -s -X PUT "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<filename>?timestamp=<timestamp>&sensorId=<sensorId>"
-H "Content-Type: application/octet-stream"
-H "Content-Length: <file_size_in_bytes>"
--upload-file /path/to/video.mp4 | jq .

核心行为:
- 若同名文件已存在,返回**409 Conflict**——不会自动重命名
- `sensorId`查询参数:若提供,用作sensorId(允许将文件归类至现有传感器作为子流);若省略,生成新的随机UUID
- 必须传入`Content-Length`请求头

---

PUT Upload — Legacy API (v1):
PUT /storage/file/{filename}/{timestamp}

PUT上传——旧版API(v1):
PUT /storage/file/{filename}/{timestamp}

Both filename and timestamp in the path. No query params.
bash
undefined
路径中同时包含文件名和时间戳。无查询参数。
bash
undefined

filename: must not contain whitespace

filename:不能包含空格

timestamp: ISO 8601 UTC, e.g. 2025-01-01T00:00:00.000Z — default when user has not specified: 2025-01-01T00:00:00.000Z

timestamp:ISO 8601 UTC格式,例如2025-01-01T00:00:00.000Z——用户未指定时默认值为2025-01-01T00:00:00.000Z

curl -s -X PUT "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<filename>/<timestamp>"
-H "Content-Type: application/octet-stream"
-H "Content-Length: <file_size_in_bytes>"
--upload-file /path/to/video.mp4 | jq .

Key behavior:
- If a file with the same name already exists, **auto-generates a unique filename** (no 409)
- sensorId is **always a newly generated random UUID** — there is no way to specify or reuse an existing sensorId; the `sensorId` query param is ignored even if passed

---

**Response (both APIs):** `{id, filename, bytes, sensorId, streamId, filePath, timestamp, created_at}`.
- `id` — unique file identifier
- `sensorId` / `streamId` — assigned sensor and stream (auto-generated UUID if not provided)
- `filePath` — absolute path on disk where the file is stored
- `created_at` — epoch ms when file was uploaded
- 413 if payload too large; 422 if codec unsupported; 507 if disk full

**Delete an uploaded file** (removes physical file from disk AND removes sensor from all APIs):
```bash
curl -s -X PUT "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<filename>/<timestamp>"
-H "Content-Type: application/octet-stream"
-H "Content-Length: <file_size_in_bytes>"
--upload-file /path/to/video.mp4 | jq .

核心行为:
- 若同名文件已存在,**自动生成唯一文件名**(不会返回409)
- sensorId**始终为新生成的随机UUID**——无法指定或复用现有sensorId;即使传入`sensorId`查询参数也会被忽略

---

**响应(两种API):** `{id, filename, bytes, sensorId, streamId, filePath, timestamp, created_at}`。
- `id` —— 唯一文件标识符
- `sensorId`/`streamId` —— 分配的传感器和流(未提供则为自动生成的UUID)
- `filePath` —— 文件在磁盘上的绝对路径
- `created_at` —— 文件上传时的时间戳(毫秒级)
- 若 payload过大返回413;若 codec不支持返回422;若磁盘已满返回507

**删除上传的文件**(从磁盘中删除物理文件并从所有API中移除传感器):
```bash

streamId: use the streamId returned in the upload response (or from sensor/{sensorId}/streams)

streamId:使用上传响应中返回的streamId(或从sensor/{sensorId}/streams获取)

startTime / endTime: use the timeline range for this streamId (fetch from /storage/<streamId>/timelines)

startTime/endTime:使用该streamId的时间线范围(从/storage/<streamId>/timelines获取)

Returns {spaceSaved: <MB>}

返回{spaceSaved: <MB>}

curl -s -X DELETE "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<streamId>?startTime=<startTime>&endTime=<endTime>" | jq .

> **Identify sensor type before deleting:** call `GET /sensor/<sensorId>/streams` and check the `url` field.
> - If `url` starts with `rtsp://` → RTSP/IP sensor
> - If `url` is a file path (e.g. `/home/vst/.../video.mp4`) → uploaded file sensor
>
> **Which delete to use:**
> - **Uploaded file sensor** — use ONLY `DELETE /storage/file/<streamId>?startTime=...&endTime=...`. This deletes the physical file and removes the sensor from all APIs. Do NOT use `DELETE /sensor/<sensorId>` alone — it removes the sensor from APIs but leaves the physical file on disk.
> - **RTSP sensor** — use BOTH in order: first `DELETE /sensor/<sensorId>` (stops recording, removes from APIs), then `DELETE /storage/file/<streamId>?startTime=...&endTime=...` (deletes recordings from disk). Using only the storage delete on an RTSP sensor erases existing recordings but the sensor stays active and keeps recording.

> **File sensor timeline times:** Uploaded file sensors report timelines relative to the timestamp provided at upload time, not the upload wall-clock time. If the default was used, timelines start at `2025-01-01T00:00:00.000Z`. Always fetch the timeline first before building the delete command — never assume times based on upload time.

---
curl -s -X DELETE "http://<VST_ENDPOINT>/vst/api/v1/storage/file/<streamId>?startTime=<startTime>&endTime=<endTime>" | jq .

> **删除前识别传感器类型:** 调用`GET /sensor/<sensorId>/streams`并检查`url`字段。
> - 若`url`以`rtsp://`开头 → RTSP/IP传感器
> - 若`url`是文件路径(例如`/home/vst/.../video.mp4`) → 上传文件传感器
>
> **选择删除方式:**
> - **上传文件传感器** —— 仅使用`DELETE /storage/file/<streamId>?startTime=...&endTime=...`。此操作会删除物理文件并从所有API中移除传感器。请勿单独使用`DELETE /sensor/<sensorId>`——它会从API中移除传感器,但物理文件仍留在磁盘上。
> - **RTSP传感器** —— 按顺序使用两种方式:先调用`DELETE /sensor/<sensorId>`(停止录制,从API中移除),再调用`DELETE /storage/file/<streamId>?startTime=...&endTime=...`(从磁盘中删除录制内容)。仅对RTSP传感器使用存储删除操作会清除现有录制内容,但传感器仍处于活跃状态并会继续录制。

> **文件传感器时间线时间:** 上传文件传感器报告的时间线基于上传时提供的时间戳,而非上传的实际时间。若使用默认值,时间线从`2025-01-01T00:00:00.000Z`开始。构建删除命令前请始终先获取时间线——切勿基于上传时间假设时间范围。

---

Workflow: sensor name/IP -> clip or snapshot

工作流程:传感器名称/IP → 片段或快照

When the user has a sensor name or IP but needs a clip or snapshot:
  1. Verify VST is reachable (see Setup — Availability Check):
    bash
    curl -sf --connect-timeout 5 "http://<VST_ENDPOINT>/vst/api/v1/sensor/version"
  2. List sensors to find
    sensorId
    :
    bash
    curl -s "http://<VST_ENDPOINT>/vst/api/v1/sensor/list" | jq .
  3. Get streams for that sensor to find
    streamId
    (prefer
    isMain: true
    ):
    bash
    curl -s "http://<VST_ENDPOINT>/vst/api/v1/sensor/<sensorId>/streams" | jq .
  4. Check timelines to confirm a recording exists in the requested range:
    bash
    curl -s "http://<VST_ENDPOINT>/vst/api/v1/storage/<streamId>/timelines" | jq .
  5. Download clip or snapshot using the
    streamId
    .

当用户拥有传感器名称或IP但需要获取片段或快照时:
  1. 验证VST是否可达(请参阅设置——可用性检查):
    bash
    curl -sf --connect-timeout 5 "http://<VST_ENDPOINT>/vst/api/v1/sensor/version"
  2. 列出传感器以找到
    sensorId
    bash
    curl -s "http://<VST_ENDPOINT>/vst/api/v1/sensor/list" | jq .
  3. 获取该传感器的流以找到
    streamId
    (优先选择
    isMain: true
    的流):
    bash
    curl -s "http://<VST_ENDPOINT>/vst/api/v1/sensor/<sensorId>/streams" | jq .
  4. 检查时间线以确认请求范围内存在录制内容:
    bash
    curl -s "http://<VST_ENDPOINT>/vst/api/v1/storage/<streamId>/timelines" | jq .
  5. 使用
    streamId
    下载片段或快照。

Responses

响应

Success with data: JSON object or array.
Success with no data:
null
— a
null
response means the API call succeeded but there is no data to return (e.g. no schedule configured, scan returned no results). It is not an error.
Success with boolean: Some endpoints return
true
on success (e.g.
DELETE /sensor/{sensorId}
).
Error: JSON object with
error_code
and
error_message
:
json
{
  "error_code": "VMSInternalError",
  "error_message": "VMS internal processing error"
}
Common codes:
VMSInternalError
,
VMSNotFound
,
VMSInvalidParameter
.

带数据的成功响应: JSON对象或数组。
无数据的成功响应:
null
——
null
响应表示API调用成功但无数据返回(例如未配置调度、扫描无结果)。这并非错误。
布尔值成功响应: 部分端点成功时返回
true
(例如
DELETE /sensor/{sensorId}
)。
错误响应: 包含
error_code
error_message
的JSON对象:
json
{
  "error_code": "VMSInternalError",
  "error_message": "VMS内部处理错误"
}
常见错误码:
VMSInternalError
VMSNotFound
VMSInvalidParameter

Tips

提示

  • jq: All JSON responses are piped through
    jq .
    for readability. Binary responses (clip download, snapshot) are not — they use
    -o <file>
    instead.
  • Time format: Always ISO 8601 UTC, e.g.
    2026-04-10T10:30:00Z
    or
    2026-04-10T10:30:00.000Z
    .
  • streamId header: Live/replay/recorder endpoints require
    streamId
    as BOTH a path parameter AND a request header — include both.
  • Large clips: Use the
    /url
    variant to get a temporary download link rather than streaming bytes through curl.
  • Sensor vs stream ID:
    sensorId
    identifies a camera;
    streamId
    identifies a specific video stream from that camera (a sensor can have a main stream and sub-streams).
  • Identifying sensor type (RTSP vs uploaded file): Call
    GET /sensor/<sensorId>/streams
    and inspect the
    url
    field of each stream. If
    url
    starts with
    rtsp://
    it is a live RTSP/IP camera stream. If
    url
    is a file path (e.g.
    "/home/vst/vst_release/streamer_videos/TruckAccident.mp4"
    ) it is an uploaded file sensor. This determines which delete flow to use — see Section 8.
  • Endpoint resolution: The VST endpoint is provided by the VSS deployment context. Do not attempt manual IP/port discovery. If unavailable, ask the user. All curl examples use
    <VST_ENDPOINT>
    as a placeholder — substitute the resolved endpoint before executing.
  • jq: 所有JSON响应均通过
    jq .
    管道处理以提高可读性。二进制响应(片段下载、快照)除外——它们使用
    -o <file>
    替代。
  • 时间格式: 始终使用ISO 8601 UTC格式,例如
    2026-04-10T10:30:00Z
    2026-04-10T10:30:00.000Z
  • streamId请求头: 直播/回放/录制端点要求
    streamId
    同时作为路径参数和请求头传入——请同时包含两者。
  • 大片段: 使用
    /url
    变体获取临时下载链接,而非通过curl流式传输字节。
  • 传感器ID与流ID:
    sensorId
    标识摄像头;
    streamId
    标识该摄像头的特定视频流(一个传感器可包含主流和子流)。
  • 识别传感器类型(RTSP vs 上传文件): 调用
    GET /sensor/<sensorId>/streams
    并检查每个流的
    url
    字段。若
    url
    rtsp://
    开头,则为直播RTSP/IP摄像头流。若
    url
    是文件路径(例如
    "/home/vst/vst_release/streamer_videos/TruckAccident.mp4"
    ),则为上传文件传感器。这决定了应使用哪种删除流程——请参阅第8节。
  • 端点解析: VST端点由VSS部署环境提供。请勿尝试手动发现IP/端口。若端点不可用,请询问用户。所有curl示例使用
    <VST_ENDPOINT>
    作为占位符——执行前请替换为解析后的端点。