# 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/] ''` | 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/.*connected' ``` 4. Тестовый publish: ```bash mosquitto_pub -h 192.168.88.4 -t '<твой topic>' -m 'test' -r ``` В логах composer'а должно появиться `[cfc/mqtt-overlay/] '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