feat(room): замена фона видео на картинку — только на десктопе
Кнопка «Фон» в тулбаре комнаты и выбор фона в превью на входе: три готовые
сцены и свои картинки из профиля. Фон применяется процессором к самому
публикуемому треку (`LocalVideoTrack.setProcessor`), а НЕ пересозданием
`RoomOptions` — ссылка на них обязана оставаться стабильной, иначе
`LiveKitRoom` переподключается к комнате.
Фича только для ДЕСКТОПА, и «десктоп» определяется по возможностям устройства
(`pointer: fine` + `hover: hover` + `maxTouchPoints`), а НЕ по ширине окна:
узкое окно на десктопе — всё ещё десктоп, а широкий планшет — всё ещё планшет,
который сегментация греет. На мобильном кнопки нет вовсе, а не задизейбленной.
Ассеты сегментации отдаются СО СВОЕГО домена: библиотека по умолчанию тянет
wasm с jsdelivr, а модель с storage.googleapis.com, и в закрытом контуре фича
молча не работала бы. Модель (Apache 2.0, см. NOTICE.txt) лежит в репозитории,
wasm-рантайм (~19 МБ) копируется из node_modules плагином сборки. Сама
библиотека и модель грузятся ЛЕНИВО — только когда фон реально включают, вход
в конференцию не стал медленнее.
Три дефолтные сцены — собственные векторные рисунки (`design/backgrounds/`),
а не фотографии из интернета: у нарисованной сцены нет чужой лицензии, а
продукт расходится по инсталляциям, и проверять права на каждую копию некому.
Свои картинки — в профиле, до 10 штук, с уменьшением до 1280px и переводом в
WebP прямо в браузере перед отправкой. Удаление применённого сейчас фона
сбрасывает выбор на «без фона»: хранится ключ записи, а не URL картинки.
Смена камеры фон не теряет (`restartTrack` перезапускает процессор сам),
выключение и включение камеры — навешивает его на новый трек заново.
⚠️ Прокси dev-сервера для `/media/` — обязательно со слэшем: ключ `/media`
Vite матчит префиксом и перехватывает заодно `/mediapipe/...`, из-за чего
модель получала 404 и фон молча не включался.
This commit is contained in:
39
frontend/src/lib/isDesktopDevice.ts
Normal file
39
frontend/src/lib/isDesktopDevice.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Замена фона — фича ТОЛЬКО для десктопа (решение оператора от 09.08.2026).
|
||||
*
|
||||
* Причина не в верстке, а в цене: сегментация силуэта считается нейросетью на
|
||||
* КАЖДОМ кадре, пока фон включён. На телефоне это греет устройство, ест
|
||||
* батарею и просаживает FPS в самой встрече — портить основное ради украшения
|
||||
* нельзя.
|
||||
*
|
||||
* ⚠️ Поэтому «десктоп» здесь определяется по ВОЗМОЖНОСТЯМ УСТРОЙСТВА, а не по
|
||||
* ширине окна. `useIsCompactViewport` (мобильный брейкпоинт 600px) для этого
|
||||
* не годится принципиально: узкое окно на десктопе — это по-прежнему десктоп с
|
||||
* его процессором, и прятать там фичу неправильно, а планшет с широким экраном
|
||||
* остаётся устройством, которое сегментация нагреет.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Признаки указывающего устройства:
|
||||
* - `pointer: fine` — точный указатель (мышь/трекпад), у пальца он `coarse`;
|
||||
* - `hover: hover` — указатель может «зависать» над элементом, чего тач не умеет.
|
||||
*
|
||||
* Проверяются ОБА: гибриды вроде ноутбука с сенсорным экраном сообщают
|
||||
* `any-pointer: coarse`, но основным указателем у них остаётся мышь — такое
|
||||
* устройство десктопное, и фича на нём должна быть.
|
||||
*/
|
||||
const DESKTOP_POINTER_QUERY = '(pointer: fine) and (hover: hover)'
|
||||
|
||||
/**
|
||||
* Является ли устройство десктопным (и, значит, можно ли предлагать замену фона).
|
||||
*
|
||||
* Второе условие — `maxTouchPoints`: iPad в Safari по умолчанию притворяется
|
||||
* десктопом (десктопный user-agent, `pointer: fine` при подключённом
|
||||
* трекпаде), но остаётся планшетом с планшетным теплопакетом. Больше двух
|
||||
* точек касания — это тач-устройство, сколько бы мышей к нему ни подключили.
|
||||
*/
|
||||
export function isDesktopDevice(): boolean {
|
||||
if (typeof window === 'undefined') return false
|
||||
if (!window.matchMedia(DESKTOP_POINTER_QUERY).matches) return false
|
||||
return navigator.maxTouchPoints <= 2
|
||||
}
|
||||
Reference in New Issue
Block a user