Compare commits

..

2 Commits

Author SHA1 Message Date
b12d32dfba release: версия 0.0.38
Some checks are pending
CI / backend (push) Waiting to run
CI / frontend (push) Waiting to run
2026-08-11 02:04:00 +03:00
359f9fd1f5 fix(room): починить чернеющее своё видео в Safari при выключении фона
Safari гасил собственный обходной путь для чёрного кадра — охрана от
мерцания в livekit-client сравнивает srcObject с тем же объектом
MediaStream, а detach/attach внутри библиотеки промахивался мимо
обработанного трека и мутировал поток на месте. Переприцепляем
элементы вручную после stopProcessor(), чтобы пересоздать MediaStream
и дать защите сработать штатно.
2026-08-11 02:03:24 +03:00
5 changed files with 30 additions and 3 deletions

View File

@@ -133,7 +133,7 @@ SMTP_TIMEOUT_S=30
# --- Версия инстанса (релиз v0.0.1) --- # --- Версия инстанса (релиз v0.0.1) ---
# install.sh копирует значение из корневого файла VERSION при каждой # install.sh копирует значение из корневого файла VERSION при каждой
# установке/обновлении — руками менять не нужно. # установке/обновлении — руками менять не нужно.
VIDCONF_VERSION=0.0.37 VIDCONF_VERSION=0.0.38
# --- Профили compose. Дефолт ниже (`media,monitoring`) — только для ручного # --- Профили compose. Дефолт ниже (`media,monitoring`) — только для ручного
# `docker compose up` БЕЗ install.sh: медиа (LiveKit+coturn) + мониторинг, # `docker compose up` БЕЗ install.sh: медиа (LiveKit+coturn) + мониторинг,

View File

@@ -3,6 +3,17 @@
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/), Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/),
проект придерживается [семантического версионирования](https://semver.org/lang/ru/). проект придерживается [семантического версионирования](https://semver.org/lang/ru/).
## [0.0.38] — 2026-08-11
### Исправлено
- Safari: при выключении виртуального фона в комнате чернело собственное
видео (остальные участники видели картинку нормально). Причина —
внутренняя охрана livekit-client от мерцания сравнивала `srcObject` с
тем же объектом `MediaStream` и из-за этого не давала сработать
собственному обходному пути библиотеки для чёрного кадра в Safari.
Теперь после остановки процессора фона элементы принудительно
переприцепляются (`detach`/`attach`), пересоздавая `MediaStream`.
## [0.0.37] — 2026-08-10 ## [0.0.37] — 2026-08-10
Закрытие технического долга. Без изменений в продуктовой логике, кроме Закрытие технического долга. Без изменений в продуктовой логике, кроме

View File

@@ -1 +1 @@
0.0.37 0.0.38

View File

@@ -94,7 +94,7 @@ services:
MEDIA_ROOT: ${MEDIA_ROOT:-/app/media} MEDIA_ROOT: ${MEDIA_ROOT:-/app/media}
# Версия инстанса (релиз v0.0.1) — install.sh копирует значение # Версия инстанса (релиз v0.0.1) — install.sh копирует значение
# из файла VERSION (корень репозитория) в .env; отдаётся в GET /api/health. # из файла VERSION (корень репозитория) в .env; отдаётся в GET /api/health.
VIDCONF_VERSION: ${VIDCONF_VERSION:-0.0.37} VIDCONF_VERSION: ${VIDCONF_VERSION:-0.0.38}
# Число процессов uvicorn (см. backend/Dockerfile). Дефолт 2 рассчитан # Число процессов uvicorn (см. backend/Dockerfile). Дефолт 2 рассчитан
# на 4-ядерный сервер, где ядра делятся с LiveKit. Поднимая значение, # на 4-ядерный сервер, где ядра делятся с LiveKit. Поднимая значение,
# проверьте бюджет соединений с БД: каждый воркер держит свой пул # проверьте бюджет соединений с БД: каждый воркер держит свой пул

View File

@@ -103,6 +103,22 @@ export function useVirtualBackground(
if (!track || !desiredUrl) { if (!track || !desiredUrl) {
if (track && processorRef.current) { if (track && processorRef.current) {
await track.stopProcessor() await track.stopProcessor()
// Safari-обход: `stopProcessor` внутри livekit-client меняет трек
// в элементе «на месте», переиспользуя тот же объект `MediaStream`
// (внутренний `detach` промахивается мимо обработанного трека,
// который реально висел в элементе). Из-за этого собственная
// защита библиотеки от мерцания (`srcObject !== mediaStream` в
// `attachToElement`) не даёт сработать её же обходному пути для
// чёрного кадра в Safari. Пересоздаём `MediaStream` вручную —
// detach обнулит `srcObject`, attach создаст новый объект, защита
// пропустит штатный `play()`. Элемент остаётся в своём документе,
// никуда не переезжает. Копия массива обязательна: `detach`
// правит `attachedElements` по ходу перебора. Уберётся, если
// библиотека когда-нибудь починит эту защиту.
for (const el of [...track.attachedElements]) {
track.detach(el)
track.attach(el)
}
await processorRef.current.destroy() await processorRef.current.destroy()
processorRef.current = null processorRef.current = null
} }