五分鐘快速開始
從乾淨節點到第一則圖片事件
這條黃金路徑不需要攝影機或雲端帳號。先使用 deterministic mock provider 驗證 API key、持久化資源、JPEG、Event、Webhook 簽章與證據下載,再換成真實 RTSP 與模型。
會收到什麼?事件輸出與欄位
Watch 會以 HTTP POST 將事件 JSON 送到你設定的 Webhook URL。以下是異常事件的精簡範例(只列常用欄位,ID、時間與內容為示意)。
{
"id": "evt_example",
"schema": "sentinel.event.v1",
"type": "monitor.alert.raised",
"severity": "critical",
"state": "raised",
"created_at": "2026-09-07T12:00:00Z",
"source_id": "src_camera03",
"monitor_id": "mon_restricted_area",
"title": "有人進入管制區域",
"summary": "攝影機 03 偵測到有人進入指定區域。",
"evidence": {
"image_url": "/v1/events/evt_example/image"
}
}| 欄位 | 用途 |
|---|---|
| id | 事件 ID。同一事件的狀態更新可沿用此 ID。 |
| type | 發生什麼事,例如 monitor.alert.raised(監看告警)。 |
| severity | 嚴重程度:safe、suspicious、critical。 |
| state | 事件狀態:raised(發生)、updated(更新)、cleared(解除)。 |
| created_at | 事件建立時間(ISO 8601)。 |
| source_id / monitor_id | 對應的攝影機來源與監看任務;部分系統事件可為 null。 |
| title / summary | 提供人閱讀的標題與說明,不要用文字解析來判斷告警。 |
| evidence.image_url | 事件圖片位置;可能無圖片。下載需 events:read API key。 |
常見事件:monitor.alert.raised(告警發生)、monitor.alert.updated(告警更新)、monitor.alert.cleared(告警解除)、source.disconnected(攝影機斷線)、inference.failed(推論失敗)。實際接收哪些事件,由 Webhook 篩選設定決定;只勾 critical 與 raised 時,不會收到所有更新或解除通知。
接收端先驗證簽章、保存事件,再回覆 2xx。重送請依 HTTP header 的 X-Sentinel-Delivery-ID 去重,不要只用事件 id。Webhook 不會逐筆傳送普通推論。
本機 wiring 驗證
不需要攝影機
節點保持運行
0. 取得 Source Kit
以下指令要從 Sentinel Monitor Source Kit 的 checkout 執行。目前尚未發布可匿名下載的映像或公開原始碼;評估套件會包含 Runtime、Compose、範例與這份文件。
執行前:安裝並啟動必要工具
Docker 提供隔離的 API Runtime、mock provider 與持久化 volumes;Quickstart 不會啟動選用 UI。macOS/Linux 路徑另外需要 curl 與 Python 3,因為腳本會做 readiness、第一則 Event 與證據雜湊驗證。
- macOS:安裝並開啟 Docker Desktop,等待 Engine running。
- macOS:從 Python 官方頁安裝 Python 3;macOS 內建 curl,若驗證指令找不到它,先完成系統更新或依 curl 官方安裝說明恢復。 curl ↗
- Ubuntu Linux:依官方步驟安裝 Docker Engine 與 Compose plugin.
- Ubuntu:套件安裝可經管理員核准使用 sudo apt-get install curl python3;Docker 安裝後,依官方 Linux post-install 設定 non-root(docker group 等同 root 權限)或採用 rootless mode,登出再登入,直到一般使用者能通過下方 docker version。不要用 sudo 執行 Sentinel Quickstart。 non-root 設定 ↗ · rootless ↗
- Windows/WSL:不要在 Ubuntu 另裝第二套 Docker;使用 Windows 11 首次安裝指南.
docker version
docker compose version
docker info --format '{{.OSType}}'
curl --version
python3 --version一個指令,取得第一則事件
macOS、Linux 或 Ubuntu/WSL
./deploy/api/quickstart.shWindows PowerShell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\deploy\api\quickstart.ps1在 Source Kit 根目錄執行其中一條指令。Quickstart 會自行找到部署檔案、在需要時建立私密金鑰、啟動 API-only Runtime 與 deterministic mock provider、等待 readiness、執行完整的第一則 Event 範例,最後保留節點運行。它們不會啟動選用 UI。Windows 的 ExecutionPolicy 只套用到該驗證過 kit 的子程序,不會變更使用者或機器政策。
進階:手動走一次相同路徑
1. 啟動 API-only Runtime
cd Sentinel-Monitor/deploy/api
# If .env already exists, keep it; bootstrap refuses to overwrite secrets.
./bootstrap.sh mock
docker compose up -d --build
export SENTINEL_API_KEY="$(python3 ../../docs/api/examples/read_dotenv.py .env SENTINEL_API_KEY)"
export SENTINEL_BASE_URL=http://localhost:8000
curl --fail "$SENTINEL_BASE_URL/readyz"
curl --fail "$SENTINEL_BASE_URL/v1/system" \
-H "Authorization: Bearer $SENTINEL_API_KEY"2. 建立測試 Source
SOURCE_JSON="$(curl --fail -X POST "$SENTINEL_BASE_URL/v1/sources" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-source-1" \
-d '{
"name": "Quickstart JPEG",
"input": {"type": "frame"}
}')"
export SOURCE_ID="$(printf '%s' "$SOURCE_JSON" |
python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
printf 'Created %s\n' "$SOURCE_ID"3. 建立 Monitor
MONITOR_JSON="$(python3 -c 'import json,os
print(json.dumps({
"name": "After-hours loading dock",
"source_id": os.environ["SOURCE_ID"],
"prompt": "Notify when a person enters the loading area after hours.",
"enabled": True,
}))' |
curl --fail -X POST "$SENTINEL_BASE_URL/v1/monitors" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-monitor-1" \
--data-binary @-)"
export MONITOR_ID="$(printf '%s' "$MONITOR_JSON" |
python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
printf 'Created %s\n' "$MONITOR_ID"4. 選用:註冊並測試 Webhook
: "${SENTINEL_WEBHOOK_URL:?Export a reachable HTTPS receiver URL first}"
WEBHOOK_JSON="$(python3 -c 'import json,os
print(json.dumps({
"name": "My receiver",
"url": os.environ["SENTINEL_WEBHOOK_URL"],
"secret_env": "SENTINEL_WEBHOOK_SIGNING_SECRET",
"enabled": True,
"filters": {"event_types": ["sdk.test"]},
}))' |
curl --fail -X POST "$SENTINEL_BASE_URL/v1/webhook-endpoints" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-webhook-1" \
--data-binary @-)"
export WEBHOOK_ID="$(printf '%s' "$WEBHOOK_JSON" |
python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
curl --fail -X POST \
"$SENTINEL_BASE_URL/v1/webhook-endpoints/$WEBHOOK_ID/test" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-webhook-test-1" \
-d '{
"severity": "suspicious",
"title": "Sentinel webhook test",
"summary": "Verify receipt and signature."
}'自動 smoke 已用本機 receiver 驗證 exact-body HMAC;只有在你已有可連線的 receiver 時才需要手動執行此步驟。若要接收下一則 sdk.test Event,請保持 receiver 運作。
5. 傳入真正的 JPEG bytes
export TEST_JPEG="${TMPDIR:-/tmp}/sentinel-quickstart-frame.jpg"
python3 -c 'import base64,pathlib,sys
pathlib.Path(sys.argv[2]).write_bytes(base64.b64decode(pathlib.Path(sys.argv[1]).read_text()))' \
../../docs/api/assets/sample-frame.jpg.b64 "$TEST_JPEG"
curl --fail -X POST "$SENTINEL_BASE_URL/v1/sources/$SOURCE_ID/frames" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: image/jpeg" \
-H "Idempotency-Key: quickstart-frame-1" \
--data-binary "@$TEST_JPEG"frames 是有限的測試/自訂 ingest 路徑,不是影片儲存 API。Runtime 會在推理前驗證 content type、解碼尺寸與大小上限。
6. 建立含圖片的 deterministic 測試 Event
EVENT_JSON="$(python3 -c 'import base64,json,os,pathlib
print(json.dumps({
"source_id": os.environ["SOURCE_ID"],
"monitor_id": os.environ["MONITOR_ID"],
"type": "sdk.test",
"severity": "suspicious",
"summary": "Quickstart evidence event",
"image_base64": base64.b64encode(pathlib.Path(os.environ["TEST_JPEG"]).read_bytes()).decode(),
}))' |
curl --fail -X POST "$SENTINEL_BASE_URL/v1/events/test" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-event-1" \
--data-binary @-)"
export EVENT_ID="$(printf '%s' "$EVENT_JSON" |
python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
printf 'Created %s\n' "$EVENT_ID"image_base64 只存在於受控的 test-event endpoint,方便沒有攝影機時驗證證據路徑。正式 Event 與 Webhook 預設都回傳 image_url,不把 Base64 內嵌在 JSON。
7. 查詢 Event 並下載 JPEG
curl --fail "$SENTINEL_BASE_URL/v1/events/$EVENT_ID" \
-H "Authorization: Bearer $SENTINEL_API_KEY"
curl --fail "$SENTINEL_BASE_URL/v1/events/$EVENT_ID/image" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
--output event.jpg
file event.jpg普通推論文字與即時預覽
curl --no-buffer --fail \
"$SENTINEL_BASE_URL/v1/analyses/stream?monitor_id=$MONITOR_ID" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Accept: text/event-stream"
curl --fail \
"$SENTINEL_BASE_URL/v1/sources/$SOURCE_ID/stream?max_fps=15&max_height=720" \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
--output preview.mjpeg第一個串流會送出每一次完成的普通推論文字(包含安全結果);第二個是受限制的 MJPEG 預覽。事件/警告/錯誤請用 /v1/events、/v1/events/stream 或 signed Webhook;關閉桌面視窗不會停止這些 API 輸出。
Python:執行同一套已測試流程
Source kit 內附只使用 Python 3 標準函式庫的完整範例;它會建立 Source 與 Monitor、傳入 JPEG、建立測試 Event,並驗證下載證據的 SHA-256。
cd deploy/api
export SENTINEL_BASE_URL=http://127.0.0.1:8000
export SENTINEL_API_KEY="<your-server-side-key>"
python3 ../../docs/api/examples/first_event.pyJavaScript:查詢與二進位圖片
import { writeFile } from "node:fs/promises";
const base = "http://localhost:8000";
const headers = { Authorization: `Bearer ${process.env.SENTINEL_API_KEY}` };
const events = await fetch(`${base}/v1/events?limit=10`, { headers })
.then(async (response) => {
if (!response.ok) throw await response.json();
return response.json();
});
const event = events.data[0];
if (!event) throw new Error("No events returned");
const image = await fetch(new URL(event.evidence.image_url, base), { headers });
if (!image.ok) throw new Error(`image download failed: ${image.status}`);
await writeFile("event.jpg", Buffer.from(await image.arrayBuffer()));換成真實環境
- 依模型指南改用 local_* 或 private_openai_compatible;cloud_gemini 必須通過文件列出的 release gate 才能使用。
- 先設定精確 RTSP host/host:port 或 CIDR allowlist,再建立 input.type=rtsp 的 Source。
- 呼叫 Source test,確認可解碼影格與 sanitized failure code。
- 為新的 RTSP Source 建立新的 Monitor,再用代表性影像觸發真實推理;mock Monitor 仍連到原本的 frame Source。