fix(камера): не держать превью-камеру весь звонок (лампочка горела при выкл. видео)
Первопричина: LocalVideoControlButton/LocalAudioControlButton на mounted() подписываются на useDevices и держат подписку весь звонок; initializeDevices безусловно грабит камеру (getUserMedia video:true) для превью, хотя кнопкам нужен лишь список устройств. Камера отпускалась только по завершении звонка → индикатор горел при выключенном видео (медиа-конвейер звонка свой трек останавливает корректно, но превью-подсистема — нет). Фикс: разделены подписка на СПИСОК устройств и на ЖИВОЙ превью-поток. streamSubscribersCount + единая точка контроля в updateAudio/VideoStream (без превью-подписчика поток не грабится и останавливается — защищает и от watch). Кнопки звонка: requestStream:false. Диалог настроек — без изменений (превью работает). enableDeviceEvents использует enumerateDevices (без камеры). Сборка OK. НЕ деплоено — ждёт тест-фазу (docs/f7-fixes/camera-led-on-with-video-off.md).
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# Фикс: лампочка камеры горит при выключенном видео в звонке
|
||||
|
||||
**Ветка:** `fix/camera-led-preview` · **Статус:** реализовано, СБОРКА OK, **ждёт тест-фазу** (не деплоено).
|
||||
|
||||
## Симптом
|
||||
Пользователь входит в конференцию с выключенной камерой (или выключает её). Своего видео
|
||||
в звонке нет — но индикатор камеры ноутбука ГОРИТ, будто камера используется. Приватностный баг.
|
||||
|
||||
## Первопричина (по исходникам, высокая уверенность)
|
||||
Два независимых слоя работы с камерой:
|
||||
1. **Медиа-конвейер звонка** (`utils/media/pipeline/MediaDevicesSource.js`) — при выключении видео
|
||||
вызывает `setVideoAllowed(false)` → `track.stop()`. Камеру отпускает КОРРЕКТНО.
|
||||
2. **Превью-подсистема** (`composables/useDevices.js`) — используется диалогом настроек И
|
||||
контрол-кнопками звонка. `initializeDevices()` БЕЗУСЛОВНО грабит камеру:
|
||||
`updateVideoStream()` → `getUserMedia({video:true})`. Отпускает только когда отписались ВСЕ.
|
||||
|
||||
Виновник — контрол-кнопки: `LocalVideoControlButton.vue` и `LocalAudioControlButton.vue` на
|
||||
`mounted()` зовут `subscribeToDevices()` и держат подписку ВЕСЬ звонок (`beforeUnmount` = конец
|
||||
звонка). Первый же подписчик поднимает `initializeDevices()` → камера включается и горит всё время,
|
||||
хотя кнопкам нужен лишь СПИСОК устройств для меню выбора, а не живой поток. У кнопок нет `<video>`
|
||||
превью — поток не показывается, просто удерживает устройство.
|
||||
|
||||
Проверено: `MediaDevicesManager.enableDeviceEvents()` берёт список через `enumerateDevices()` —
|
||||
камеру НЕ трогает. Значит список для меню доступен без превью-потока.
|
||||
|
||||
## Фикс
|
||||
Разделили в `useDevices` два вида подписки:
|
||||
- **список устройств** (нужен всем, камеру не трогает);
|
||||
- **живой превью-поток** (нужен только диалогу настроек, где есть `<video>`).
|
||||
|
||||
Изменения:
|
||||
- `useDevices.js`: новый счётчик `streamSubscribersCount`; `subscribeToDevices({requestStream})` /
|
||||
`unsubscribeFromDevices({requestStream})`; ЕДИНАЯ точка контроля — `updateAudioStream()`/
|
||||
`updateVideoStream()` при `streamSubscribersCount===0` не грабят и останавливают поток (защищает
|
||||
и от `watch(videoInputId)`); `initializeDevices` поднимает потоки только при наличии превью-подписчика.
|
||||
- `LocalVideoControlButton.vue`, `LocalAudioControlButton.vue`: `subscribeToDevices({requestStream:false})`.
|
||||
- `MediaSettings.vue`: без изменений — по умолчанию `requestStream:true` (превью в диалоге работает).
|
||||
|
||||
## Что проверить в тест-фазе
|
||||
1. Вход в звонок с выключенной камерой → лампочка НЕ горит; видео нет. (главный кейс)
|
||||
2. Диалог настроек мультимедиа → превью камеры/микрофона работает; при закрытии камера гаснет.
|
||||
3. Включение видео в звонке → камера работает, видео идёт; выключение → лампочка гаснет.
|
||||
4. Смена камеры/микрофона в меню кнопки во время звонка.
|
||||
5. Виртуальный фон в превью настроек.
|
||||
6. Несколько вкладок/повторные входы — нет «залипшего» потока.
|
||||
Reference in New Issue
Block a user