Было: tpl_3 = main + 2 preview + temp_chart (rs=4) + ha_chat.
При 4 active композитор выбирал tpl_3 (waste=1 vs tpl_4 waste=0 — wait,
tpl_3 имел 3 cam cells, при 4 active брал tpl_4=quad без виджетов).
Стало: tpl_3 = main + 3 preview + temp_chart (rs=2, низ-право) + ha_chat.
4 cam cells, при 4 active best-fit выбирает tpl_3 (waste=0, раньше в registry
чем tpl_4 → tie-breaker за tpl_3). Виджеты остаются видимыми.
Geometry validated: 36+4+4+4+4+12=64 микроячеек, no overlaps.
Hot-reloaded via reload_templates ZMQ в проде.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Conversation events HA Assist не приходят (архитектурное ограничение).
Чтобы placeholders ❯ Вы: ... и ✎ HA: ... не висели на экране без
данных — overlay'и убраны до решения вопроса с источником диалога.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Подписка на assist/conversation/text + /response (plain-text retained,
schema см. home-assistant/.../assist_mqtt.md).
Позиция: левый-нижний угол стопкой —
🤖 ответ внизу (margin_y=32)
🗣 вопрос выше (margin_y=78)
Полупрозрачная подложка (bg_alpha=180), placeholder с эмодзи пока
turn'а не было.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User: "смущает чёрная ячейка в сетке". Причина: asymmetric templates
имели widget cells (placeholder тёмно-серый Y=40) + при недостатке active
camera cells оставались BlankCell (чёрный).
Два изменения:
1. templates.json — оставили только 16:9 layouts (tpl_1/tpl_4/tpl_9/tpl_16).
Все camera-cells, никаких widget-областей. Cells full 16:9 (cs==rs
микроячейки), полностью покрывают output 1920×1080 без чёрных полос.
Asymmetric layouts (main + satellites) удалены — вернуть в Phase 12
когда widget'ы будут реальными (HA-chat, temperature graph).
2. composer::maybe_relayout — заполнить свободные camera-cells остальными
drawable камерами из pool (по priority), если template имеет больше
cells чем motion-active. Условие: cap > active.size().
Производство при 4 источниках в pool:
- 1 motion → tpl_1 (1 cell full screen)
- 2 motion → tpl_4 (2 motion + 2 not-active drawable = 4 cells заняты)
- 4 motion → tpl_4 (все 4 motion)
- При добавлении новых камер (до 16) — tpl_9 при 5..9, tpl_16 при 10..16
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Объединённое состояние работ:
- Phase 10: source pool, motion-driven layout, Frigate motion_pulse,
zone-filter в pool, --source / --motion-mode CLI
- Phase 11 Steps 1-3c: 8×8 микро-сетка, JSON templates с asymmetric
layouts (tpl_1/3/4/5/6/7/8), reload через ZMQ, auto-labels per camera
В прод отдеплоено и откачено: используем gx/cuframes-composer:0.10 как
baseline. Phase 11 продолжится в branch phase11b-cpp как C++ refactor
с ООП-моделью Cell/Layout/Decoration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Несколько сессий попыток реализовать audio mixing в композитор'е.
Не достигнуто sub-секундной latency со стабильным video+audio.
Откатано на parallel mode (cfc-grid video-only, live от pipeline с audio).
Полный набор выводов и pitfall'ов — docs/LESSONS-audio-mixing-attempts.md.
Главные lesson'ы для будущей попытки:
- mpegts mux libavformat авто-инсёртит h264_mp4toannexb BSF которому
не нравится Annex-B + inline SPS/PPS — NVENC OUTPUT_SPSPPS per-frame ломает
- SPSC ring drop newest при full, не oldest (consumer's domain)
- av_new_packet (не av_malloc) для av_interleaved_write_frame ownership
- Monotonic PTS на counter (frame_idx, total_samples) — не wallclock
- mediamtx env-var path names не должны иметь '-' (parser limitation)
- Default mediamtx ReadTimeout=10s короткий для burst write'ов
Изменения в repo сохранены для будущей доработки:
- src/writer.c — mpegts backend с audio stream support
- src/audio.c — RTSP AAC consumer + lock-free SPSC ring
- include/cuframes_composer/{writer,audio}.h — public API
- examples/grid_record.c — --format=mpegts + --audio-source flags
- include/cuframes_composer/composer.h — consumer_prefix field
- docker/Dockerfile — libavformat-dev добавлен в builder/runtime
cfc-grid composer стабильно работает на видео (substantially лучше
монолитного pipeline'а с audio bag'ом). TV рекомендуется использовать
rtsp://...:554/cfc-grid + опционально rtsp://...:554/live-audio
parallel.
netcat-openbsd добавлен в runtime layer (~50KB). HEALTHCHECK probe'ит
listening на 5599 (ZMQ control). Full functional ping через nc не сработает
(ZMTP требует binary greeting handshake), но liveness через TCP-проверку
достаточен для docker-compose restart-on-unhealthy логики.
Functional проверки делегированы external monitors:
- MQTT health uptime_s растёт = composer не зависает
- HA discovery sensor.composer_cfc-grid_active = camera-feed health
- Phase 7 (Prometheus) добавит composition_time_us / fps metrics
Live-validated: cfc-grid container статус 'healthy' через 25с после
recreate, healthcheck Log shows exit 0.
docker/Dockerfile — multi-stage build:
builder: nvidia/cuda:12.6.0-devel-ubuntu24.04 + apt build-deps + cmake
runtime: nvidia/cuda:12.6.0-runtime-ubuntu24.04 + apt runtime-deps
+ grid_record/simple_record + libcuframes.so.0 + libcuframes_composer.so.0
NVIDIA_DRIVER_CAPABILITIES=compute,utility,video в env image'а — обязательно
для NVENC dlopen libnvidia-encode.so.1.
docker/docker-compose.example.yml — образец для интеграции в
localhost-infra/hosts/R9-88.23/docker/cctv/. Два сервиса:
cfc-grid — композитор + control plane + MQTT health
cfc-grid-ffmpeg — pipe→RTSP push (использует существующий
ffmpeg-vf-cuda-grid image для совместимости glibc)
Сообщение в docs/docker/docker-compose.example.yml объясняет зависимости
(cuframes-ipc-anchor, cctv-mosquitto и т.д.) и нужный MQTT user.
Phase 6 deploy (intent перевести production):
- Создать MQTT user composer + добавить в localhost-infra mosquitto passwd
- Запустить cfc-grid параллельно с cuda-grid-pipeline (разные RTSP paths,
не конфликтуют)
- После проверки на проде — retire старый cuda-grid-pipeline
- Обновить TV-плейлисты на новый rtsp://...:554/cfc-grid
Эти шаги требуют отдельных commit'ов в localhost-infra repo с явным
user approval, поэтому здесь только prep.