Detect fall events from RTSP camera streams using the KamiClaw cloud API. No local GPU needed — all inference runs server-side.
In short: Only 8-second alarm clips are sent to the cloud for AI analysis. No continuous streaming, no audio, no full video.
| What | Local | Cloud |
|---|---|---|
| ------ | ------- | ------- |
| Video stream / file | ✅ Processed locally | ❌ Never sent |
| 8-second alarm clips | ✅ Saved (optional) | ✅ Sent for AI analysis |
| Audio | ❌ Not collected | ❌ Not collected |
> 📄 Full details: Read our Privacy Policy for complete information on data handling, retention, and your rights.
save_alarm_clips: false to not save clips locallyfind logs/clips/ -type f -mtime +30 -deleteconfig.json to git> ℹ️ AI analysis requires sending alarm clips to the cloud API. Processed clips are retained per the provider's data retention policy.
All settings are in config.json. The agent auto-fills this when you provide values in chat.
| Field | Default | Description |
|---|---|---|
| ------- | --------- | ------------- |
api_key | "" | Required. KamiClaw API key |
cameras | [] | Required. Array of {name, rtsp_url} entries. Single entry: name optional, defaults to "default". Two or more entries: every entry must have a unique non-empty name. |
save_alarm_clips | true | Save alarm video clips to logs/clips/ |
feishu_webhook_url | "" | Feishu webhook URL for alarm notifications |
telegram_bot_token | "" | Telegram bot token for alarm notifications |
telegram_chat_id | "" | Telegram chat ID (user or group) |
discord_webhook_url | "" | Discord webhook URL (push notifications) |
discord_bot_token | "" | Discord bot token (two-way capable) |
discord_channel_id | "" | Discord channel ID (for bot) |
All cameras are declared in the cameras array. Each entry has just two fields: name and rtsp_url.
Single camera (one entry). name is optional — if omitted it defaults to "default":
{
"cameras": [
{ "rtsp_url": "rtsp://192.168.1.100/live/stream" }
]
}
Multiple cameras (two or more entries). Every entry must have a unique, non-empty name. Strongly recommended: pick a meaningful location label so the operator immediately knows which camera triggered.
{
"cameras": [
{ "name": "front_door", "rtsp_url": "rtsp://192.168.1.101/live/stream" },
{ "name": "backyard", "rtsp_url": "rtsp://192.168.1.102/live/stream" }
]
}
name is shown in every Feishu / Telegram / Discord push and tags every log line.cameras is empty, or if multiple entries are missing/sharing a name.MUST show this table to the user when configuring cameras, so they can pick a URL pattern based on their brand:
| Brand key | Brand | URL pattern |
|---|---|---|
| ----------- | ------- | ------------- |
hikvision | Hikvision | rtsp://{user}:{pwd}@{ip}:554/Streaming/Channels/101 (101=ch1 main, 102=ch1 sub) |
dahua | Dahua | rtsp://{user}:{pwd}@{ip}:554/cam/realmonitor?channel=1&subtype=0 (subtype=0 main, 1 sub) |
tplink | TP-Link | rtsp://{user}:{pwd}@{ip}:554/stream1 (stream1 main, stream2 sub) |
ezviz | EZVIZ | rtsp://admin:{verify_code}@{ip}:554/H264/ch1/main/av_stream |
uniview | Uniview | rtsp://{user}:{pwd}@{ip}:554/media/video1 |
reolink | Reolink | rtsp://{user}:{pwd}@{ip}:554/h264Preview_01_main |
| Field | Default | Description |
|---|---|---|
| ------- | --------- | ------------- |
run_time | 0 | Max run time in seconds; 0 = unlimited |
pre_seconds | 3.0 | Seconds buffered before motion trigger |
post_seconds | 3.0 | Seconds collected after motion trigger |
Tell the agent which channels you want. They'll guide you through setup.
| Channel | Push Only | Two-Way Capable |
|---|---|---|
| --------- | ----------- | ---------------- |
| Feishu | Webhook URL | Group Bot (same config) |
| Telegram | Bot Token + Chat ID | + Gateway Service |
| Discord | Webhook URL | Bot Token + Channel ID |
> 💡 Discord: Bot token + channel ID gives you full two-way capability. Webhook is simpler for push-only.
> 💡 Need help? Ask OpenClaw for guidance.
# With config.json (recommended)
.venv/bin/python fall_detect_cloud_skill.py
# Or override the API key on the CLI
.venv/bin/python fall_detect_cloud_skill.py \
--api_key sk_live_xxxxxxxx
Cameras are always declared in config.json under the cameras array — there is no CLI flag for the RTSP URL.
The skill runs continuously. It does NOT stop after an alarm — it resets and keeps monitoring.
Fall detected:
{
"alarm": true,
"type": "fall",
"camera_name": "front_door",
"fall_type": "active_falling",
"num_persons": 1,
"confidence": 0.92,
"reason": "Person collapsed from standing to floor near bed",
"frame": 87,
"source": "rtsp://192.168.1.101/live/stream",
"clip": "logs/clips/alarm_fall_20260429_143201.mp4"
}
Normal exit (run time reached):
{
"alarm": false,
"type": null,
"detail": "Run time limit reached, no fall detected",
"frames_processed": 3600,
"source": "rtsp://192.168.1.100/live/stream"
}
| Code | Meaning |
|---|---|
| ------ | --------- |
0 | Normal exit (run time reached) |
1 | Error (invalid API key, missing config, etc.) |
detectType: FALL, detectSubType: SK_FALL_DETECTION)For agents configuring this skill:
config.json — check whether api_key is set and whether cameras is a non-empty array.api_key is empty, ask the user: "Please provide your KamiClaw API key. Register at https://kamiclaw-skill.kamihome.com".cameras is empty, ask: "How many RTSP cameras do you want to monitor?"[ { "rtsp_url": "..." } ] — name will default to "default" automatically.front_door, backyard, living_room). Strongly recommend the user picks meaningful labels — they are shown in every alarm notification. Write [ { "name": "front_door", "rtsp_url": "..." }, { "name": "backyard", "rtsp_url": "..." } ].save_alarm_clips.config.json (read existing, merge, write back).python fall_detect_cloud_skill.py --list_cameras to confirm the resolved camera list.Never run with an empty api_key. Never run with cameras empty. When the user has multiple cameras, never accept missing/duplicate names — re-prompt until each camera has a unique label. Never ask the user to manually edit config.json.
| File | Content |
|---|---|
| ------ | --------- |
logs/app.log | Application log (rotates daily, keeps 30 days) |
logs/alarms.jsonl | All alarm events + clip analysis results |
logs/transitions.jsonl | All motion trigger events |
# Count alarms today
grep '"alarm"' logs/alarms.jsonl | grep "$(date +%Y-%m-%d)" | wc -l
# Transitions vs alarms (false positive rate)
wc -l logs/transitions.jsonl logs/alarms.jsonl
# Export alarms as CSV
cat logs/alarms.jsonl | python3 -c "
import sys, json
for line in sys.stdin:
obj = json.loads(line)
if obj.get('event') == 'alarm':
print(f\"{obj['_ts']},{obj.get('type','')},{obj.get('fall_type','')},{obj.get('confidence',0)},{obj.get('frame',0)}\")
"
| Issue | Solution |
|---|---|
| ------- | ---------- |
| No alarms detected | Check RTSP stream is active; verify camera angle covers monitoring area |
| Too many false alarms | Adjust camera position; reduce motion sensitivity area |
| API errors | Verify API key is valid; check internet connection |
| Stream disconnects | Check network stability; camera may need reboot |
kami-fall-detection/
├── SKILL.md # Documentation
├── config.json # Configuration (auto-managed by agent)
├── fall_detect_cloud_skill.py # Production entry point
├── setup.sh # Installer
└── requirements.txt # Dependencies
共 5 个版本