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:
@@ -1,3 +1,4 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { Mic, MicOff, Video, VideoOff } from 'lucide-react'
|
||||
import type { DeviceCheckStatus } from '@/hooks/useDeviceCheckAccess'
|
||||
import '@/styles/device-check.css'
|
||||
@@ -17,6 +18,13 @@ interface DeviceCheckCardProps {
|
||||
audioEnabled: boolean
|
||||
onToggleVideo: () => void
|
||||
onToggleAudio: () => void
|
||||
/**
|
||||
* Выбор фона под кнопками (сессия 35) — приходит готовым узлом, а не набором
|
||||
* пропсов: карточка про доступ к устройствам и знать про фоны, их лимиты и
|
||||
* загрузку не обязана. `undefined` — модуль выключен, устройство не
|
||||
* десктопное либо браузер не умеет сегментацию; тогда блока нет вовсе.
|
||||
*/
|
||||
backgroundPicker?: ReactNode
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +56,7 @@ export function DeviceCheckCard({
|
||||
audioEnabled,
|
||||
onToggleVideo,
|
||||
onToggleAudio,
|
||||
backgroundPicker,
|
||||
}: DeviceCheckCardProps) {
|
||||
const showPlaceholder = videoStatus !== 'granted' || !videoEnabled
|
||||
return (
|
||||
@@ -86,6 +95,8 @@ export function DeviceCheckCard({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{backgroundPicker && <div className="device-check-backgrounds">{backgroundPicker}</div>}
|
||||
|
||||
{hint && <p className="field-hint device-check-hint">{hint}</p>}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user