Кнопка «Фон» в тулбаре комнаты и выбор фона в превью на входе: три готовые
сцены и свои картинки из профиля. Фон применяется процессором к самому
публикуемому треку (`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 и фон молча не включался.
131 lines
6.7 KiB
XML
131 lines
6.7 KiB
XML
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="720" viewBox="0 0 1280 720">
|
||
<title>Офис — дефолтный фон замены фона видео</title>
|
||
<desc>Собственная векторная сцена VidConf. Светлый переговорный угол: окно с
|
||
тёплым светом, стеллаж с книгами и растениями. Центр кадра намеренно спокойный —
|
||
там будет человек, детали вынесены к краям.</desc>
|
||
<defs>
|
||
<linearGradient id="wall" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0" stop-color="#f3ede4"/>
|
||
<stop offset="0.62" stop-color="#e7ded1"/>
|
||
<stop offset="1" stop-color="#d9cebe"/>
|
||
</linearGradient>
|
||
<linearGradient id="floor" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0" stop-color="#c9b49a"/>
|
||
<stop offset="1" stop-color="#a98e70"/>
|
||
</linearGradient>
|
||
<linearGradient id="daylight" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0" stop-color="#fdfaf2"/>
|
||
<stop offset="1" stop-color="#e8eef1"/>
|
||
</linearGradient>
|
||
<linearGradient id="wood" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0" stop-color="#b58a5f"/>
|
||
<stop offset="1" stop-color="#8d6540"/>
|
||
</linearGradient>
|
||
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||
<stop offset="0" stop-color="#fff6de" stop-opacity="0.85"/>
|
||
<stop offset="1" stop-color="#fff6de" stop-opacity="0"/>
|
||
</radialGradient>
|
||
<radialGradient id="vignette" cx="0.5" cy="0.45" r="0.78">
|
||
<stop offset="0.55" stop-color="#000000" stop-opacity="0"/>
|
||
<stop offset="1" stop-color="#3b2d1e" stop-opacity="0.3"/>
|
||
</radialGradient>
|
||
<!-- Мягкое расфокусирование: фон за спиной человека в кадре камеры никогда
|
||
не бывает резким, и резкая графика выдаёт подмену сильнее всего. -->
|
||
<filter id="soft" x="-6%" y="-6%" width="112%" height="112%">
|
||
<feGaussianBlur stdDeviation="5"/>
|
||
</filter>
|
||
<filter id="softer" x="-8%" y="-8%" width="116%" height="116%">
|
||
<feGaussianBlur stdDeviation="10"/>
|
||
</filter>
|
||
</defs>
|
||
|
||
<rect width="1280" height="720" fill="url(#wall)"/>
|
||
|
||
<g filter="url(#soft)">
|
||
<!-- Окно слева -->
|
||
<rect x="52" y="86" width="330" height="392" rx="10" fill="#cbb9a3"/>
|
||
<rect x="66" y="100" width="302" height="364" rx="6" fill="url(#daylight)"/>
|
||
<rect x="212" y="100" width="10" height="364" fill="#cbb9a3"/>
|
||
<rect x="66" y="276" width="302" height="10" fill="#cbb9a3"/>
|
||
<!-- Городская дымка за стеклом -->
|
||
<rect x="66" y="352" width="302" height="112" fill="#dfe6e6" opacity="0.85"/>
|
||
<rect x="96" y="300" width="46" height="164" fill="#d3dcde" opacity="0.7"/>
|
||
<rect x="158" y="330" width="34" height="134" fill="#cfd8db" opacity="0.6"/>
|
||
<rect x="248" y="316" width="52" height="148" fill="#d3dcde" opacity="0.65"/>
|
||
<rect x="314" y="344" width="30" height="120" fill="#cfd8db" opacity="0.55"/>
|
||
|
||
<!-- Стеллаж справа -->
|
||
<rect x="876" y="120" width="352" height="392" rx="8" fill="url(#wood)"/>
|
||
<rect x="892" y="136" width="320" height="112" fill="#e9dcc9" opacity="0.55"/>
|
||
<rect x="892" y="264" width="320" height="112" fill="#e9dcc9" opacity="0.5"/>
|
||
<rect x="892" y="392" width="320" height="104" fill="#e9dcc9" opacity="0.45"/>
|
||
<!-- Книги -->
|
||
<g>
|
||
<rect x="906" y="156" width="18" height="92" fill="#8a5a4a"/>
|
||
<rect x="928" y="168" width="14" height="80" fill="#6c7f6a"/>
|
||
<rect x="946" y="150" width="20" height="98" fill="#c08a4a"/>
|
||
<rect x="970" y="172" width="16" height="76" fill="#4f6478"/>
|
||
<rect x="990" y="160" width="12" height="88" fill="#9d5f5f"/>
|
||
<rect x="1010" y="176" width="22" height="72" fill="#7a6a55"/>
|
||
|
||
<rect x="906" y="292" width="16" height="84" fill="#5f7382"/>
|
||
<rect x="926" y="284" width="20" height="92" fill="#a86f4e"/>
|
||
<rect x="950" y="300" width="14" height="76" fill="#7f8f76"/>
|
||
<rect x="968" y="288" width="18" height="88" fill="#8d5a63"/>
|
||
</g>
|
||
<!-- Растение на полке -->
|
||
<g>
|
||
<path d="M1140 392c-26-14-40-42-34-72 26 6 44 30 44 60z" fill="#4f7a52"/>
|
||
<path d="M1150 392c26-16 38-46 30-76-26 8-42 34-40 64z" fill="#5f8f5f"/>
|
||
<rect x="1128" y="386" width="40" height="30" rx="5" fill="#b98a63"/>
|
||
</g>
|
||
|
||
<!-- Картина на стене между окном и стеллажом -->
|
||
<g>
|
||
<rect x="486" y="150" width="196" height="146" rx="6" fill="#c2a882"/>
|
||
<rect x="498" y="162" width="172" height="122" fill="#eae3d3"/>
|
||
<path d="M498 284l52-58 40 34 44-52 36 76z" fill="#9fb5a2"/>
|
||
<circle cx="622" cy="196" r="16" fill="#e8c579"/>
|
||
</g>
|
||
|
||
<!-- Настольная лампа и край стола справа от картины -->
|
||
<g>
|
||
<rect x="700" y="452" width="220" height="14" rx="4" fill="#c8a878"/>
|
||
<rect x="712" y="466" width="12" height="46" fill="#b2915f"/>
|
||
<rect x="896" y="466" width="12" height="46" fill="#b2915f"/>
|
||
<rect x="792" y="392" width="8" height="60" fill="#6f7b82"/>
|
||
<path d="M760 392l36-52 36 52z" fill="#7f8d95"/>
|
||
<ellipse cx="796" cy="424" rx="54" ry="18" fill="#ffe9b8" opacity="0.5"/>
|
||
</g>
|
||
</g>
|
||
|
||
<!-- Пол -->
|
||
<rect x="0" y="512" width="1280" height="208" fill="url(#floor)"/>
|
||
<rect x="0" y="506" width="1280" height="14" fill="#e9e0d3" opacity="0.7"/>
|
||
|
||
<!-- Крупное растение в левом углу — передний план, размыто сильнее -->
|
||
<g filter="url(#softer)" opacity="0.95">
|
||
<g fill="#3f6b45">
|
||
<ellipse cx="88" cy="508" rx="52" ry="34" transform="rotate(-24 88 508)"/>
|
||
<ellipse cx="206" cy="556" rx="56" ry="36" transform="rotate(18 206 556)"/>
|
||
<ellipse cx="70" cy="596" rx="48" ry="32" transform="rotate(-8 70 596)"/>
|
||
</g>
|
||
<g fill="#4c7f52">
|
||
<ellipse cx="158" cy="486" rx="50" ry="32" transform="rotate(6 158 486)"/>
|
||
<ellipse cx="248" cy="626" rx="46" ry="30" transform="rotate(32 248 626)"/>
|
||
<ellipse cx="124" cy="574" rx="54" ry="34" transform="rotate(-14 124 574)"/>
|
||
</g>
|
||
<g stroke="#35603c" stroke-width="7" fill="none" stroke-linecap="round">
|
||
<path d="M120 668c-16-56-24-108-32-160"/>
|
||
<path d="M132 668c14-52 34-96 62-136"/>
|
||
<path d="M126 668c2-44 20-76 46-96"/>
|
||
</g>
|
||
<rect x="52" y="656" width="150" height="86" rx="14" fill="#9d7550"/>
|
||
<rect x="52" y="656" width="150" height="16" rx="8" fill="#b08a63"/>
|
||
</g>
|
||
|
||
<!-- Свет из окна и общая виньетка -->
|
||
<ellipse cx="300" cy="250" rx="460" ry="330" fill="url(#glow)"/>
|
||
<rect width="1280" height="720" fill="url(#vignette)"/>
|
||
</svg>
|