2026-03-25 — Нативный транспорт и null-sink standby
Финальный рывок недели выпустил две функции, к которым всё шло: нативное управление транспортом Sendspin и null-sink standby с автопробуждением. Двадцать один RC-релиз в рамках четырёх стабильных тегов и одного RC доставили их вместе с восстановлением после крашей ALSA, кросс-bridge обнаружением дубликатов, проходом по безопасности и более чем 125 новыми тестами.
Что вошло в релиз
Заголовок раздела «Что вошло в релиз»Нативные транспортные команды Sendspin (v2.48.0)
Заголовок раздела «Нативные транспортные команды Sendspin (v2.48.0)»Bridge теперь может отправлять команды play, pause, stop, next, previous, shuffle, repeat, mute и volume нативно через роль Sendspin Controller по POST /api/transport/cmd. Раньше всё управление транспортом шло через queue API Music Assistant, добавляя задержку и требуя активного соединения с MA.
Транспортный UI автоматически откатывается на MA queue-команды, когда нативный транспорт недоступен, поэтому операторы со старыми MA-установками не видят изменений в поведении. Кнопки shuffle и repeat обновляются сразу в веб-интерфейсе после успешной нативной команды, соответствуя более отзывчивому ощущению прямого управления.
Расширенная пересылка метаданных
Заголовок раздела «Расширенная пересылка метаданных»Соединение по протоколу Sendspin теперь пересылает album, album artist, artwork URL, year, track number, shuffle state, repeat mode и обновления состояния controller, включая supported_commands, group_volume и group_muted. Эти метаданные всегда были доступны в протоколе, но никогда не отображались в status-модели bridge.
Кросс-bridge обнаружение дубликатов
Заголовок раздела «Кросс-bridge обнаружение дубликатов»Когда запущено несколько экземпляров bridge (типичная ситуация для конфигураций с HAOS и отдельным LXC-деплоем), bridge теперь обнаруживает, когда другой экземпляр уже владеет Bluetooth-устройством. Startup и recovery flow показывают предупреждения о конфликтах, а модальное окно BT scan запрашивает подтверждение перед сопряжением устройства, которое уже занято в другом месте.
Настройка startup и аудио-дефолтов
Заголовок раздела «Настройка startup и аудио-дефолтов»Поведение первого запуска стало надёжнее с выверенными дефолтами: startup grace по умолчанию 5 секунд, recovery-banner grace — 15 секунд, PULSE_LATENCY_MSEC — 600, а для вновь добавленных устройств по умолчанию static_delay_ms = -300. Эти значения выбраны на основе production-телеметрии HAOS и устраняют самые частые обращения «работает после одного ручного перезапуска».
Восстановление после ALSA underrun краша (v2.48.1)
Заголовок раздела «Восстановление после ALSA underrun краша (v2.48.1)»Краш ValueError: memoryview assignment: lvalue and rvalue have different structures мог происходить после ALSA underrun и recovery re-anchor внутри subprocess runtime. Bridge теперь защищается от устаревшего закешированного состояния output-frame, так что повторно используемый фрейм из старого формата или цикла коррекции сбрасывается вместо краша.
Ложное recovery при потере транспорта (v2.48.1)
Заголовок раздела «Ложное recovery при потере транспорта (v2.48.1)»Несколько ложноположительных guidance-состояний были устранены:
- Активная аудиотрансляция теперь рассматривается как авторитетная во время кратких переподключений Sendspin control, поэтому переходные окна
server_connected=falseбольше не вызывают предупреждения о потере транспорта, пока колонка продолжает играть. - Простаивающие колонки входят в выделенное переходное состояние
ma_reconnectingво время плановых переподключений MA metadata вместо отображения предупреждений об отключении. - После успешного замещающего переподключения bridge публикует
server_connectedтолько после завершения handshake нового WebSocket, предотвращая затирание свежего состояния соединения callback-ом отключения старой сессии.
Исправление совместимости роли visualizer (v2.48.2)
Заголовок раздела «Исправление совместимости роли visualizer (v2.48.2)»Более новые сборки aiosendspin обнажили черновую роль visualizer@_draft_r1, которая вызывала отказ Music Assistant принять соединение плеера при startup. Bridge больше не анонсирует роль visualizer в ClientHello, и aiosendspin теперь закреплён на 4.3.2 напрямую в requirements.txt для предотвращения транзитивного дрифта зависимостей.
Phase 2: null-sink standby с автопробуждением (v2.49.0)
Заголовок раздела «Phase 2: null-sink standby с автопробуждением (v2.49.0)»Это была главная функция недели. Когда колонка переходит в idle, daemon продолжает жить на PulseAudio null sink вместо завершения работы. Плеер Music Assistant остаётся видимым, поэтому воспроизведение автоматически возобновляется при запросе — с задержкой Bluetooth-переподключения около 5 секунд вместо 30+ секунд, необходимых для холодного старта daemon.
Система standby включает:
- Автопробуждение при play — когда MA отправляет play, а колонка в standby, Bluetooth переподключается автоматически.
- Пробуждение sync-группы — участники группы будят друг друга, поэтому запуск воспроизведения на одной колонке в sync-группе поднимает остальные.
- Idle disconnect — per-device
idle_disconnect_minutesотключает Bluetooth после таймаута тишины для экономии батареи колонки. - Взаимное исключение — keep-alive и idle standby взаимоисключающие как в UI, так и в backend; включение одного отключает другое.
- Null-sink fallback — null sink
sendspin_fallbackпредотвращает попадание осиротевших потоков на случайные Bluetooth-колонки. - Отключение rescue-streams —
DISABLE_PA_RESCUE_STREAMSвыгружаетmodule-rescue-streamsPulseAudio при startup для окружений, где дрифт sink постоянный.
UI standby показывает бейдж 💤 на карточках устройств, кнопку-переключатель луна/солнце и переходное состояние «Waking». Фильтр статуса standby в тулбаре позволяет операторам сфокусироваться на активных или спящих устройствах.
Пользовательская иерархия исключений
Заголовок раздела «Пользовательская иерархия исключений»Обработка ошибок перешла от перехвата голого Exception к структурированной иерархии: BridgeError → BluetoothError, PulseAudioError, MusicAssistantError, ConfigError, IPCError. Это сделало тестирование путей ошибок осмысленным и позволило вызывающему коду перехватывать конкретные виды отказов.
Укрепление безопасности (v2.49.0)
Заголовок раздела «Укрепление безопасности (v2.49.0)»Standby-релиз включал проход по безопасности: итерации PBKDF2 повышены до 600K с версионированным форматом хеша, POST /api/config теперь фильтрует через белый список разрешённых ключей, artwork proxy валидирует Content-Type (только image/*), динамические значения onclick используют escHtmlAttr() для предотвращения XSS, capability SYS_ADMIN удалён из конфигов HA addon, а каждый subprocess daemon теперь задаёт уникальное имя приложения PulseAudio для предотвращения путаницы потоков module-stream-restore между колонками.
125+ новых тестов и унификация CI
Заголовок раздела «125+ новых тестов и унификация CI»Набор тестов вырос с ~830 до 959 тестов, покрывая sendspin_client, web_interface, bt_monitor и bt_manager. CI/CD pipeline был унифицирован в единый release workflow: один файл VERSION запускает lint → test → tag → Docker build → HA addon sync.
Переработка UX конфигурации
Заголовок раздела «Переработка UX конфигурации»Вкладка General settings была реорганизована в фокусированные секции, и добавлена отдельная вкладка Audio для настроек PulseAudio. Переключатель экспериментальных функций (browser-local) показывает или скрывает поля room name, room ID и handoff mode. Действия Release и Reclaim переехали в выпадающее меню Device Fleet и список Already Paired.
Обновления зависимостей (v2.50.0-rc.1)
Заголовок раздела «Обновления зависимостей (v2.50.0-rc.1)»Первый RC следующего цикла обновил основные зависимости: websockets 13.1 → 16.0 (async API мигрирован на websockets.asyncio.client), waitress 2.1.2 → 3.0.2 и обновления CI actions по всем направлениям.
Почему это важно
Заголовок раздела «Почему это важно»Нативный транспорт и null-sink standby вместе преобразили bridge из ретранслятора воспроизведения в нечто более близкое к полноценному плееру Music Assistant. Транспортные команды выполняются за миллисекунды вместо round-trip через queue API MA. Standby означает, что колонки просыпаются за 5 секунд вместо 30, делая передачу между комнатами отзывчивой, а не сломанной.
Укрепление безопасности, пользовательские исключения и 125+ новых тестов дали проекту фундамент надёжности, необходимый для поддержки этих более сложных runtime-поведений. А кросс-bridge обнаружение дубликатов закрыло реальную болевую точку операторов, использующих одновременно HAOS и LXC-деплои.
Что дальше
Заголовок раздела «Что дальше»v2.50.0-rc.1 отмечает начало следующего цикла разработки, сфокусированного на модернизации зависимостей и подготовке runtime к работе по backend abstraction для v3, описанной в обновлённом roadmap.