Kami Conflict Detection
/install kami-conflict-detection
\r \r
Kami Conflict Detection\r
\r Detect physical conflicts (fighting, shoving, scuffling) between 2+ people from RTSP camera streams or local video files. Uses an event-driven architecture where OpenClaw schedules the script in a loop for continuous real-time monitoring.\r \r
Execution Architecture (Event-Driven Loop)\r
\r
┌──────────────────────────────────────────────────────────┐\r
│ OpenClaw Scheduling Loop │\r
│ │\r
│ 1. OpenClaw starts the script │\r
│ └─ .venv/bin/python conflict_detector_last.py │\r
│ │\r
│ 2. Script continuously monitors video stream │\r
│ ├─ YOLO: count persons in frame │\r
│ ├─ >= min_persons? Collect multiple frames │\r
│ ├─ Send frames to LLM API for conflict analysis │\r
│ └─ Conflict detected? │\r
│ ├─ No → continue monitoring │\r
│ └─ Yes → save video clip, output JSON, exit(10) │\r
│ │\r
│ 3. OpenClaw reads stdout alert JSON │\r
│ └─ Reports detection result to user in chat window │\r
│ │\r
│ 4. OpenClaw automatically restarts script → back to 1 │\r
└──────────────────────────────────────────────────────────┘\r
```\r
\r
## Detection Pipeline\r
\r
1. **YOLO pre-filter** — lightweight person detection to count people in frame (must be >= 2)\r
2. **Multi-frame collection** — collect N frames with configurable time gap\r
3. **LLM conflict analysis** — send frames to Kami detection API for violence/conflict judgment\r
4. **Event-triggered exit** — on conflict detection, save video clip, output alert JSON, exit with code 10\r
\r
## When to Use\r
\r
Use this skill when the user wants to:\r
- Monitor a camera feed for physical fights or scuffles\r
- Detect shoving, pushing, or violent behavior between people\r
- Run conflict detection on a local video file for testing\r
- Set up automated surveillance alerts for physical altercations\r
\r
## Installation\r
\r
```bash\r
bash setup.sh\r
```\r
\r
This will:\r
1. Detect system Python, create `.venv/` virtual environment\r
2. Install dependencies: `onnxruntime`, `opencv-python-headless`, `numpy`, `requests`\r
3. Create `alerts/` output directory\r
\r
Idempotent — safe to run repeatedly.\r
\r
## Prerequisites\r
\r
- `python3` and `python3-venv` installed on the system\r
- `yolov8s-worldv2.onnx` model file in the skill directory\r
- RTSP camera online and network-reachable, OR a local video file for testing\r
- Kami API key (via `--kami_api_key` or environment variable `KAMI_API_KEY`). If you don't have one yet, register and obtain a key at: https://kamiclaw-skill.kamihome.com\r
- `setup.sh` has been run at least once\r
\r
## Parameter Confirmation\r
\r
Before running this skill, confirm the following parameters with the user:\r
\r
| Parameter | Default | Description |\r
|-----------|---------|-------------|\r
| `--rtsp_url` | *(required)* | RTSP camera URL or local video file path |\r
| `--kami_api_key` | *(required)* | Kami API key (also via env `KAMI_API_KEY`). Register at https://kamiclaw-skill.kamihome.com if you don't have one. |\r
| `--yolo_model` | `yolov8s-worldv2.onnx` | YOLO model file path |\r
| `--conf_threshold` | `0.25` | YOLO confidence threshold (0.0-1.0) |\r
| `--min_persons` | `2` | Minimum person count to trigger LLM analysis |\r
| `--sample_interval` | `1.0` | How often (seconds) to run YOLO pre-filter |\r
| `--multi_frame_count` | `3` | Number of frames to collect for LLM analysis |\r
| `--multi_frame_gap` | `0.5` | Time gap (seconds) between collected frames |\r
| `--buffer_seconds` | `30` | Ring buffer duration (seconds) for video clip export |\r
| `--clip_before` | `5` | Seconds of video to include before the conflict |\r
| `--clip_after` | `5` | Seconds of video to include after the conflict |\r
| `--output_dir` | `alerts/` | Directory for saved video clips |\r
| `--run_time` | `0` | Max single-round run time in seconds; `0` = unlimited |\r
| `--fps` | `15` | Video stream frame rate |\r
| `--inbox_file` | `alerts/pending.jsonl` | Alarm inbox file consumed by the heartbeat task to push into the chat window |\r
| `--feishu_webhook` | *(env `FEISHU_WEBHOOK_URL`)* | Feishu custom bot webhook URL — alarms are pushed directly to the user's phone |\r
| `--feishu_secret` | *(env `FEISHU_WEBHOOK_SECRET`)* | Feishu webhook signing secret (only if the bot has signing enabled) |\r
\r
**Ask the user: do any parameters need to be changed?**\r
\r
### Feishu push setup\r
\r
Create a Feishu custom bot (自定义机器人) in the target group chat, copy its webhook URL, then either:\r
\r
```bash\r
export FEISHU_WEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx"\r
# Optional, only if the bot has "签名校验" enabled:\r
export FEISHU_WEBHOOK_SECRET="your_secret_here"\r
```\r
\r
Or pass `--feishu_webhook` / `--feishu_secret` on the CLI. When set, every conflict alarm is POSTed to Feishu as an interactive card (title / description / timestamp / clip duration / clip path). If the env var is empty, the Feishu channel is silently skipped — detection still works.\r
\r
## Alarm Delivery Channels (Tri-channel)\r
\r
Alarms are delivered through **three independent, redundant channels** so the user\r
is notified even if one path fails:\r
\r
| # | Channel | Trigger | Consumer | Guarantee |\r
|---|---------|---------|----------|-----------|\r
| 1 | **stdout JSON + exit(10)** | On every conflict | OpenClaw reads stdout and reports in chat window, then restarts the script | Primary chat push (OpenClaw loop) |\r
| 2 | **Inbox file** `alerts/pending.jsonl` | On every conflict (appended) | Heartbeat task in `space/HEARTBEAT.md` polls the file and proactively pushes unreported alarms into chat | Fallback chat push (survives OpenClaw glitches) |\r
| 3 | **Feishu webhook** (interactive card) | On every conflict (if `FEISHU_WEBHOOK_URL` set) | User's phone via Feishu bot | Instant phone push, regardless of LLM / chat state |\r
\r
Channels 2 and 3 mirror the design already proven in `kami-suspicious-person`.\r
Channel 1 remains the canonical driver of the OpenClaw detect-report-restart loop.\r
\r
## OpenClaw Execution Instructions\r
\r
OpenClaw should execute this skill using the following loop logic:\r
\r
### Step 1: Start Detection\r
\r
```bash\r
.venv/bin/python conflict_detector_last.py \\r
--rtsp_url \x3CUSER_RTSP_URL> \\r
--kami_api_key \x3CAPI_KEY> \\r
[other params]\r
```\r
\r
### Step 2: Handle Exit Code\r
\r
| Exit Code | Meaning | OpenClaw Action |\r
|-----------|---------|-----------------|\r
| `0` | Normal exit (video ended, timeout, no event) | Report "monitoring session ended normally" to user. Optionally restart. |\r
| `10` | **Event detected** — conflict alert JSON on stdout | Parse stdout JSON, report alert details to user in chat, then **immediately restart** the script. |\r
| `1` | Runtime error | Report error to user, check logs at `conflict_detector.log`. |\r
\r
### Step 3: Report to User\r
\r
When exit code is `10`, parse the stdout JSON and report to the user like:\r
\r
> 🥊 **Physical Conflict Alert**\r
> A physical conflict has been detected: Two people are engaged in a physical altercation.\r
> Video clip saved to alerts/conflict_20250115_143022.mp4 (10s).\r
> Please review and take appropriate action.\r
>\r
> *Restarting monitoring...*\r
\r
### Step 4: Restart\r
\r
After reporting, immediately restart the script with the same parameters to continue monitoring.\r
\r
### Complete Loop Example\r
\r
```\r
OpenClaw:\r
1. Run: .venv/bin/python conflict_detector_last.py --rtsp_url rtsp://... --kami_api_key ...\r
2. Wait for process to exit\r
3. If exit_code == 10:\r
- Read stdout JSON\r
- Display alert message to user in chat\r
- Go to step 1 (restart)\r
If exit_code == 0:\r
- Inform user: "Monitoring session ended normally, no conflicts detected"\r
- Ask user if they want to restart\r
If exit_code == 1:\r
- Report error, show log content\r
```\r
\r
## Usage\r
\r
```bash\r
# Initialize environment (first time only)\r
bash setup.sh\r
\r
# Run with RTSP stream\r
.venv/bin/python conflict_detector_last.py \\r
--rtsp_url rtsp://127.0.0.1/live/YOUR-STREAM-ID \\r
--kami_api_key YOUR-API-KEY\r
\r
# Run with local video file (for testing)\r
.venv/bin/python conflict_detector_last.py \\r
--rtsp_url /path/to/test_video.mp4 \\r
--kami_api_key YOUR-API-KEY\r
\r
# Custom parameters\r
.venv/bin/python conflict_detector_last.py \\r
--rtsp_url rtsp://127.0.0.1/live/YOUR-STREAM-ID \\r
--kami_api_key YOUR-API-KEY \\r
--min_persons 2 \\r
--clip_before 10 \\r
--clip_after 10 \\r
--run_time 3600\r
```\r
\r
## Output Format (stdout JSON)\r
\r
When a conflict is detected (exit code 10), stdout contains:\r
\r
```json\r
{\r
"alert": "conflict_detected",\r
"timestamp": "2025-01-15T14:30:22.123456",\r
"description": "Two people are engaged in a physical altercation",\r
"video_clip": "alerts/conflict_20250115_143022.mp4",\r
"clip_duration": "10s",\r
"message": "Warning: Physical conflict detected. Two people are engaged in a physical altercation. Video clip saved to alerts/conflict_20250115_143022.mp4. Please review and take appropriate action."\r
}\r
```\r
\r
| Field | Type | Description |\r
|-------|------|-------------|\r
| `alert` | string | Always `"conflict_detected"` |\r
| `timestamp` | string | ISO format timestamp of the alert |\r
| `description` | string | LLM-generated description of the conflict |\r
| `video_clip` | string | Path to the saved video clip |\r
| `clip_duration` | string | Total duration of the saved clip |\r
| `message` | string | Pre-formatted alert message for direct display |\r
\r
## Exit Codes\r
\r
| Code | Meaning |\r
|------|---------|\r
| `0` | Normal exit (run time exceeded, video ended, user interrupt, no event detected) |\r
| `10` | **Event detected** — conflict alert, JSON output on stdout |\r
| `1` | Runtime error (model not found, stream failure, missing API key) |\r
\r
## Architecture\r
\r
```\r
RTSP/File → FrameGrabber thread (ring buffer + latest frame)\r
├─ All frames → ring buffer (last 30s)\r
└─ Latest frame → main thread (every 1s)\r
├─ YOLO: person count >= 2?\r
│ ├─ No → skip, clear frame buffer\r
│ └─ Yes → collect N frames (gap=0.5s)\r
│ → LLM conflict analysis\r
│ ├─ No conflict → continue\r
│ └─ Conflict detected:\r
│ → wait clip_after seconds\r
│ → export video clip from ring buffer\r
│ → output JSON to stdout\r
│ → exit(10)\r
└─ Timeout → exit(0)\r
\r
OpenClaw drives the loop:\r
run script → wait for exit → parse stdout → report to user → re-run script\r
```\r
\r
## Launch Checklist (Dual-channel Active Push)\r
\r
This skill pushes every alarm through three redundant channels (see **Alarm\r
Delivery Channels** above): stdout+exit(10), inbox file, and Feishu webhook.\r
Before launching the detector, the agent MUST verify:\r
\r
- [ ] `FEISHU_WEBHOOK_URL` env var is set (or `--feishu_webhook` is passed). If not, warn the user that phone push is disabled — chat-window push still works via stdout+exit(10) and the inbox file.\r
- [ ] `alerts/` directory is writable so `pending.jsonl` can be appended.\r
- [ ] `space/HEARTBEAT.md` still contains the conflict-detection inbox task; on every heartbeat, read `kami-conflict-detection/alerts/pending.jsonl`, if non-empty send a proactive summary to the user then MOVE (not delete) the file to `alerts/consumed/\x3Ctimestamp>.jsonl`. If empty, reply `HEARTBEAT_OK`.\r
- [ ] Previous run's `alerts/pending.jsonl` has been consumed (or archived) to avoid re-reporting stale alarms.\r
\r
**Never** rely on tailing stdout to report alarms — the agent is only invoked on\r
user messages / heartbeats, so real-time stdout watching is impossible.\r
\r
## Strict Rules (MUST Follow)\r
\r
- **RULE**: Alarms flow via (a) stdout+exit(10) → OpenClaw → chat, (b) inbox file → heartbeat → chat, (c) Feishu webhook → user's phone. Never rely solely on one channel.\r
- **RULE**: Every heartbeat consumes `alerts/pending.jsonl`; non-empty → proactive chat summary; empty → `HEARTBEAT_OK`.\r
- **RULE**: Consumed alarms are MOVED to `alerts/consumed/`, not deleted.\r
- **RULE**: Verify `FEISHU_WEBHOOK_URL` before launch; warn the user if missing (phone push disabled, chat push still active).\r
- **RULE**: On exit code `10`, OpenClaw MUST restart the script immediately to continue monitoring.\r
\r
## Troubleshooting\r
\r
**Virtual environment not found**\r
→ Run `bash setup.sh`\r
\r
**Model file missing**\r
→ Place `yolov8s-worldv2.onnx` in the skill directory\r
\r
**RTSP connection failure**\r
→ Verify camera is online, check `--rtsp_url`, confirm network connectivity\r
\r
**LLM API failure**\r
→ Check `--kami_api_key` is correct, or set via `export KAMI_API_KEY=your-key`. If you don't have a key, register at https://kamiclaw-skill.kamihome.com. Verify network access to the detection API endpoint.\r
\r
**No alerts generated**\r
→ Check `conflict_detector.log` for details. Common causes: fewer than 2 people in frame, confidence threshold too high (try lowering `--conf_threshold`).\r
\r
**Script exits immediately with code 1**\r
→ Check log for error details. Common causes: model file missing, RTSP URL unreachable, API key not set.\r
\r
**OpenClaw restart loop too fast**\r
→ If the script keeps detecting events immediately on restart, consider increasing `--sample_interval` or adding a brief delay between restarts.\r
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install kami-conflict-detection - After installation, invoke the skill by name or use
/kami-conflict-detection - Provide required inputs per the skill's parameter spec and get structured output
What is Kami Conflict Detection?
Detect physical conflicts (fighting, shoving, scuffling) between 2+ people from RTSP camera streams or local video files. Event-driven mode: the script exits... It is an AI Agent Skill for Claude Code / OpenClaw, with 28 downloads so far.
How do I install Kami Conflict Detection?
Run "/install kami-conflict-detection" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Kami Conflict Detection free?
Yes, Kami Conflict Detection is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Kami Conflict Detection support?
Kami Conflict Detection is cross-platform and runs anywhere OpenClaw / Claude Code is available (linux).
Who created Kami Conflict Detection?
It is built and maintained by KamiVision (@13681882136); the current version is v1.0.0.