Files
cuframes-composer/docs/ru/operations.md
T
gx e76360dbc4 docs: руководства пользователя / разработчика / operations (RU+EN)
Полный комплект документации к Phase 11b:

  docs/ru/user.md        — для админа инсталляции (motion-mode, PTZ,
                            templates.json, mqtt_overlays.json, ZMQ verbs)
  docs/ru/developer.md   — архитектура (Cell / Layout / Decoration),
                            как добавить новый Cell/Decoration, ABI shim,
                            algorithms (best-fit + asymmetric hysteresis)
  docs/ru/operations.md  — build (host + jammy + incremental bake),
                            deploy, logs/telemetry, troubleshooting
                            (broken pipe, MQTT-overlay, motion-mode)
  docs/en/*.md           — английская версия всех трёх
  README.md              — переписан с overview + ссылками на docs/

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 22:02:47 +01:00

405 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# cfc-grid — operations / deploy / troubleshooting
> Аудитория: тот кто билдит, деплоит, мониторит cfc-grid в проде.
>
> Если ты пользователь — см. [user.md](user.md). Если разработчик —
> см. [developer.md](developer.md).
## 1. Production setup (R9-88.23)
### 1.1 Стек
```
docker compose -f docker-compose.yml \
-f cuda-grid/docker-compose.override.yml \
-f cuframes-composer/docker-compose.override.yml \
-f onvif/docker-compose.override.yml \
up -d
```
Файлы — в `localhost-infra/hosts/R9-88.23/docker/cctv/`.
| Сервис | Image | Назначение |
|---|---|---|
| `cuframes-ipc-anchor` | `gx/cuframes:0.4` | Shared VMM IPC anchor для cuframes |
| `cuframes-pub-*` (parking/back_yard/front_yard/gate_lpr) | `gx/cuframes:0.4` | RTSP → cuframes per-camera publishers |
| `cuda-grid-mediamtx` | `bluenviron/mediamtx` | RTSP/HLS/WebRTC gateway |
| `cctv-mosquitto` | `eclipse-mosquitto` | MQTT broker (+bridge к 192.168.88.4) |
| **`cfc-grid`** | `gx/cuframes-composer:0.11b-step1` | Композитор (главный сервис) |
| `cfc-grid-ffmpeg` | `ffmpeg-vf-cuda-grid:phase4b-final` | H.264 pipe → RTSP push |
| `cfc-grid-watchdog` | `gx/cuda-grid-watchdog:0.4` | Restart cfc-grid при stuck inboundBytes |
| `cctv-onvif` | `gx/cctv-onvif:0.6` | ONVIF discovery + PTZ → ZMQ |
| `cctv-frigate` | `ghcr.io/blakeblackshear/frigate` | Object detection → MQTT events |
### 1.2 Поток кадров
```
cuframes-pub-X ──VMM──┐
cuframes-pub-Y ──VMM──┼──→ cfc-grid (composer)
cuframes-pub-Z ──VMM──┘ │
│ H.264 NVENC
↓ named pipe /tmp/cfc-pipe-dir/grid.h264
cfc-grid-ffmpeg (re-mux)
│ RTSP push
cuda-grid-mediamtx
rtsp://*/cfc-grid (TCP/UDP)
http://*:8888/cfc-grid (HLS)
http://*:8889/cfc-grid (WebRTC)
```
### 1.3 Сети
- Внутренний docker network: `cctv`
- Внешние порты на R9-88.23:
- `554/tcp` — RTSP (mediamtx)
- `8888/tcp` — HLS (mediamtx)
- `8889/tcp` — WebRTC (mediamtx)
- `5599/tcp` — ZMQ control plane composer'а
- `8085/tcp` — ONVIF SOAP (cctv-onvif)
- `3702/udp` — WS-Discovery multicast (cctv-onvif)
## 2. Build
### 2.1 Local host build (Ubuntu 24.04, dev машина)
```bash
cd /home/claude/projects/cuframes-composer
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
```
Артефакты в `build/src/libcuframes_composer.so` и `build/examples/grid_record`.
**ВАЖНО:** host'овый бинарь (Ubuntu 24.04, glibc 2.39, libavformat60)
**несовместим** с runtime контейнером (Ubuntu 22.04 jammy, glibc 2.35,
libavformat58). См. memory `incremental-ffmpeg-rebuild`.
### 2.2 Jammy build (для production image)
Использует кешированный builder-контейнер `cuframes-composer-builder:cached`
(Ubuntu 22.04 + nvidia/cuda:12.4.1-devel + apt-deps):
```bash
cd /home/claude/projects/cuframes-composer
# Если builder ещё не закеширован:
docker image inspect cuframes-composer-builder:cached >/dev/null 2>&1 || {
docker run -d --name cfc-builder-tmp \
nvidia/cuda:12.4.1-devel-ubuntu22.04 sleep 3600
docker exec cfc-builder-tmp bash -c '
apt-get update -qq && apt-get install -y -qq --no-install-recommends \
build-essential cmake git pkg-config \
libpng-dev libfreetype-dev \
libzmq3-dev libjson-c-dev libmosquitto-dev \
libavformat-dev libavcodec-dev libavutil-dev'
docker commit cfc-builder-tmp cuframes-composer-builder:cached
docker rm -f cfc-builder-tmp
}
# Сам build:
docker run --rm --gpus all -v "$PWD":/src -w /src/build-jammy \
cuframes-composer-builder:cached \
bash -c 'cmake -DCMAKE_BUILD_TYPE=Release .. && make -j$(nproc)'
```
Артефакты в `build-jammy/`.
### 2.3 Bake image (incremental — без `docker build`)
Не используем `docker build` (4GB CUDA pull при cache miss). Вместо:
```bash
docker rmi gx/cuframes-composer:0.11b-step1 -f 2>/dev/null
CID=$(docker create gx/cuframes-composer:0.10)
docker cp build-jammy/examples/grid_record "$CID":/usr/local/bin/grid_record
docker cp build-jammy/src/libcuframes_composer.so.0.1.0 \
"$CID":/usr/lib/x86_64-linux-gnu/libcuframes_composer.so.0
docker cp docker/templates.json "$CID":/opt/templates.json
docker cp docker/mqtt_overlays.json "$CID":/opt/mqtt_overlays.json
docker commit \
--change 'ENTRYPOINT ["/usr/local/bin/grid_record"]' \
--change 'CMD ["--help"]' \
--change 'ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility,video' \
"$CID" gx/cuframes-composer:0.11b-step1
docker rm "$CID"
```
Использует базу `gx/cuframes-composer:0.10` (с уже установленными runtime
deps) + накладывает свежие артефакты. Быстрее и без сетевого трафика.
### 2.4 Build ONVIF image
```bash
cd hosts/R9-88.23/docker/cctv/onvif
docker build -t gx/cctv-onvif:0.6 -f Dockerfile .
```
Python image, лёгкий. Если меняешь `server.py` — rebuild image (тег
поднимать) + правишь image в `docker-compose.override.yml`.
## 3. Deploy
### 3.1 Прод (R9-88.23)
```bash
cd /home/claude/projects/localhost-infra/hosts/R9-88.23/docker/cctv
docker compose -f docker-compose.yml \
-f cuda-grid/docker-compose.override.yml \
-f cuframes-composer/docker-compose.override.yml \
-f onvif/docker-compose.override.yml \
up -d cfc-grid
```
Compose автоматически recreate'нет контейнер если image tag поменялся в
`docker-compose.override.yml`.
### 3.2 Verify post-deploy
```bash
# Logs композитора
docker logs --tail 30 cfc-grid 2>&1 | grep -iE "loaded|template|pool|motion"
# Ожидаем что-то типа:
# [cfc/loader] /opt/templates.json: loaded 9 templates
# [cfc/composer] templates loaded: 9 (path='/opt/templates.json')
# [cfc/composer] pool+ 'cam-parking' (frigate=parking_overview prio=100)
# [cfc/composer] motion_mode=1 ttl=45000ms pool=4
# [cfc/composer] grow → template='tpl_3' active=3
```
### 3.3 Rollback
```bash
sed -i 's|gx/cuframes-composer:0.11b-step1|gx/cuframes-composer:0.10|' \
hosts/R9-88.23/docker/cctv/cuframes-composer/docker-compose.override.yml
docker compose ... up -d cfc-grid
```
## 4. Logs
### 4.1 Live tail
```bash
docker logs -f --tail 50 cfc-grid
docker logs -f --tail 30 cfc-grid-ffmpeg
docker logs -f --tail 30 cuda-grid-mediamtx
docker logs -f --tail 30 cctv-onvif
docker logs -f --tail 30 cctv-frigate
```
### 4.2 Telemetry pattern
| Маркер | Что значит |
|---|---|
| `[grid_record] N кадров, M IDR, X МБ за Y.0с (25.0 fps)` | Composer успешно encode'ит каждые ~50 кадров |
| `[cfc/composer] grow → template='X'` | Применился новый template (расширение, мгновенно) |
| `[cfc/composer] shrink → template='X'` | Применился новый template после hysteresis (сжатие) |
| `[cfc/composer] manual override 'X' до +60000ms` | PTZ через ONVIF |
| `[cfc/composer] manual override expired, возврат в motion-mode` | Auto-возврат после 60s |
| `[cfc/mqtt-overlay/<id>] '<text>'` | MQTT-overlay получил/отрендерил новый text |
| `[cfc/frigate] connected, subscribe 'frigate/events'` | Frigate-subscriber подключился |
| `[cfc/temp] update: 'XX.X°C'` | (старый код, deprecated — теперь mqtt-overlay) |
### 4.3 Когда что-то сломалось
| Симптом | Где искать |
|---|---|
| `src active=0 stale=0 dead=4` | cuframes-pub-* контейнеры; проверь `docker ps` и сетевой доступ к камерам |
| `overlay 0 draw failed` | `cfc_overlay_text_rebuild_atlas` — обычно невалидный шрифт или текст |
| RTSP стрим не отдаёт | `cfc-grid-ffmpeg` логи; смотри §6.1 |
| TV/ONVIF не находит | `cctv-onvif` логи; проверь multicast WS-Discovery в LAN |
## 5. Monitoring
### 5.1 MQTT health
`cfc-grid` публикует health в `cuda_grid/health/composer/cfc-grid`
каждые ~10 секунд:
```json
{
"uptime_s": 3600,
"frames_encoded": 90000,
"fps_actual": 25.0,
"bitrate_kbps": 6000,
"src_active": 4,
"src_stale": 0,
"src_dead": 0,
"idr_count": 1
}
```
```bash
PW=$(grep '^COMPOSER_MQTT_PASSWORD=' \
/home/claude/projects/localhost-infra/hosts/R9-88.23/docker/cctv/.env | cut -d= -f2)
mosquitto_sub -h 192.168.88.23 -u composer -P "$PW" \
-t 'cuda_grid/health/composer/cfc-grid' -v
```
### 5.2 Watchdog
`cfc-grid-watchdog` — отдельный сервис, мониторит mediamtx
`inboundBytes` для пути `cfc-grid`. Если **30 секунд молчания**
`docker restart cfc-grid`.
Логи watchdog'а:
```bash
docker logs --tail 30 cfc-grid-watchdog
```
При срабатывании — публикует в `cuda_grid/health/watchdog/cfc-grid`.
## 6. Troubleshooting
### 6.1 RTSP не отдаёт / `cfc-grid-ffmpeg` в "Broken pipe"
**Симптом:** `docker logs cfc-grid-ffmpeg` показывает
`[out#0/rtsp] Task finished with error code: -32 (Broken pipe)`.
**Причина:** `--intra-refresh` в composer'е (без IDR-burst'ов), mediamtx
рвёт RTSP-publisher если не может отдать новому клиенту start-frame.
**Лечение:**
- Полный restart pipeline:
```bash
docker compose ... restart cfc-grid-ffmpeg cfc-grid cuda-grid-mediamtx
```
- Если повторяется — отключить `--intra-refresh` в compose override
(стоимость: IDR-bursts в bitrate, но стабильнее для downstream
клиентов с frequent disconnect/reconnect)
### 6.2 ffmpeg не получает кадры от RTSP
**Симптом:** при `ffmpeg -i rtsp://192.168.88.23:554/cfc-grid -frames:v 1 out.jpg`
зависает на 30+ секунд.
**Причина:** Composer пишет H.264 без regular IDR (intra-refresh). Новый
RTSP-клиент ждёт keyframe для старта декодинга. ffmpeg в default
конфигурации не ждёт достаточно долго.
**Workaround:**
```bash
ffmpeg -rtsp_transport tcp \
-analyzeduration 10000000 -probesize 10000000 \
-i rtsp://192.168.88.23:554/cfc-grid \
-frames:v 1 -y out.jpg
```
Или используй HLS:
```bash
ffmpeg -i http://192.168.88.23:8888/cfc-grid/index.m3u8 \
-frames:v 1 -y out.jpg
```
### 6.3 MQTT-overlay не обновляется
**Чек-лист:**
1. Бридж к HA broker (192.168.88.4) работает?
```bash
docker logs cctv-mosquitto 2>&1 | grep -i 'bridge'
```
Ищи `Connecting bridge ha-bridge` и подтверждение connect.
2. Нужный topic в bridge config?
```bash
docker exec cctv-mosquitto grep 'topic.*in 0' /mosquitto/config/mosquitto.conf
```
Если новый префикс — добавь `topic XXX/# in 0` и restart mosquitto.
3. Subscriber подключился?
```bash
docker logs cfc-grid 2>&1 | grep 'mqtt-overlay/<id>.*connected'
```
4. Тестовый publish:
```bash
mosquitto_pub -h 192.168.88.4 -t '<твой topic>' -m 'test' -r
```
В логах composer'а должно появиться `[cfc/mqtt-overlay/<id>] 'test'`.
### 6.4 Motion-mode не переключает layout
**Чек-лист:**
1. Frigate шлёт events?
```bash
mosquitto_sub -h 192.168.88.23 -u composer -P "$PW" \
-t 'frigate/events' -C 3
```
2. Composer получает events?
```bash
docker logs cfc-grid 2>&1 | grep 'frigate.*started\|grow\|shrink'
```
3. Camera-name матчится?
`frigate=<имя>` в `--source` должно совпадать с `event.after.camera`.
4. Zone-filter не отсекает?
Если `zones=A:B:C` в `--source` — посмотри в Frigate event
`current_zones`. Если пусто или не пересекается — pulse отбрасывается.
5. TTL не истёк?
Logs `motion_ttl=45000` (45 сек) — если события приходят реже —
камера выпадает из active.
### 6.5 ONVIF PTZ presets пусты в TV
**Причина:** TV закешировал старый ответ `GetPresets` (Phase 9 имена).
**Лечение:** удалить и заново добавить камеру в TV-клиенте.
### 6.6 Templates загрузились но motion-mode не использует новый
Composer читает global registry `cfc::current_templates()` на каждом
кадре — изменение через `cfc_layout_load_file` (ZMQ или CLI) должно
быть подхвачено сразу. Если нет — проверь:
```bash
echo '{"cmd":"list_layouts"}' | python3 -c "
import zmq,json,sys
s = zmq.Context().socket(zmq.REQ)
s.connect('tcp://192.168.88.23:5599')
s.send_json({'cmd':'list_layouts'})
print(json.dumps(s.recv_json(), indent=2, ensure_ascii=False))"
```
Поле `source` показывает текущий загруженный path. Если built-in (только
`tpl_1` + `tpl_4`) — JSON не подгрузился (syntax error, кривой path).
## 7. Конфиги в репо
| Что | Где |
|---|---|
| templates.json | `cuframes-composer/docker/templates.json` |
| mqtt_overlays.json | `cuframes-composer/docker/mqtt_overlays.json` |
| compose override | `localhost-infra/hosts/R9-88.23/docker/cctv/cuframes-composer/docker-compose.override.yml` |
| ONVIF config | `localhost-infra/.../onvif/onvif.yaml` |
| ONVIF server | `localhost-infra/.../onvif/server.py` |
| Mosquitto config | `localhost-infra/.../cctv/mosquitto/config/mosquitto.conf` |
| .env (passwords) | `localhost-infra/.../cctv/.env` (gitignored) |
После изменения compose override — `docker compose ... up -d cfc-grid`
автоматически recreate'нет.
## 8. Известные ограничения / TODO
- **`--intra-refresh` ↔ RTSP-clients**: trade-off bitrate vs latency
(см. §6.1)
- **Watchdog только cfc-grid**: cfc-grid-ffmpeg в зомби-state не
детектится напрямую; помогает только полный restart
- **Hot-reload mqtt_overlays.json**: нет ZMQ verb'а
- **MQTT-overlay per-broker config**: всё через один broker; для
внешнего broker'а нужно расширить `MqttBrokerCfg` per-item
## 9. См. также
- [user.md](user.md) — настройка композитора
- [developer.md](developer.md) — внутренности, добавление модулей
- `memory/host-and-project.md` — общая инфра R9-88.23
- `memory/project_cfc-grid-deployed.md` — deploy 1-го прода
- `memory/project_cfc-grid-cpp-refactor.md` — Phase 11b refactor
- `memory/incremental-ffmpeg-rebuild.md` — incremental docker recipe