fix(room): замена фона в Safari и Firefox
Проверка поддержки была строже, чем требует библиотека, и молча отрезала два браузера: кнопки выбора фона не было ни в превью, ни в комнате. У `@livekit/track-processors` ДВА конвейера обработки кадров: современный (`MediaStreamTrackProcessor`/`Generator`, только Chrome и производные) и запасной — рисует кадры в canvas и отдаёт `canvas.captureStream()`. Проверка требовала именно современный, хотя запасной путь доступен и в Safari, и в Firefox. Заодно она проверяла `OffscreenCanvas`, но пропускала `VideoFrame`, `createImageBitmap` и WebGL2, которые библиотеке реально нужны. Теперь условие буквально повторяет `supportsBackgroundProcessors()` из самой библиотеки: «умеет считать сегментацию» И «есть хоть какой-то конвейер». При обновлении пакета сверять с ним. Пробный WebGL2-контекст (иначе поддержку не определить) создаётся один раз на жизнь страницы и сразу отпускается через `WEBGL_lose_context`: браузеры держат ограниченное число живых контекстов. Проверено: в Firefox 153 детект возвращает «поддерживается» (современного конвейера нет, запасной есть), в Chrome регрессии нет — процессор поднимается, трек живой.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -61,3 +61,4 @@ frontend/public/mediapipe/wasm/
|
||||
|
||||
# Рабочая страница замера CPU (сессия 35), в репозиторий не идёт.
|
||||
frontend/bg-bench.html
|
||||
frontend/bg-support.html
|
||||
|
||||
@@ -98,21 +98,60 @@ export function resolveBackgroundUrl(
|
||||
}
|
||||
|
||||
/**
|
||||
* Поддерживает ли браузер сегментацию вообще.
|
||||
* Поддерживает ли браузер замену фона.
|
||||
*
|
||||
* Проверяется по наличию API конвейера обработки кадров (Insertable Streams /
|
||||
* `MediaStreamTrackProcessor`) — их нет, например, в Firefox. Проверка
|
||||
* СИНХРОННАЯ и намеренно не трогает саму библиотеку: она нужна до её загрузки,
|
||||
* чтобы не показывать кнопку, которая всё равно не сработает, и не тянуть
|
||||
* мегабайты впустую.
|
||||
* Проверка СИНХРОННАЯ и намеренно не трогает саму библиотеку: решение нужно
|
||||
* ДО её загрузки, чтобы не показывать кнопку, которая не сработает, и не
|
||||
* тянуть мегабайты впустую. Поэтому здесь буквально повторено условие
|
||||
* `supportsBackgroundProcessors()` из `@livekit/track-processors` — при
|
||||
* обновлении пакета сверять с ним.
|
||||
*
|
||||
* ⚠️ Конвейеров у библиотеки ДВА, и требовать современный нельзя:
|
||||
* - современный (`MediaStreamTrackProcessor`/`Generator`, Insertable Streams)
|
||||
* есть только в Chrome и производных;
|
||||
* - запасной рисует кадры в canvas и отдаёт `canvas.captureStream()` — он
|
||||
* работает в Safari и Firefox.
|
||||
*
|
||||
* Первая версия (0.0.35) требовала именно современный конвейер — и фича
|
||||
* молча отсутствовала в Safari и Firefox, хотя запасной путь там доступен.
|
||||
* Условие ниже — «умеет считать сегментацию» И «есть хоть какой-то конвейер».
|
||||
*/
|
||||
export function isVirtualBackgroundSupported(): boolean {
|
||||
if (typeof window === 'undefined') return false
|
||||
return (
|
||||
'MediaStreamTrackProcessor' in window &&
|
||||
'MediaStreamTrackGenerator' in window &&
|
||||
typeof OffscreenCanvas !== 'undefined'
|
||||
)
|
||||
return canRunSegmentation() && hasAnyFramePipeline()
|
||||
}
|
||||
|
||||
/**
|
||||
* Условие `BackgroundTransformer.isSupported`: чем библиотека считает маску и
|
||||
* собирает кадр. WebGL2 проверяется созданием пробного контекста — иначе никак,
|
||||
* но результат кэшируется на всю жизнь страницы: браузеры держат ограниченное
|
||||
* число живых WebGL-контекстов, и создавать новый на каждый рендер нельзя.
|
||||
*/
|
||||
let segmentationSupport: boolean | null = null
|
||||
function canRunSegmentation(): boolean {
|
||||
if (segmentationSupport !== null) return segmentationSupport
|
||||
const hasApis =
|
||||
typeof OffscreenCanvas !== 'undefined' &&
|
||||
typeof VideoFrame !== 'undefined' &&
|
||||
typeof createImageBitmap !== 'undefined'
|
||||
if (!hasApis) {
|
||||
segmentationSupport = false
|
||||
return false
|
||||
}
|
||||
const probe = document.createElement('canvas').getContext('webgl2')
|
||||
// Пробный контекст сразу отпускаем — он больше не нужен, а слот в лимите
|
||||
// браузера занимал бы до сборки мусора.
|
||||
probe?.getExtension('WEBGL_lose_context')?.loseContext()
|
||||
segmentationSupport = Boolean(probe)
|
||||
return segmentationSupport
|
||||
}
|
||||
|
||||
/** Условие `ProcessorWrapper.isSupported`: современный конвейер ЛИБО запасной на canvas. */
|
||||
function hasAnyFramePipeline(): boolean {
|
||||
const modern = 'MediaStreamTrackProcessor' in window && 'MediaStreamTrackGenerator' in window
|
||||
const fallback =
|
||||
typeof HTMLCanvasElement !== 'undefined' && 'captureStream' in HTMLCanvasElement.prototype
|
||||
return modern || fallback
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user