fix(room): починить чернеющее своё видео в Safari при выключении фона

Safari гасил собственный обходной путь для чёрного кадра — охрана от
мерцания в livekit-client сравнивает srcObject с тем же объектом
MediaStream, а detach/attach внутри библиотеки промахивался мимо
обработанного трека и мутировал поток на месте. Переприцепляем
элементы вручную после stopProcessor(), чтобы пересоздать MediaStream
и дать защите сработать штатно.
This commit is contained in:
2026-08-11 02:03:24 +03:00
parent 41aca319fc
commit 359f9fd1f5

View File

@@ -103,6 +103,22 @@ export function useVirtualBackground(
if (!track || !desiredUrl) {
if (track && processorRef.current) {
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()
processorRef.current = null
}