Трансляція камери¶
Візуально спостерігайте за друком через живу трансляцію камери безпосередньо з вашого принтера Bambu Lab.
Жива трансляція¶
BamDude забезпечує MJPEG-відеотрансляцію з вбудованої камери принтера або зовнішньої мережевої камери.
Відкриття камери¶
- Натисніть іконку камери на картці принтера
- Оберіть між оверлей-режимом або окремим вікном (налаштовується в Параметрах)
- Трансляція починається автоматично
Елементи керування¶
| Кнопка | Дія |
|---|---|
| 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 |
Конфігурація¶
- Settings → General → Camera.
- Знайди свій принтер у секції External Cameras.
- Перемкни switch для увімкнення.
- Введи URL камери.
- Обери Type.
- Натисни 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 — пробрось пристрій:
Layer-Based Timelapse (тільки зовнішні камери)¶
Коли увімкнено зовнішню камеру і принтер публікує per-layer-change MQTT-події, BamDude автоматично:
- Захоплює кадр на кожен інкремент шару друку.
- Зберігає кадри у тимчасовій директорії під час друку.
- Стічить відео через ffmpeg на завершенні друку.
- Прикріплює результуючий 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. Досвідчені оператори можуть перед запуском сервісу встановити змінну
середовища:
Вона запускає один 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:
Якщо не задано — поведінка незмінна (пошук у 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 токен:
- Фронт стукає в
POST /api/v1/printers/camera/stream-token, щоб отримати токен, прив'язаний до поточного користувача (TTL 60 хв). - Токен дописується як
?token=...до кожного camera-URL черезwithStreamToken()в API-клієнті. - Уже відрендерені DOM-вузли (наприклад,
<img>, змонтований до приходу токена) ретрофітяться черезrewriteMediaSrcWithToken(). - Токен у 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, тож її можна додати в закладки або показати на настінному екрані:
Відкрита в браузері, де ти залогінений, — це та сама стіна, що й на сторінці Принтери: плитки клікабельні, поповер налаштувань працює як завжди.
Телевізор чи Raspberry Pi у режимі kiosk логіну не має, тож автентифікується токеном з областю Стіна камер прямо в URL:
Токенова стіна навмисно зведена до того, що потрібно пасивному екрану:
- Без поповера налаштувань і без переходу по кліку. Біля телевізора ніхто не стоїть.
- Лише компактний оверлей статусу. Бейдж стану показується; ім'я файлу — ні. Фід за цією сторінкою взагалі не віддає імен файлів, тож деталь на столі ніколи не називається кімнаті, куди може зайти будь-хто.
- Без адрес і серійних номерів принтерів — з тієї ж причини.
- Архівовані принтери не показуються. Принтери в режимі обслуговування — показуються: вони досі на фермі.
Оскільки kiosk-браузер незручно конфігурувати (devtools на настінному телевізорі не відкриєш), налаштування стіни можна передати через URL:
| Параметр | Значення | Діапазон |
|---|---|---|
maxLive |
Скільки плиток стрімлять наживо водночас; решта тягне знімки | 1–16 |
interval |
Секунд між оновленнями знімків на не-live плитках | 2–60 |
status |
Оверлей статусу: off або compact (токенова стіна не може обрати full) |
— |
Значення поза діапазоном або нечитабельні відкочуються до типових, а не роблять стіну, яку тим самим URL уже не полагодиш. Kiosk ніколи не записує їх назад у браузер, тож одноразове відкриття kiosk-посилання не перезапише твої власні налаштування стіни.
URL — це і є ключ
Будь-хто, хто прочитає цей URL — з екрана, з історії браузера, з конфігу kiosk — зможе дивитись стіну. Стався до нього як до ключа. Якщо екран списали чи скомпрометували — відклич токен, і стіна згасне з наступного запиту.
Revoke токена¶
- Налаштування → API-ключі → Токени камер і монітора.
- Знайди ряд за іменем або
lookup_prefix. - Натисни 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:
- Засікає, що кадри не приходять у threshold.
- Закриває застряглий конекшен.
- Реконнектиться автоматично.
- Відновлює стрімінг.
Після короткого обриву перший 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 з камери при завершенні друку:
- Settings → General.
- Увімкни Capture snapshot on print complete.
- Snapshot-и зберігаються у архівну папку друку і вилазять у photo-галереї архіву.
Це створює візуальний запис кожного завершеного друку. Механізм вимкнений за замовчуванням: інсталяція без явно збереженого перемикача не тримає фонові кадри, не робить фото завершення й не додає зображення до сповіщень. Його увімкнення не вмикає власний timelapse принтера — той і далі є per-print вибором слайсера або принтера.
Як BamDude обирає момент
Ідеальний момент — останній шар моделі, поки друк ще на столі й до того, як End G-code припаркує голову, змінить або скине плиту. BamDude пробує три джерела за спаданням якості:
- внутрішню «кінцеву» стадію принтера, якщо прошивка її повідомляє;
- перехід на фінальний шар, спійманий зі статус-апдейтів принтера;
- rolling-знімок, зроблений поки друк ще тривав — фолбек для прошивок, які не повідомляють ні першого, ні другого (відомий кейс — A1 Mini).
Саме третє джерело і є причиною, чому фото авто-зміненої плити більше не приходить порожнім. Rolling-знімок оновлюється не частіше ніж раз на 25 секунд і перестає оновлюватись тієї ж миті, коли друк завершився, — тож він тримає готовий друк, а не те, що лишилось після. Знімається лише коли finish photo увімкнено, ніколи не переноситься між друками і пропускається, поки ти дивишся живу камеру, щоб не рвати стрім.
Інші камери (не прив'язані до принтера)¶
Зовнішня камера вище — це заміна камери одного принтера: через неї йде і його трансляція, і фінальне фото, і перевірка столу, і кадри для Obico. Камера, що дивиться на кімнату, стелаж чи сушарку філаменту — інша річ, і живе у власному списку.
- Налаштування → Друк → Камера → Інші камери → Додати камеру.
- Дайте назву (її показують плитка, кнопка й заголовок вікна, тому вона має бути унікальною), виберіть тип — MJPEG, RTSP, Snapshot або USB — і введіть URL чи шлях до пристрою. Той самий необов'язковий Snapshot URL і поворот, що й вище.
- За бажання виберіть Розташування — ті самі місця, під якими стоять принтери й сенсори Zigbee.
- Перевірити відкриває джерело один раз і підтверджує кадр, точно як для камери принтера.
Де вона потім з'являється:
- Стіна камер, після принтерів і за назвою, і на авторизованій стіні, і на кіоск-стіні з
?token=. Плитка може піти в LIVE, як будь-яка інша, і враховується в тому самому бюджеті; статусу друку на ній немає, бо друку немає. - Сторінка принтерів, кнопкою в заголовку того розташування, під яким ви її вказали, поруч із показниками сенсорів того ж місця. Клік відкриває плаваюче вікно або вікно браузера — за тим самим налаштуванням Режим перегляду камери, що й картки принтерів.
Показувати на стіні вимикає камеру, не видаляючи її: плитка й кнопка зникають, а її маршрути потоку й кадру перестають відповідати; налаштування лишаються на потім.
Чого окрема камера не робить ніколи
Вона не знімає фінальних фото, не перевіряє стіл, не годує детекцію збоїв Obico, не пише пошаровий таймлапс і не вмикає світло: усе це належить принтеру, а в неї принтера немає. Вона також ніколи не підміняє камеру принтера — для цього є Зовнішні камери вище.
Одне з'єднання на камеру
Усі, хто дивиться ту саму окрему камеру, ділять одне з'єднання, тож USB-камера — яка пускає рівно одного читача — не скидає першого глядача, коли відкривається другий. Кадр, узятий поки хтось дивиться, береться з живого потоку, а не окремим читачем.
Кіоск-список не містить URL
Кіоск-стіна автентифікується токеном у своєму URL, а в URL RTSP-камери живе пароль. Тому кіоск-стрічка віддає назву, поворот і розташування — і нічого більше, з тієї ж причини, з якої вона ніколи не віддає серійного номера принтера.
Світло для камери¶
Темна камера — темне фото. BamDude може вмикати світло в камері принтера для камери і гасити його після — для будь-якого звернення: фото в Telegram, трансляція в браузері, стіна камер, фінальне фото, перевірка пластини, діагностика камери. (Окрема камера вище принтера не має, тож до неї це не стосується.)
- Налаштування → Друк → Камера → Світло для камери. Типово вимкнено — на фермі, де це не ввімкнули, нічого не змінюється. Це головний вимикач: поки він вимкнений, нічого з наведеного нижче не діє.
- У тій самій картці, список Зовнішні камери, для кожного принтера: Світло для камери — Як на фермі / Ні. Принтер, який не має світитися у вікно, каже Ні. Селектор показується лише коли фермовий перемикач увімкнено, і не показується для підключеного принтера, який не повідомив про кероване світло.
- І для детекції збоїв Obico — окремий перемикач, типово вимкнений; показується лише коли фермовий перемикач увімкнено і детекцію Obico ввімкнено. Obico дивиться в камеру кожні кілька секунд увесь друк, тож із ним світло горітиме увесь друк.
Два правила, завдяки яким це можна лишати ввімкненим:
- Вмикається лише вимкнене світло. Світло, що вже горіло — ви його ввімкнули, або прошивка при старті друку — не чіпається ні до, ні після.
- Гаситься лише те світло, яке ввімкнув BamDude, і лише коли камерою більше ніхто не користується. Якщо ви самі вимкнете світло під час трансляції, BamDude його не вмикатиме назад; якщо самі ввімкнете — BamDude його після не погасить.
Як це виглядає на практиці: разове фото чекає, поки принтер підтвердить світло, і лише тоді бере кадр (без фіксованої паузи й без темного першого фото), а гасне світло приблизно через десять секунд після останнього звернення, тож два фото поспіль не блимають. Кілька вкладок браузера на один принтер — це одне ввімкнення й одне вимкнення. Стіна камер у режимі кадрів тримає світло, поки стіна відкрита, і відпускає його протягом одного інтервалу оновлення після закриття. Пошаровий таймлапс світло навмисно не бере — воно блимало б на кожному шарі; якщо таймлапсу треба світло, ввімкніть його самі. Власний таймлапс принтера світить сам.
Одне звернення на перемикач не зважає: перевірка робочого столу (нижче) вмикає світло для свого порівняння, хай там що в налаштуваннях, як робила завжди — її еталон відкалібровано з увімкненим світлом, і перевірка в темряві поставила б друк на паузу ні за що. Тепер вона робить це тим самим механізмом: з підтвердженням від принтера замість фіксованої паузи, і не чіпаючи світло, яке вже горіло.
A1 / A1 mini
Ці принтери не вмикають світло при старті друку, як серії X1 і P1, тому фото з бота на темному A1 завжди було темним. Саме це налаштування це виправляє.
Після перезапуску
Нічого з цього не запам'ятовується між перезапусками BamDude. Світло, ввімкнене для трансляції, яка була відкрита під час перезапуску, лишається горіти; наступне звернення застає його ввімкненим і, за другим правилом, не чіпає.
Build Plate Empty Detection¶
Автоматично детектить об'єкти, залишені на столі перед стартом друку. При детекції — друк паузиться, фаєриться нотифікація.
Як це працює¶
- Calibrate — захоп reference-зображення твого пустого столу.
- Enable — увімкни plate-detection для принтера.
- Auto-check — при старті будь-якого друку BamDude порівнює поточне зображення камери з референсами.
- Auto-pause — якщо детектовано об'єкти, друк негайно паузиться.
Калібровка¶
Зберігай до 5 reference-зображень на принтер для різних типів столу (textured, smooth, high-temp, тощо):
- Натисни scan-іконку на картці принтера для відкриття модала.
- Переконайся, що стіл повністю порожній і chamber light ON.
- Натисни Calibrate Empty Plate.
- Опційно додай label (
Textured PEI,Cool Plate). - Повтори для кожного типу столу, який реально використовуєш.
Кілька референсів
Система автоматично обирає найкращий-матчинг референс при перевірці. Калібруй кожен тип, який реально юзаєш, для точної детекції.
Увімкнення детекції¶
На картці принтера є split button:
| Частина | Дія |
|---|---|
| Main (scan-іконка) | Перемикає детекцію on/off. |
| Chevron (▼) | Відкриває модал калібровки / управління. |
Коли увімкнено — кнопка має зелену рамку.
ROI (Region of Interest) editor¶
Налаштуй, яку частину camera-вʼю аналізувати:
- Відкрий plate-detection модал.
- Скрол до Detection Area (ROI).
- Натисни Edit.
- Слайдерами X / Y / Width / Height задай зелений ROI-box.
- Save.
Зелений box у preview показує detection area. Зосередь на столі, щоб уникнути false positives від рами принтера, AMS, фону.
Механіка детекції¶
- Захоплює поточний камера-кадр (або юзає buffered-кадр, якщо стрім активний).
- Накладає важкий Gaussian blur на обидва — поточний і reference.
- Нормалізує обидва для consistent-порівняння.
- Вирізає ROI-регіон.
- Рахує pixel-difference відсоток.
- Якщо різниця > 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.
Траблшутинг¶
Стрім не стартує
- Чи увімкнено принтер? Камера потребує живлення.
- Чи увімкнена камера в налаштуваннях принтера?
- Чи інстальовано
ffmpeg? (Включено в Docker-образ.) - Чи увімкнено Developer Mode? (Потрібно для доступу до камери на Bambu принтерах.)
- Для зовнішніх камер — перевір URL з
curlзсередини BamDude-хоста:curl -I http://192.168.1.50/mjpeg. - У 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:
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:
- В OBS клацни + під Sources.
- Обери Browser.
- URL:
http://your-bamdude:8000/api/v1/printers/{id}/camera/stream?token=<long-lived-token>(юзай long-lived camera token — короткоживучі експайряться mid-stream). - Width / height під сцену (наприклад, 1920×1080).
- OK.
Для багатшого overlay зі статус-текстом — див. наступну секцію.
OBS Streaming Overlay¶
Спеціальна overlay-сторінка комбінує camera-фід з real-time print-статусом — один Browser Source замість окремих camera + text. Форма URL:
OBS потрібен токен
Усе, що малює оверлей — статус друку, назва принтера, фід камери — за автентифікацією. У браузері, де ти вже залогінений, він працює, але OBS — це чистий браузер без сесії, тож URL вище дасть порожній оверлей.
До способу, яким ти дістаєшся сервера, це не має стосунку: реверс-проксі, Cloudflare Tunnel чи віддалений домен нічого не змінюють, а вікно інкогніто ламається так само. OBS потрібен саме токен.
Токен Оверлея для стріму¶
- Налаштування → API-ключі → Токени камер і монітора.
- Створи токен з областю Оверлей для стріму і скопіюй його.
- Додай його до URL оверлея; номер принтера збігається з номером у його власному
URL на сторінці Принтери (
/overlay/1— принтер 1, і так далі):
У токен-режимі оверлей взагалі не відкриває 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.