Перейти до змісту

Трансляція камери

Візуально спостерігайте за друком через живу трансляцію камери безпосередньо з вашого принтера Bambu Lab.


Жива трансляція

BamDude забезпечує MJPEG-відеотрансляцію з вбудованої камери принтера або зовнішньої мережевої камери.

Відкриття камери

  1. Натисніть іконку камери на картці принтера
  2. Оберіть між оверлей-режимом або окремим вікном (налаштовується в Параметрах)
  3. Трансляція починається автоматично

Елементи керування

Кнопка Дія
Live Відеотрансляція MJPEG у реальному часі
Snapshot Одне статичне зображення (менше навантаження)
Перезапустити трансляцію
Повноекранний режим

Стіна камер (Camera Wall)

Сторінка Printers має два макети, що перемикаються тумблером Cards / Cam wall у заголовку сторінки. Cam wall замінює картки принтерів адаптивною сіткою камер-тайлів — один погляд на всі камери ферми.

Щоб економити трафік і ffmpeg-процеси, стіна стрімить розумно, а не відкриває всі камери відразу:

  • Живими йдуть лише тайли на екрані. IntersectionObserver позначає тайл "видимим", щойно ≥40% його на екрані — поріг 40% не дає смужці на межі скролу підняти стрім.
  • Live обмежено протоколом браузера. Збережене налаштування max live має дефолт 4. Для HTTP/1.x чи невідомого протоколу діє максимум 2 живі потоки у вкладці, спільно зі спливною камерою. Підтверджений HTTP/2 чи HTTP/3 дозволяє обраний максимум (до 16). Решта видимих тайлів показують знімки; поза екраном — пауза. UI пояснює нижчий фактичний ліміт, не змінюючи збережене налаштування.
  • Решта — snapshot-и. Тайли понад кап оновлюють один кадр кожні 8 секунд за замовчуванням (налаштування snapshot interval).
  • Тайли поза екраном паузяться. Прокрути тайл за межі видимості — і він припиняє будь-яку мережеву активність до повернення. Відключені принтери теж рендеряться в паузі — жоден live-слот не витрачається на камеру, якій нічого стрімити.

Протокол береться із завершених API-запитів браузера, включно з його з’єднанням до reverse proxy. Сам HTTPS не доводить HTTP/2. Якщо браузер не дає даних про протокол, лишається ліміт два. Окремі вкладки/вікна не ділять цей frontend-бюджет; це не глобальна гарантія кількості з’єднань у браузері.

Знімки ділять чергу з двох запитів, скасовуються при виході та зберігають останню картинку, доки приходить нова. Час унизу праворуч — успішне оновлення знімка в цій вкладці, а не час захоплення на принтері. При помилці попередній кадр лишається, оновлення повторюється. Для живого відео лишається бейдж НАЖИВО.

Per-tile

Кожен тайл показує:

  • offline-чіп, коли принтер не підключений;
  • опційний status overlay — off, компактний state chip або full з прогресом %, лічильником шарів і залишком часу на тайлах, що друкують/на паузі;
  • HMS-error badge, коли в принтера активні (не-шумові) HMS-помилки;
  • клік відкриває цю камеру у твоєму preferred-переглядачі — embedded-оверлей чи окреме вікно, згідно з налаштуваннями Camera. У повному оверлеї залогіненої стіни назва завдання бере перше наявне значення: підзадачу принтера, назву поточного друку, а потім ім'я завантаженого файлу — тайл не лишається анонімним, коли firmware не надсилає одне з полів.

Налаштування стіни

Кнопка-шестерня на стіні відкриває per-browser налаштування: max live (1–16), snapshot interval (2–60 с) і режим status overlay (off / compact / full). Усі три зберігаються в local storage браузера — вони per-device, не синхронізуються з акаунтом, бо на Pi 4 живий кеп нижчий, ніж на NUC.

Дозвіл

Тумблер Cam wall потребує дозволу camera:view — того самого, що й переглядач камери. Без нього тумблер неактивний.

Спільні стріми, більше жодних заморожених тайлів

Кожен переглядач принтера — cam-wall тайл, embedded-оверлей, popup-вікно — підписаний на один спільний fan-out стрім. Закриття одного переглядача більше не морозить інший: стрім розбирається лише коли відключився останній переглядач.


Зовнішні камери

Підключай зовнішні мережеві камери замість вбудованої камери принтера. Корисно для кращих кутів, вищої роздільної здатності або принтерів у бокс-корпусах, де вбудована частково перекрита.

Підтримувані типи

Тип Приклад URL/шлях
MJPEG http://192.168.1.50/mjpeg
RTSP rtsp://192.168.1.50:554/stream
Snapshot http://192.168.1.50/snapshot.jpg
USB (V4L2) /dev/video0

Конфігурація

  1. Settings → General → Camera.
  2. Знайди свій принтер у секції External Cameras.
  3. Перемкни switch для увімкнення.
  4. Введи URL камери.
  5. Обери Type.
  6. Натисни Test — BamDude відкриває стрім один раз, підтверджує кадр і відключається.

RTSP-авторизація

Креденшали в URL: rtsp://user:[email protected]:554/stream.

go2rtc та IP-камери: warm-up-frame skip + Snapshot URL override

Багато MJPEG-джерел — особливо go2rtc, плюс ряд IP-камер — видають "warm-up" / часто чорний кадр на байті відразу після прийняття з'єднання (останній keyframe з енкодера до того, як він наздожене реальний live-контент). Починаючи з 0.4.4 BamDude читає повз перший кадр і повертає другий на всіх шляхах захоплення single-frame (notification thumbnails, finish photo, layer-timelapse, plate detection, Obico inference). Повільні / single-frame стріми, які не доставляють другий кадр у таймаут, падають на перший — щоб caller завжди отримав щось. Без додаткового налаштування.

