mirror of
https://github.com/deadcxap/P2S_OSD.git
synced 2026-07-02 05:43:41 +03:00
main
Обновить README: добавить архитектурные варианты и план реализации OSD для Bambu P2S
P2S_OSD
Проект наложения телеметрии печати Bambu Lab P2S поверх RTSP-видеопотока камеры принтера.
Цель
Получить единый выходной видеопоток (для OBS/go2rtc/других клиентов), в котором уже «вклеены»:
- состояние принтера;
- данные задания печати;
- текущий слой и прогресс;
- параметры AMS (катушка, тип, цвет, слот);
- температуры (сопло, стол, камера);
- скорости вентиляторов и иные доступные метрики.
Ограничения:
- принтер в режиме
LAN-only+ включённыйDeveloper Mode; - взаимодействие по MQTT (как в OpenBambuAPI);
- входное видео по
rtsps://...:322/streaming/live/1; - работа без GPU (CPU-only);
- один Docker-контейнер;
- автозапуск без ручных команд после старта контейнера;
- читаемые логи;
- устойчивость при пропаже MQTT/RTSP;
- endpoint healthcheck для мониторинга.
Вариант 1 (рекомендуется): Python + GStreamer + Cairo/Pango OSD
Идея
Собрать сервис на Python, который:
- читает RTSP через GStreamer;
- рисует OSD-слой на кадре в пайплайне (
cairooverlay/textoverlay); - держит отдельный MQTT-клиент для статуса принтера;
- публикует выход как RTSP (через встроенный
gst-rtsp-server) или SRT/MPEG-TS; - поднимает HTTP endpoint
/healthzи/metrics.
Инструменты
python:3.12-slim;gstreamer1.0+-plugins-base/-good/-bad/-ugly;- Python-библиотеки:
paho-mqtt,fastapi/aiohttp,uvicorn,pydantic; gst-rtsp-server(через C-плагин в runtime, либо запуск отдельного процессаgst-rtsp-launch, но внутри того же контейнера).
Плюсы
- нативный real-time видеопайплайн;
- хорошая отказоустойчивость за счёт рестартуемых веток пайплайна;
- OSD рендерится без полного декод/энкод в Python-коде;
- удобная интеграция метрик и health endpoint.
Минусы
- сложнее в настройке GStreamer;
- нужно аккуратно подобрать кодек/битрейт CPU-only.
План реализации
- Каркас приложения
app/main.py(оркестратор),app/config.py,app/logging.py.
- MQTT-адаптер
- подключение к топикам Bambu;
- нормализация в единый
PrinterState.
- State Store
- thread-safe/async-safe store;
- TTL-поля (чтобы помечать устаревшие данные как
N/A).
- Видеопайплайн
- RTSP ingest → decode → overlay → encode (
x264enc ultrafast) → RTSP output.
- RTSP ingest → decode → overlay → encode (
- OSD layout
- несколько блоков: job, printer, temps, fans, AMS;
- fallback-текст при отсутствии данных.
- Resilience
- retry с backoff для MQTT и RTSP;
- watchdog пайплайна, автоматический re-init.
- Observability
- структурные логи JSON/текст;
/healthz(liveness/readiness),/metrics.
- Docker
ENTRYPOINTзапускает единый процесс-супервизор.
Вариант 2: Go + FFmpeg filtergraph (drawtext/overlay) + MQTT
Идея
Go-сервис получает MQTT-статус, генерирует текстовый OSD (или bitmap), а FFmpeg-процесс выполняет транскод и наложение через фильтры.
Инструменты
- Go 1.23+;
ffmpeg(libx264, drawtext);- MQTT-клиент (
eclipse/paho.mqtt.golang); - HTTP сервер (
chi/net/http) для health.
Плюсы
- проще найти специалистов по FFmpeg;
- один стабильный бинарь-оркестратор;
- предсказуемое поведение в Docker.
Минусы
drawtextобновляется через перезапись textfile/zmq-команды, что усложняет динамику;- сложнее сделать богатый UI (цветные блоки, иконки) без дополнительных костылей.
План реализации
- Go-daemon с подсистемами
mqtt,state,ffmpeg,health. - Генерация
osd.txt(atomic write) каждые 250–500 мс. - Запуск FFmpeg с
-vf drawtext=textfile=...:reload=1. - Выходной поток: RTSP push в локальный go2rtc (внутри контейнера) или прямой RTMP/SRT.
- Контроль процесса FFmpeg (перезапуск + throttling).
- Prometheus/health endpoints.
Вариант 3: Встроенный go2rtc + sidecar-процесс OSD внутри одного контейнера
Идея
В одном контейнере работают:
go2rtcкак универсальный ретранслятор;- отдельный OSD-процесс (Python/Go), который берёт исходный поток и публикует «обогащённый» поток обратно в go2rtc.
Несмотря на два процесса, это один контейнер, что соответствует требованию.
Плюсы
- сразу готовая интеграция с экосистемой go2rtc;
- удобно раздавать в разные протоколы (WebRTC/RTSP/HLS).
Минусы
- нужно корректно организовать процесс-менеджмент (s6/supervisord/tini + watchdog);
- сложнее отладка при циклической маршрутизации потоков.
План реализации
- Собрать image с
go2rtc+ OSD service. - Статический
go2rtc.yamlс входным потоком принтера и выходомstream_osd. - OSD service публикует в локальный ingest (
rtsp://127.0.0.1:8554/...). - Единый
/healthzагрегирует состояние обоих процессов. - Логи обоих процессов в stdout/stderr контейнера.
Рекомендуемая архитектура MVP
Для первого релиза: Вариант 1.
Почему:
- лучший баланс между гибкостью OSD и стабильностью в real-time;
- можно начать с простого текстового overlay и постепенно добавить графические элементы;
- проще контролировать reconnect-логику в одном коде.
MVP scope (итерация 1)
- вход RTSP;
- MQTT-подписка на базовые поля (status/progress/layers/temps);
- простое OSD (2 колонки);
- выход RTSP;
/healthzи/readyz;- Docker +
HEALTHCHECK; - устойчивый reconnect.
Итерция 2
- AMS-детализация (тип/цвет/слот);
- красивые плашки/цвета;
- экспорт метрик Prometheus;
- профили качества (low/medium/high CPU).
Структура репозитория (предложение)
.
├─ app/
│ ├─ main.py
│ ├─ config.py
│ ├─ logging.py
│ ├─ state/
│ │ ├─ models.py
│ │ └─ store.py
│ ├─ mqtt/
│ │ ├─ client.py
│ │ └─ parser.py
│ ├─ video/
│ │ ├─ pipeline.py
│ │ └─ overlay.py
│ └─ api/
│ └─ health.py
├─ Dockerfile
├─ docker-compose.example.yml
├─ .env.example
└─ README.md
Ключевые нефункциональные требования и как их закрыть
- Не падать при отсутствии коннекта
- бесконечный reconnect c exponential backoff;
- «деградированный режим» (OSD показывает
NO MQTT/NO VIDEO).
- Читаемые логи
- уровни
INFO/WARN/ERROR, correlation-id сессии подключения; - отдельные события
mqtt_connected,rtsp_disconnected,pipeline_restarted.
- уровни
- Автозапуск
ENTRYPOINT ["python", "-m", "app.main"];- никаких ручных post-start команд.
- Проверка работоспособности
/healthz(жив ли процесс);/readyz(есть ли свежие state/video за N сек).
- CPU-only
x264enc tune=zerolatency speed-preset=ultrafast;- ограничить fps/разрешение в конфиге.
Что подготовить перед кодированием
- список точных MQTT topic/payload полей (по OpenBambuAPI и фактическим payload вашего принтера);
- целевой формат выходного потока (RTSP/RTMP/WebRTC);
- допустимая задержка (например, ≤ 2–3 с);
- CPU-бюджет хоста (число vCPU).
После этого можно переходить к реализации MVP в этом репозитории.