♻️(frontend) refactor preview track to avoid unnecessary resets
Replace usePreviewTrack approach with manual track management inspired by deprecated LiveKit implementation that only toggles what's needed instead of resetting entire preview track on config changes. Previous approach created new videoTrack when updating audio track, causing video preview to blink black during audio configuration changes. It was also acquiring video streams even when disabled. New implementation: * Initializes tracks once with user permissions for both devices * Manually handles muting/unmuting and device updates * Preserves muted state when changing device IDs * Uses exact device constraints on Chrome for proper device selection Prevents unnecessary track recreation and eliminates preview blinking.
This commit is contained in:
committed by
aleb_the_flash
parent
4e655a0a64
commit
e926b407b1
@@ -32,6 +32,7 @@ import { ToggleDevice } from './join/ToggleDevice'
|
||||
import { SelectDevice } from './join/SelectDevice'
|
||||
import { useResolveDefaultDeviceId } from '../livekit/hooks/useResolveDefaultDevice'
|
||||
import { isSafari } from '@/utils/livekit'
|
||||
import type { LocalUserChoices } from '@/stores/userChoices'
|
||||
|
||||
const onError = (e: Error) => console.error('ERROR', e)
|
||||
|
||||
@@ -116,11 +117,27 @@ export const Join = ({
|
||||
saveProcessorSerialized,
|
||||
} = usePersistentUserChoices()
|
||||
|
||||
const initialUserChoices = useRef<LocalUserChoices | null>(null)
|
||||
|
||||
if (initialUserChoices.current === null) {
|
||||
initialUserChoices.current = {
|
||||
audioEnabled,
|
||||
videoEnabled,
|
||||
audioDeviceId,
|
||||
audioOutputDeviceId,
|
||||
videoDeviceId,
|
||||
processorSerialized,
|
||||
username,
|
||||
}
|
||||
}
|
||||
|
||||
const tracks = usePreviewTracks(
|
||||
{
|
||||
audio: { deviceId: audioDeviceId },
|
||||
video: {
|
||||
deviceId: videoDeviceId,
|
||||
audio: !!initialUserChoices.current && {
|
||||
deviceId: initialUserChoices.current.audioDeviceId,
|
||||
},
|
||||
video: !!initialUserChoices.current && {
|
||||
deviceId: initialUserChoices.current.videoDeviceId,
|
||||
processor:
|
||||
BackgroundProcessorFactory.deserializeProcessor(processorSerialized),
|
||||
},
|
||||
@@ -599,7 +616,16 @@ export const Join = ({
|
||||
<SelectDevice
|
||||
kind="audioinput"
|
||||
id={audioDeviceId}
|
||||
onSubmit={saveAudioInputDeviceId}
|
||||
onSubmit={async (id) => {
|
||||
try {
|
||||
saveAudioInputDeviceId(id)
|
||||
if (audioTrack) {
|
||||
await audioTrack.setDeviceId({ exact: id })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to switch microphone device', err)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{!isSafari() && (
|
||||
@@ -623,7 +649,16 @@ export const Join = ({
|
||||
<SelectDevice
|
||||
kind="videoinput"
|
||||
id={videoDeviceId}
|
||||
onSubmit={saveVideoInputDeviceId}
|
||||
onSubmit={async (id) => {
|
||||
try {
|
||||
saveVideoInputDeviceId(id)
|
||||
if (videoTrack) {
|
||||
await await videoTrack.setDeviceId({ exact: id })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to switch camera device', err)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user