Опційно: Snapshot URL override. Для типів MJPEG, RTSP і USB можна додатково заповнити окремий Snapshot URL під live-stream URL. Коли заданий, BamDude тягне single-frame захоплення (notification thumbnails, finish photo, layer timelapse, plate detection, Obico inference) з нього через plain HTTP GET — повністю обходячи warm-up-frame dance. Корисно для go2rtc-сетапів (http://<host>:1984/api/frame.jpeg?src=<name> — спеціалізований single-frame ендпоінт, який ніколи не повертає stale keyframe з енкодера) чи IP-камер зі snapshot-ендпоінтом типу /snapshot.jpg. Натисни Test поряд зі Snapshot URL для перевірки. Live-view стрім завжди йде через основний URL; override змінює тільки single-frame захоплення (опитувати snapshot-ендпоінт 1 fps для live-view було б регресом для тих, у кого нема цієї проблеми). Прихований коли тип камери = Snapshot — live URL уже single-frame, override був би зайвим. Залиш порожнім — буде використано warm-up-frame skip на live-стрімі.

USB / V4L2 setup

USB-вебкамери працюють через V4L2 на Linux-хостах:

# Інсталяція тулзів для лістингу пристроїв
sudo apt install v4l-utils

# Перелік відеопристроїв
v4l2-ctl --list-devices

BamDude читає /dev/video0 за замовчуванням. Якщо камера на іншому ноді (наприклад, /dev/video2), введи шлях прямо в поле URL зовнішньої камери.

Для Docker — пробрось пристрій:

services:
  bamdude:
    devices:
      - /dev/video0:/dev/video0

Layer-Based Timelapse (тільки зовнішні камери)

Коли увімкнено зовнішню камеру і принтер публікує per-layer-change MQTT-події, BamDude автоматично:

  1. Захоплює кадр на кожен інкремент шару друку.
  2. Зберігає кадри у тимчасовій директорії під час друку.
  3. Стічить відео через ffmpeg на завершенні друку.
  4. Прикріплює результуючий timelapse до архіву друку.

Тільки зовнішні камери

Layer-based timelapse працює лише з зовнішніми камерами (MJPEG, RTSP, Snapshot або USB). Вбудовані камери принтерів використовують власну timelapse-фічу принтера — він стічить сам, і BamDude просто прикріплює готовий MP4/AVI.

ffmpeg обов'язковий

Layer-timelapse потребує ffmpeg (включений у Docker-образ BamDude; на bare metal — apt install ffmpeg).

Це продукує помітно якісніший timelapse за fixed-interval capture, бо кожен кадр відповідає чистому стану друку (голова припаркована поза деталлю, між шарами).


Поворот камери

Налаштування Rotation на кожен принтер (0 / 90 / 180 / 270, у налаштуваннях камери принтера) — для камери, фізично встановленої під кутом.

Воно застосовується до всього, що BamDude робить із цієї камери:

Результат Повертається
Знімок для сповіщення
Кадри layer-timelapse — повертаються під час захоплення, до складання відео
Фінальне фото, з будь-якого з п'яти джерел: заздалегідь захоплений кадр, зовнішня камера, вже відкритий live-перегляд, свіжий грабіж кадру або кадр, відновлений із власного timelapse-відео принтера
Власне timelapse-відео принтера

Чому власне timelapse-відео принтера не чіпаємо

Воно лишається точно таким, яким його записав принтер: повернути готове відео означає перекодувати його. Випрямляється лише кадр, витягнутий із нього, — тож фінальне фото збігається з рештою зображень, а відео лишається недоторканим.

Кадр, уже повернутий при захопленні, вдруге ніколи не повертається.


Одна камера — один читач

Прошивка принтера Bambu дозволяє рівно одне з'єднання з камерою, а USB-камера — рівно один V4L2-хендл. Захоплення, що конкурує з іншим читачем, не деградує — воно падає.

BamDude тримає це за двома осями:

  • Фонове захоплення проти глядача. Поки хтось дивиться live-перегляд, кожен фоновий споживач — layer timelapse, фінальне фото, AI-детекція збоїв, перевірка столу, знімки для сповіщень — перевикористовує кадр із live-перегляду, замість відкривати власне з'єднання. Для вбудованої камери принтера так було завжди; тепер зовнішні камери публікують свої кадри так само. До того перегляд зовнішньої камери під час друку означав, що layer timelapse записував майже нічого, а фінальне фото приходило порожнім.
  • Фонове захоплення проти фонового захоплення. Коли не дивиться ніхто, кожен споживач справедливо доходив висновку, що ні з ким не конкурує, — і відкривав власне з'єднання рівно в ту саму мить, що й наступний. Двох захоплень із різницею 207 мс вистачало, щоб покласти працюючий стрім camera wall. Тепер одночасні захоплення ділять одне з'єднання: перше відкриває його, решта чекають на той самий кадр.

Воно об'єднує, але не кешує

Захоплення, що прийшло після завершення спільного, все одно бере свіжий кадр. Детекція столу й фінальне фото роблять висновки про друк, що триває, саме з цих зображень, і застарілий кадр гірший за повільний — фінальне фото з уже опущеним столом є саме тим збоєм, якого це уникає.


Експериментальний ізольований процес камери

Стандартний runtime inline виконує camera transport у процесі сервера BamDude. Досвідчені оператори можуть перед запуском сервісу встановити змінну середовища:

CAMERA_RUNTIME=worker

Вона запускає один supervised локальний дочірній процес для роботи камери. One-shot capture, built-in Bambu chamber/RTSPS live view та зовнішні live MJPEG, RTSP і snapshot проходять через автентифікований локальний JPEG relay; browser URL, токени й звичайна поведінка спільного перегляду не змінюються. Якщо browser relay відвалився, producer у дочірньому процесі звільняється, а не лишає камеру чи ffmpeg відкритими. Relay приймає не більше 64 активних джерел і відкидає JPEG понад 2 MiB: черги live-кадрів обмежені 128 MiB на процес.

Експериментально: перевірте перед production-фермою

worker працює fail-closed. Якщо containment процесу або локальне з'єднання не стартує, BamDude не перемикає запит назад на inline transport. Built-in Bambu live view теж належить worker; його RTSPS шлях бере той самий profile моделі для probe і reconnect, що й inline view. Virtual Printer camera passthrough — worker-owned byte-for-byte raw TCP lease. Лишайте inline за замовченням, якщо не перевірили camera і Virtual Printer paths на своєму хості.

Налаштування не замінює hardware test. Camera firmware, Wi-Fi, ffmpeg і поведінка hardware decoder залежать від хоста та моделі камери.


Перезапуск та діагностика за INFO-логами

Додайте змінну в середовище запуску бекенда (або його .env) та перезапустіть BamDude. Видалення змінної або CAMERA_RUNTIME=inline діє після наступного перезапуску. У dev-режимі reloader може додати Python-процес запуску: дивіться worker-ready записи та PID дочірнього процесу, а не лише загальну кількість Python.

Звичайний лог бекенда містить запуск/завершення воркера, приєднання/від’єднання глядачів, початок/перший кадр/завершення relay та метрики завершених сесій. Принтер і поля session/identity зв’язують записи бекенда з дочірнім процесом. Час першого кадру й кількість кадрів описують доставку до бекенда, а не доказ відмальовування браузером. viewers_gone після закриття — нормально. subscribers=0 підтверджує відсутність глядачів цього relay; інший глядач закономірно лишає спільне джерело активним.

Поточний лог можна скачати в Інформації про систему. Для такої базової діагностики DEBUG не потрібен. Пересилання логів воркера обмежує розмір і частоту записів та приховує credentials/URL; кожен відеокадр не логується. Передаючи лог підтримці, додайте час проблеми й назву принтера. Ізоляція сама не вмикає VAAPI/ D3D11 і не усуває обмеження з’єднань HTTP/1 у браузері.


Масштабування та панорамування

Метод Дія
Коліщатко миші Збільшення/зменшення (100% - 400%)
Клік і перетягування Панорамування при збільшенні
Жест щипка Масштабування на сенсорному пристрої

Технічні деталі

graph LR
    A[Камера принтера] -->|RTSP| B[ffmpeg]
    B -->|MJPEG| C[BamDude API]
    C -->|HTTP Stream| D[Браузер]
Вимога Деталі
ffmpeg Має бути встановлений (включений у Docker-образ). Потрібен для RTSP-камери серій X1 / X2 / H2 / P2; протокол chamber-image (A1 / P1) його не використовує.
Камера увімкнена Має бути увімкнена в налаштуваннях принтера
Режим розробника Необхідний для доступу до камери

Вказати ffmpeg — FFMPEG_PATH

Якщо ffmpeg встановлений, але не в PATH запущеного сервісу — найчастіше свіже встановлення на Windows, чия зміна PATH не дійшла до вже відкритої консолі — RTSP-камера (X1 / X2 / H2 / P2) конектиться, але кадрів нема. Задай FFMPEG_PATH у .env (або в оточенні) — повний шлях до бінаря ffmpeg, і BamDude візьме його напряму, без пошуку по PATH:

FFMPEG_PATH=C:/Users/you/AppData/Local/Microsoft/WinGet/Packages/Gyan.FFmpeg_.../bin/ffmpeg.exe

Якщо не задано — поведінка незмінна (пошук у PATH + типових локаціях). Docker-образ і нативні інсталери містять ffmpeg, тож це зазвичай потрібно лише для локальної розробки на Windows.


OBS-оверлей

BamDude включає оверлей для стрімів за адресою /overlay/{printer_id}, що поєднує відео з камери зі статусом друку в реальному часі. Авторизація не потрібна.

Налаштування через параметри запиту: ?size=large&fps=30&show=progress,eta,filename


Stream-токен як шлюз

Camera-ендпоінти (live-стрім, snapshot, cover-мініатюра, plate-detection reference) не дружать з Bearer-токеном -- тег <img src> не може причепити заголовок Authorization. BamDude натомість пропускає їх через короткоживучий query-param токен:

  1. Фронт стукає в POST /api/v1/printers/camera/stream-token, щоб отримати токен, прив'язаний до поточного користувача (TTL 60 хв).
  2. Токен дописується як ?token=... до кожного camera-URL через withStreamToken() в API-клієнті.
  3. Уже відрендерені DOM-вузли (наприклад, <img>, змонтований до приходу токена) ретрофітяться через rewriteMediaSrcWithToken().
  4. Токен у React-Query кешується по user.id, тож логін/логаут інвалідує кеш.

Токени зберігаються в auth_ephemeral_tokens, тож переживають перезапуски бекенда і працюють під багатоворкерними деплоями. Операторам нічого робити не треба -- це невидима сантехніка -- але наслідок такий: copy-paste camera-URL з браузера працює лише на час життя вшитого токена.

Довготривалі токени для Home Assistant / Frigate / kiosk / OBS

60-хвилинний токен інтерфейсу має неправильну форму для настінної панелі, сутності камери в Home Assistant чи фронтенду Frigate, який місяцями смикає той самий URL. Для таких випадків BamDude випускає довготривалі токени.

Налаштування → API-ключі → Токени камер і монітора → Створити новий токен. Дай назву, обери область дії (нижче) і час життя (1–365 днів, типово 90), тоді натисни «Створити». Токен показується рівно один раз.

Показується лише раз

BamDude зберігає тільки pbkdf2-хеш, тож відкритий текст неможливо отримати вдруге — а вкрадений дамп бази не можна відтворити проти ендпоінтів камери. Якщо загубив токен — відклич рядок і створи новий.

Області дії

Кожна область — окремий грант. Вони ніколи не розширюють одна одну, і створення однієї ніколи не змінює того, що вміє вже наявний токен.

Область Дає доступ до
Лише потік камери Ендпоінти потоку та знімка камери, і більше нічого. Правильний вибір для Home Assistant, Frigate чи будь-чого, що вбудовує одну камеру.
Стіна камер Ті самі потоки плюс read-only фід Стіни камер: назва кожного принтера, стан з'єднання і прогрес друку — але ніколи ім'я файлу.
Оверлей для стріму Потік камери одного принтера плюс живий статус друку, який малює оверлей OBS — і він таки містить ім'я файлу на екрані.

Межі навмисні й перевіряються в обидва боки: токен «лише потік» відхиляється і фідом Стіни камер, і фідом оверлея; токен Стіни камер відхиляється фідом оверлея (стіні довіряють ніколи не називати деталь на столі, тож об'єднання мовчки розширило б кожен уже виданий токен стіни) — і навпаки. Жоден з них не відкриває IP-адресу принтера, серійний номер чи код доступу і не дістає жодного іншого API BamDude.

Монітор стану — окрема область лише для операційних даних у тій самій панелі. Вона відкриває екран оператора для всіх неархівних принтерів, без камер, назв файлів чи керування. Цей токен не працює для камер, а камерні області не відкривають монітор стану.

Властивості токена

Властивість Деталі
Формат bblt_<prefix>_<secret>. 8-символьний prefix індексований, щоб пошук не сканував таблицю; він же дозволяє розрізняти рядки в інтерфейсі, коли забув, який пристрій який токен тримає.
Зберігання Таблиця long_lived_tokens, окремо від 60-хвилинних браузерних токенів — ефемерний sweeper їх не чіпає.
Хешування pbkdf2_sha256 по всьому токену, так само як решта хешування паролів у кодовій базі.
Максимальний строк 365 днів. «Ніколи не спливає» відхиляється навмисно: витеклий вічний токен був би невідкличною міною. Ротуй щороку в межах звичайної гігієни облікових даних.
Аудит last_used_at проставляється на кожному успішному використанні (не частіше разу на хвилину, щоб MJPEG keep-alive не бив по базі). Токени без активності 30+ днів отримують попереджувальний чип.
Відкликання Діє з наступного запиту — жодного кешу чекати не треба.
Обсяг токена Усі принтери. Ці токени не звужуються до конкретного принтера; токен «лише потік» витягне потік будь-якого. Якщо потрібне звуження — використовуй API-ключі.

Адміністратори бачать додаткову секцію Усі користувачі з переліком усіх активних токенів інсталяції — стане в пригоді, якщо є підозра на витік, або для загальнофермової гігієни.

Камерні області потребують camera:view та дозволу API-ключів для відповідної дії: api_keys:create, api_keys:read або api_keys:delete. Доступ до інтерфейсу Налаштувань також потребує settings:read. Для токена Монітор стану разом із правами API-ключів потрібне читання принтерів і черги; доступ до камер не потрібен. Дивіться посібник налаштування монітора.

Форма URL: /api/v1/printers/{id}/camera/stream?token=<токен> — той самий контракт query-параметра, що й у короткоживучого потоку, тож generic camera platform у Home Assistant, mjpeg_streams у Frigate чи звичайний <img src> працюють без додаткової сантехніки.

Стіна камер на телевізорі чи kiosk

Стіна камер має власний URL, тож її можна додати в закладки або показати на настінному екрані:

http://your-bamdude:8000/camwall

Відкрита в браузері, де ти залогінений, — це та сама стіна, що й на сторінці Принтери: плитки клікабельні, поповер налаштувань працює як завжди.

Телевізор чи Raspberry Pi у режимі kiosk логіну не має, тож автентифікується токеном з областю Стіна камер прямо в URL:

http://your-bamdude:8000/camwall?token=bblt_<prefix>_<secret>

Токенова стіна навмисно зведена до того, що потрібно пасивному екрану:

  • Без поповера налаштувань і без переходу по кліку. Біля телевізора ніхто не стоїть.
  • Лише компактний оверлей статусу. Бейдж стану показується; ім'я файлу — ні. Фід за цією сторінкою взагалі не віддає імен файлів, тож деталь на столі ніколи не називається кімнаті, куди може зайти будь-хто.
  • Без адрес і серійних номерів принтерів — з тієї ж причини.
  • Архівовані принтери не показуються. Принтери в режимі обслуговування — показуються: вони досі на фермі.

Оскільки kiosk-браузер незручно конфігурувати (devtools на настінному телевізорі не відкриєш), налаштування стіни можна передати через URL:

Параметр Значення Діапазон
maxLive Скільки плиток стрімлять наживо водночас; решта тягне знімки 1–16
interval Секунд між оновленнями знімків на не-live плитках 2–60
status Оверлей статусу: off або compact (токенова стіна не може обрати full) —
http://your-bamdude:8000/camwall?token=bblt_…&maxLive=9&interval=10

Значення поза діапазоном або нечитабельні відкочуються до типових, а не роблять стіну, яку тим самим URL уже не полагодиш. Kiosk ніколи не записує їх назад у браузер, тож одноразове відкриття kiosk-посилання не перезапише твої власні налаштування стіни.

URL — це і є ключ

Будь-хто, хто прочитає цей URL — з екрана, з історії браузера, з конфігу kiosk — зможе дивитись стіну. Стався до нього як до ключа. Якщо екран списали чи скомпрометували — відклич токен, і стіна згасне з наступного запиту.

Revoke токена

  1. Налаштування → API-ключі → Токени камер і монітора.
  2. Знайди ряд за іменем або lookup_prefix.
  3. Натисни Revoke, підтверди.

Будь-який пристрій з цим токеном втратить доступ з наступного запиту — без grace period, без cache-шару. Хеш ряду видаляється з БД, тож навіть DB-dump replay не спрацює.


Cover-мініатюри

GET /api/v1/printers/{id}/cover повертає мініатюру того, що принтер зараз друкує. Видається виключно з локального каталогу архівів -- BamDude ніколи не ініціює FTP-завантаження з цього ендпоінта. Поки друк активний і його 3MF ще не доклеєний, ендпоінт повертає 404, а UI показує загальний плейсхолдер. Це очікувано в перші хвилини будь-якого друку, запущеного поза BamDude: рядок архіву створюється в момент старту друку, а 3MF витягується з принтера вже потім -- на P1S цей витяг заміряно у понад вісім хвилин. Щойно файл приземлиться -- чи то з того витягу, чи з пізнішої спроби archive_download_retry -- ендпоінт почне віддавати реальний PNG без жодних дій з боку клієнта.


Оверлей-режим vs віконний режим

Переглядач камери має два режими, налаштовуються per-user у Settings > Camera:

  • Embedded (за замовчуванням) -- переглядач накладається прямо поверх картки принтера. Кілька принтерів можуть мати камери відкритими одночасно, і кожен переглядач тримає власний розмір/позицію через локальний стан. Status bar у заголовку сторінки продовжує керувати рештою UI.
  • Window -- переглядач запускається в окремому вікні браузера (або PWA-вікні). Корисно, щоб припаркувати одну камеру на другому моніторі.

Embedded -- правильний дефолт для живого моніторингу; віконний режим -- для сетапів, де камера живе на окремому екрані від дашборду принтерів.

Embedded-фічі

В embedded-режимі камера з'являється як floating-вікно з такими можливостями:

  • Draggable — клікни і тягни header для переміщення.
  • Resizable — тягни нижній правий куток для зміни розміру.
  • Persistent position — позиція і розмір запам'ятовуються per-printer між сесіями.
  • Navigation persistence — вихід зі сторінки принтерів закриває її медіазапити; повернення відновлює останню обрану камеру.
  • Minimize — згортання до заголовка зупиняє live-запит; розгортання запускає його знову.
  • Close — X для закриття.
  • Одне вікно — клік на іншому принтері замінює поточну камеру та скасовує старий потік. Зі старого списку камер відновлюється лише остання.

Embedded-режим для всієї ферми

Одне спливне вікно — для огляду принтера; Стіна камер — для всієї ферми.


Snapshot mode та налаштування FPS

Для меншого трафіку перемкни per-camera режим у Snapshot замість Live:

  • Захоплює один кадр за запитом, refresh — наступний.
  • Ідеально для cellular-конекшенів, повільних мереж, дешевих kiosk-екранів без потреби в русі.

Дефолтний фреймрейт live-режиму — 15 FPS. Тюн через URL ?fps=N або per-camera setting:

FPS Use case
5 Малий трафік / A1/P1 камери (hardware-ліміт)
10–15 Збалансовано (15 default)
20–25 Гладше відео
30 Maximum quality (X1 / H2 / P2 only — і USB)

FPS-ліміти за типом камери

  • Зовнішні камери — кеп 15 FPS.
  • A1 / P1 принтери — кеп 5 FPS (hardware-обмеження).
  • X1 / H2 / P2 принтери — до 30 FPS.

Вищий FPS = більше трафіку

Вищі fps жеруть більше bandwidth і ресурсів сервера — для multi-printer ферми на 30 FPS на кожному перегляді відразу плануй відповідно.


Очищення стріма та auto-reconnect

BamDude правильно прибирає за собою camera-стріми, щоб не плодити osиротілі ffmpeg-процеси:

  • Window close — стрім стопиться автоматично.
  • Tab hidden — стрім паузиться для збереження ресурсів.
  • Page unload — ffmpeg-процес вбивається.
  • Refresh — старий стрім зупиняється, новий стартує.

Stall detection

Браузер періодично перевіряє, чи стрім ще отримує кадри:

  • Інтервал перевірки — кожні 5 секунд.
  • Детекція — порівняння timestamp останнього кадру.
  • Threshold — stalled, якщо нема нових кадрів >5 секунд.

Автоматичне відновлення

При детекції stall:

  1. Засікає, що кадри не приходять у threshold.
  2. Закриває застряглий конекшен.
  3. Реконнектиться автоматично.
  4. Відновлює стрімінг.

Після короткого обриву перший RTSP-реконект іде одразу. Повторні збої мають коротку обмежену експоненційну затримку з окремим jitter для кожного стріму, тому вся ферма не робить один спільний burst після повернення точки доступу чи світча. Закриття переглядача перериває це очікування — reconnect-task не лишається у фоні.

Мережеві blip-и

Якщо мережа коротко падає — стрім відновиться автоматично після повернення з'єднання, без ручного втручання.


Діагностика камери

Коли камера не стрімить, BamDude може запустити вбудовану діагностику, що тестує з'єднання стадія за стадією і каже, яка саме ланка ланцюга зламана. Кнопка Diagnose стоїть поряд з Retry на error-стані переглядача, а маленька іконка стетоскопа живе в always-visible control bar (між Refresh і Fullscreen) для pre-flight перевірки ще до старту стрімінгу.

Вона стукає в POST /api/v1/printers/{id}/camera/diagnose і показує результат inline в модалі: один рядок на стадію з маркером pass / fail / skipped, тривалістю стадії в мілісекундах і перекладеним remediation-хінтом. Кнопка Run again перезапускає всю перевірку без закриття модала.

Стадії

Стадія Що перевіряє
tcp_reachable Відкриває сирий TCP-сокет до camera-порту — 322 для RTSPS, 6000 для chamber-image — з таймаутом 3 секунди. Розрізняє timeout ("принтер недосяжний"), refused-конекшен ("camera-порт закритий — перевір LAN-Only Mode + Developer Mode") і помилку host-unreachable.
first_frame Захоплює один JPEG end-to-end з таймаутом 15 секунд, через той самий pipeline, що живить /camera/snapshot. Доводить, що повний шлях реально віддає зображення, а не лише відкритий порт.

Шорткат на живому стрімі

Якщо переглядач уже дивиться камеру і буферизований останній кадр свіжіший за 10 секунд, діагностика пропускає реальний тест і репортить стрім як живий / healthy. Відкриття свіжого сокета вибило б живого глядача на firmware, що дозволяє лише один camera-конекшен — тож коли вже є доказ, що камера працює, BamDude її не чіпає.

Результат також несе метадані для support-тріажу: протокол (rtsp / chamber_image), порт, профіль (default чи model-specific назва), дзеркальну каталожну роздільність Bambu Studio, якщо вона відома, і summary-код. Каталог тут лише описовий: він ніколи не вибирає транспорт камери замість живих даних.

Якщо first_frame приєднався до вже запущеного захоплення камери, модальне вікно покаже Спільне одночасне захоплення. Це успішний результат, який не відкрив другий сокет до принтера з одним reader; Нове захоплення з камери означає, що діагностика відкрила шлях захоплення сама.


Camera Snapshot on Print Complete

BamDude може автоматично робити snapshot з камери при завершенні друку:

  1. Settings → General.
  2. Увімкни Capture snapshot on print complete.
  3. Snapshot-и зберігаються у архівну папку друку і вилазять у photo-галереї архіву.

Це створює візуальний запис кожного завершеного друку. Механізм вимкнений за замовчуванням: інсталяція без явно збереженого перемикача не тримає фонові кадри, не робить фото завершення й не додає зображення до сповіщень. Його увімкнення не вмикає власний timelapse принтера — той і далі є per-print вибором слайсера або принтера.

Як BamDude обирає момент

Ідеальний момент — останній шар моделі, поки друк ще на столі й до того, як End G-code припаркує голову, змінить або скине плиту. BamDude пробує три джерела за спаданням якості:

  1. внутрішню «кінцеву» стадію принтера, якщо прошивка її повідомляє;
  2. перехід на фінальний шар, спійманий зі статус-апдейтів принтера;
  3. rolling-знімок, зроблений поки друк ще тривав — фолбек для прошивок, які не повідомляють ні першого, ні другого (відомий кейс — A1 Mini).

Саме третє джерело і є причиною, чому фото авто-зміненої плити більше не приходить порожнім. Rolling-знімок оновлюється не частіше ніж раз на 25 секунд і перестає оновлюватись тієї ж миті, коли друк завершився, — тож він тримає готовий друк, а не те, що лишилось після. Знімається лише коли finish photo увімкнено, ніколи не переноситься між друками і пропускається, поки ти дивишся живу камеру, щоб не рвати стрім.


Інші камери (не прив'язані до принтера)

Зовнішня камера вище — це заміна камери одного принтера: через неї йде і його трансляція, і фінальне фото, і перевірка столу, і кадри для Obico. Камера, що дивиться на кімнату, стелаж чи сушарку філаменту — інша річ, і живе у власному списку.

  1. Налаштування → Друк → Камера → Інші камери → Додати камеру.
  2. Дайте назву (її показують плитка, кнопка й заголовок вікна, тому вона має бути унікальною), виберіть тип — MJPEG, RTSP, Snapshot або USB — і введіть URL чи шлях до пристрою. Той самий необов'язковий Snapshot URL і поворот, що й вище.
  3. За бажання виберіть Розташування — ті самі місця, під якими стоять принтери й сенсори Zigbee.
  4. Перевірити відкриває джерело один раз і підтверджує кадр, точно як для камери принтера.

Де вона потім з'являється:

  • Стіна камер, після принтерів і за назвою, і на авторизованій стіні, і на кіоск-стіні з ?token=. Плитка може піти в LIVE, як будь-яка інша, і враховується в тому самому бюджеті; статусу друку на ній немає, бо друку немає.
  • Сторінка принтерів, кнопкою в заголовку того розташування, під яким ви її вказали, поруч із показниками сенсорів того ж місця. Клік відкриває плаваюче вікно або вікно браузера — за тим самим налаштуванням Режим перегляду камери, що й картки принтерів.

Показувати на стіні вимикає камеру, не видаляючи її: плитка й кнопка зникають, а її маршрути потоку й кадру перестають відповідати; налаштування лишаються на потім.

Чого окрема камера не робить ніколи

Вона не знімає фінальних фото, не перевіряє стіл, не годує детекцію збоїв Obico, не пише пошаровий таймлапс і не вмикає світло: усе це належить принтеру, а в неї принтера немає. Вона також ніколи не підміняє камеру принтера — для цього є Зовнішні камери вище.

Одне з'єднання на камеру

Усі, хто дивиться ту саму окрему камеру, ділять одне з'єднання, тож USB-камера — яка пускає рівно одного читача — не скидає першого глядача, коли відкривається другий. Кадр, узятий поки хтось дивиться, береться з живого потоку, а не окремим читачем.

Кіоск-список не містить URL

Кіоск-стіна автентифікується токеном у своєму URL, а в URL RTSP-камери живе пароль. Тому кіоск-стрічка віддає назву, поворот і розташування — і нічого більше, з тієї ж причини, з якої вона ніколи не віддає серійного номера принтера.


Світло для камери

Темна камера — темне фото. BamDude може вмикати світло в камері принтера для камери і гасити його після — для будь-якого звернення: фото в Telegram, трансляція в браузері, стіна камер, фінальне фото, перевірка пластини, діагностика камери. (Окрема камера вище принтера не має, тож до неї це не стосується.)

  1. Налаштування → Друк → Камера → Світло для камери. Типово вимкнено — на фермі, де це не ввімкнули, нічого не змінюється. Це головний вимикач: поки він вимкнений, нічого з наведеного нижче не діє.
  2. У тій самій картці, список Зовнішні камери, для кожного принтера: Світло для камери — Як на фермі / Ні. Принтер, який не має світитися у вікно, каже Ні. Селектор показується лише коли фермовий перемикач увімкнено, і не показується для підключеного принтера, який не повідомив про кероване світло.
  3. І для детекції збоїв Obico — окремий перемикач, типово вимкнений; показується лише коли фермовий перемикач увімкнено і детекцію Obico ввімкнено. Obico дивиться в камеру кожні кілька секунд увесь друк, тож із ним світло горітиме увесь друк.

Два правила, завдяки яким це можна лишати ввімкненим:

  • Вмикається лише вимкнене світло. Світло, що вже горіло — ви його ввімкнули, або прошивка при старті друку — не чіпається ні до, ні після.
  • Гаситься лише те світло, яке ввімкнув BamDude, і лише коли камерою більше ніхто не користується. Якщо ви самі вимкнете світло під час трансляції, BamDude його не вмикатиме назад; якщо самі ввімкнете — BamDude його після не погасить.

Як це виглядає на практиці: разове фото чекає, поки принтер підтвердить світло, і лише тоді бере кадр (без фіксованої паузи й без темного першого фото), а гасне світло приблизно через десять секунд після останнього звернення, тож два фото поспіль не блимають. Кілька вкладок браузера на один принтер — це одне ввімкнення й одне вимкнення. Стіна камер у режимі кадрів тримає світло, поки стіна відкрита, і відпускає його протягом одного інтервалу оновлення після закриття. Пошаровий таймлапс світло навмисно не бере — воно блимало б на кожному шарі; якщо таймлапсу треба світло, ввімкніть його самі. Власний таймлапс принтера світить сам.

Одне звернення на перемикач не зважає: перевірка робочого столу (нижче) вмикає світло для свого порівняння, хай там що в налаштуваннях, як робила завжди — її еталон відкалібровано з увімкненим світлом, і перевірка в темряві поставила б друк на паузу ні за що. Тепер вона робить це тим самим механізмом: з підтвердженням від принтера замість фіксованої паузи, і не чіпаючи світло, яке вже горіло.

A1 / A1 mini

Ці принтери не вмикають світло при старті друку, як серії X1 і P1, тому фото з бота на темному A1 завжди було темним. Саме це налаштування це виправляє.

Після перезапуску

Нічого з цього не запам'ятовується між перезапусками BamDude. Світло, ввімкнене для трансляції, яка була відкрита під час перезапуску, лишається горіти; наступне звернення застає його ввімкненим і, за другим правилом, не чіпає.


Build Plate Empty Detection

Автоматично детектить об'єкти, залишені на столі перед стартом друку. При детекції — друк паузиться, фаєриться нотифікація.

Як це працює

  1. Calibrate — захоп reference-зображення твого пустого столу.
  2. Enable — увімкни plate-detection для принтера.
  3. Auto-check — при старті будь-якого друку BamDude порівнює поточне зображення камери з референсами.
  4. Auto-pause — якщо детектовано об'єкти, друк негайно паузиться.

Калібровка

Зберігай до 5 reference-зображень на принтер для різних типів столу (textured, smooth, high-temp, тощо):

  1. Натисни scan-іконку на картці принтера для відкриття модала.
  2. Переконайся, що стіл повністю порожній і chamber light ON.
  3. Натисни Calibrate Empty Plate.
  4. Опційно додай label (Textured PEI, Cool Plate).
  5. Повтори для кожного типу столу, який реально використовуєш.

Кілька референсів

Система автоматично обирає найкращий-матчинг референс при перевірці. Калібруй кожен тип, який реально юзаєш, для точної детекції.

Увімкнення детекції

На картці принтера є split button:

Частина Дія
Main (scan-іконка) Перемикає детекцію on/off.
Chevron (▼) Відкриває модал калібровки / управління.

Коли увімкнено — кнопка має зелену рамку.

ROI (Region of Interest) editor

Налаштуй, яку частину camera-вʼю аналізувати:

  1. Відкрий plate-detection модал.
  2. Скрол до Detection Area (ROI).
  3. Натисни Edit.
  4. Слайдерами X / Y / Width / Height задай зелений ROI-box.
  5. Save.

Зелений box у preview показує detection area. Зосередь на столі, щоб уникнути false positives від рами принтера, AMS, фону.

Механіка детекції

  1. Захоплює поточний камера-кадр (або юзає buffered-кадр, якщо стрім активний).
  2. Накладає важкий Gaussian blur на обидва — поточний і reference.
  3. Нормалізує обидва для consistent-порівняння.
  4. Вирізає ROI-регіон.
  5. Рахує pixel-difference відсоток.
  6. Якщо різниця > 1% — стіл "не порожній".

Нотифікації при детекції

  • Друк негайно паузиться.
  • Toast-нотифікація в BamDude.
  • Push-нотифікація (Telegram / Discord / Email / Pushover / ntfy / HA — що увімкнено).
  • WebSocket-подія для інтеграцій.

Вимоги

Вимога Деталі
OpenCV opencv-python-headless (вже в Docker-образі).
Chamber light Має бути ON для надійної детекції.
Calibration Хоча б один reference.

Траблшутинг

False positives (детектить об'єкти при порожньому столі)

  • Калібруй з chamber light ON (як під час друку).
  • Зменши ROI, щоб виключити рами/AMS.
  • Додай кілька калібровок для різних умов освітлення.

False negatives (не детектить об'єкти)

  • Переконайся, що chamber light ON.
  • Перекалібруй — поверхня столу могла змінитися (резин-резидіу, peel-стікер, подряпини).
  • Перевір, що об'єкти всередині ROI — все поза зеленим box ігнорується by design.

Траблшутинг

Стрім не стартує

  1. Чи увімкнено принтер? Камера потребує живлення.
  2. Чи увімкнена камера в налаштуваннях принтера?
  3. Чи інстальовано ffmpeg? (Включено в Docker-образ.)
  4. Чи увімкнено Developer Mode? (Потрібно для доступу до камери на Bambu принтерах.)
  5. Для зовнішніх камер — перевір URL з curl зсередини BamDude-хоста: curl -I http://192.168.1.50/mjpeg.
  6. У Docker? Якщо default bridge не дотягується до принтера, перемкни на network_mode: host.

Стрім фризить

  • Network congestion або WiFi-дропи — спробуй знизити FPS до 5 або 10.
  • Перевір силу WiFi-сигналу принтера (поганий сигнал — нестабільна доставка кадрів).
  • Спробуй snapshot mode — він не залежить від continuous-стріма.

Висока latency (1–3 секунди лагу)

Це нормально для MJPEG-over-HTTP і випливає з RTSP-буферизації, ffmpeg-pipeline і HTTP-stream-chunk boundaries. Не усунеш повністю. Зменшити можна:

  • Знизити FPS для меншої per-frame буферизації.
  • Snapshot-режим замість стріма для моніторингу.
  • Зовнішня камера з hardware MJPEG-виходом (пропускає RTSP→MJPEG transcoding).

Чорний екран

  • Камера може ініціалізуватися — почекай 5–10 секунд і refresh.
  • Перевір, що камера працює в Bambu Studio спочатку; якщо там не працює — це printer-side, не BamDude.
  • Перевір user-permission grants — потрібен camera:view.

Docker: камера не працює

Якщо в Docker не працює, спробуй host-network:

services:
  bamdude:
    network_mode: host
    # прибери секцію ports: при host-mode

Default bridge з NAT працює в більшості сетапів. Host-mode потрібен лише коли мережева конфігурація заважає NAT-трафіку дотягтися до RTSP-порту принтера.


API-ендпоінти

Для розробників і інтеграцій:

Ендпоінт Метод Опис
/api/v1/printers/{id}/camera/stream GET MJPEG live-стрім.
/api/v1/printers/{id}/camera/snapshot GET Single JPEG-кадр.
/api/v1/printers/{id}/camera/stop POST Зупинити активні стріми принтера.
/api/v1/printers/{id}/camera/test GET Тест conneкту до камери (success/failure без стрімінгу).
/api/v1/printers/camera/stream-token POST Mint 60-хв query-param stream-токен (див. Stream Token Gate вище).

Рецепт OBS Browser Source

Embed live-стрім в OBS як Browser Source:

  1. В OBS клацни + під Sources.
  2. Обери Browser.
  3. URL: http://your-bamdude:8000/api/v1/printers/{id}/camera/stream?token=<long-lived-token> (юзай long-lived camera token — короткоживучі експайряться mid-stream).
  4. Width / height під сцену (наприклад, 1920×1080).
  5. OK.

Для багатшого overlay зі статус-текстом — див. наступну секцію.


OBS Streaming Overlay

Спеціальна overlay-сторінка комбінує camera-фід з real-time print-статусом — один Browser Source замість окремих camera + text. Форма URL:

http://your-bamdude:8000/overlay/{printer_id}

OBS потрібен токен

Усе, що малює оверлей — статус друку, назва принтера, фід камери — за автентифікацією. У браузері, де ти вже залогінений, він працює, але OBS — це чистий браузер без сесії, тож URL вище дасть порожній оверлей.

До способу, яким ти дістаєшся сервера, це не має стосунку: реверс-проксі, Cloudflare Tunnel чи віддалений домен нічого не змінюють, а вікно інкогніто ламається так само. OBS потрібен саме токен.

Токен Оверлея для стріму

  1. Налаштування → API-ключі → Токени камер і монітора.
  2. Створи токен з областю Оверлей для стріму і скопіюй його.
  3. Додай його до URL оверлея; номер принтера збігається з номером у його власному URL на сторінці Принтери (/overlay/1 — принтер 1, і так далі):
http://your-bamdude:8000/overlay/1?token=bblt_<prefix>_<secret>

У токен-режимі оверлей взагалі не відкриває WebSocket і оновлюється опитуванням раз на 2 секунди — токен не може підняти WebSocket, і опитування є фідом.

Стався до URL як до ключа

Будь-хто, хто прочитає цей URL, зможе дивитись потік принтера і бачити ім'я файлу друку. Він не дістає адресу принтера, серійний номер чи код доступу і не може перелічити інші твої принтери — токен Оверлея відкриває оверлей одного принтера і нічого більше. Відклич його на тій самій сторінці Налаштувань, щоб відрізати оверлей.

Що включено

Елемент Опис
Camera-фід Full-screen live camera.
BamDude-логотип Брендинг у правому верхньому.
Filename Ім'я поточного print-файлу.
Status Printing, Paused, Idle тощо.
Progress bar Візуальний прогрес з відсотком.
Layer count Поточний шар / загальна кількість.
Time remaining Оцінка залишку часу.
ETA Оцінка часу завершення.

Кастомізація через query-параметри

Param Значення Ефект
size small / medium / large Масштаб тексту і логотипа. medium default.
fps 1–30 Live-FPS. Сlamp-ається server-side per-camera-type.
camera true (default), false/0 false ховає camera-фід, показує статус на чорному фоні.
show comma-separated: progress, layers, eta, filename, status, printer Які елементи статусу показувати.

Приклади:

# Компактний кутовий overlay з повним статусом
/overlay/1?size=small&show=progress,layers,eta,filename,status

# Status-only, без камери (low-bandwidth сценарій)
/overlay/1?camera=false&show=progress,eta,status

# Maximum quality, full screen
/overlay/1?size=large&fps=30&show=progress,layers,eta,filename,status,printer

Idle-стан

Коли друк не йде, overlay все одно працює — показує camera-фід плюс "idle" / "offline" і логотип BamDude. Корисно для стрімінгу cleanup ферми, swap-у плити, off-hours.

Траблшутинг overlay

Overlay не вантажиться в OBS

  • Перевір, що URL працює в звичайному браузері спочатку.
  • Перевір, що OBS дотягується до BamDude-сервера (та сама мережа, без VPN-обмежень).
  • Right-click source в OBS → Refresh cache of current page.

Камера не показується в overlay

  • Підтверди, що принтер підключений.
  • Підтверди, що camera-стрімінг працює в BamDude напряму спочатку — overlay юзає той самий стрім.
  • Status-апдейти йдуть по WebSocket; якщо WS-handshake падає, статус фолбекається на polling кожні 2 секунди.

Поради

Кілька камер

Для кількох камер використовуйте Стіну камер. Оверлей тримає одне вікно й перемикає його на обраний принтер.

Економія трафіку

Закривайте вікна камер, коли не спостерігаєте активно, щоб зберегти ресурси сервера.

Мобільний перегляд

Camera-стрімінг працює на мобільних з повною touch-підтримкою — pinch для zoom, drag для pan коли zoom > 100%. Доступ через camera-іконку на картці принтера.

Базується на документації Bambuddy.