diff --git a/packages/core/src/components/mediaDeviceSelect.ts b/packages/core/src/components/mediaDeviceSelect.ts index 41ca6cc89..f5093c483 100644 --- a/packages/core/src/components/mediaDeviceSelect.ts +++ b/packages/core/src/components/mediaDeviceSelect.ts @@ -51,7 +51,7 @@ export function setupDeviceSelector( activeDeviceSubject.next(useDefault ? id : actualDeviceId); } else if (localTrack) { await localTrack.setDeviceId(options.exact ? { exact: id } : id); - const actualId = await localTrack.getDeviceId(); + const actualId = await localTrack.getDeviceId(false); activeDeviceSubject.next( id === 'default' && localTrack.mediaStreamTrack.label.startsWith('Default') ? id : actualId, ); diff --git a/packages/core/src/observables/room.ts b/packages/core/src/observables/room.ts index 4359b624f..cf6edbc85 100644 --- a/packages/core/src/observables/room.ts +++ b/packages/core/src/observables/room.ts @@ -246,7 +246,7 @@ export function createActiveDeviceObservable(room: Room, kind: MediaDeviceKind) return roomEventSelector(room, RoomEvent.ActiveDeviceChanged).pipe( filter(([kindOfDevice]) => kindOfDevice === kind), map(([kind, deviceId]) => { - log.debug('activeDeviceObservable | RoomEvent.ActiveDeviceChanged', { kind, deviceId }); + log.info('activeDeviceObservable | RoomEvent.ActiveDeviceChanged', { kind, deviceId }); return deviceId; }), ); diff --git a/packages/core/src/persistent-storage/user-choices.ts b/packages/core/src/persistent-storage/user-choices.ts index 3960f7f39..3542cee05 100644 --- a/packages/core/src/persistent-storage/user-choices.ts +++ b/packages/core/src/persistent-storage/user-choices.ts @@ -39,8 +39,8 @@ export type LocalUserChoices = { export const defaultUserChoices: LocalUserChoices = { videoEnabled: true, audioEnabled: true, - videoDeviceId: '', - audioDeviceId: '', + videoDeviceId: 'default', + audioDeviceId: 'default', username: '', } as const; diff --git a/packages/react/src/components/controls/MediaDeviceSelect.tsx b/packages/react/src/components/controls/MediaDeviceSelect.tsx index e7abd9c99..b5ec469a5 100644 --- a/packages/react/src/components/controls/MediaDeviceSelect.tsx +++ b/packages/react/src/components/controls/MediaDeviceSelect.tsx @@ -113,8 +113,12 @@ export const MediaDeviceSelect: ( [className, props], ); + const hasDefault = !!devices.find((info) => info.label.toLowerCase().startsWith('default')); + function isActive(deviceId: string, activeDeviceId: string, index: number) { - return deviceId === activeDeviceId || (index === 0 && activeDeviceId === 'default'); + return ( + deviceId === activeDeviceId || (!hasDefault && index === 0 && activeDeviceId === 'default') + ); } return ( diff --git a/packages/react/src/hooks/useMediaDeviceSelect.ts b/packages/react/src/hooks/useMediaDeviceSelect.ts index 614959e35..aac431108 100644 --- a/packages/react/src/hooks/useMediaDeviceSelect.ts +++ b/packages/react/src/hooks/useMediaDeviceSelect.ts @@ -1,5 +1,5 @@ import { createMediaDeviceObserver, setupDeviceSelector, log } from '@livekit/components-core'; -import type { LocalAudioTrack, LocalVideoTrack, Room } from 'livekit-client'; +import { getBrowser, type LocalAudioTrack, type LocalVideoTrack, type Room } from 'livekit-client'; import * as React from 'react'; import { useMaybeRoomContext } from '../context'; import { useObservableState } from './internal'; @@ -54,7 +54,7 @@ export function useMediaDeviceSelect({ const devices = useObservableState(deviceObserver, [] as MediaDeviceInfo[]); // Active device management. const [currentDeviceId, setCurrentDeviceId] = React.useState( - roomContext?.getActiveDevice(kind) ?? '', + roomContext?.getActiveDevice(kind) ?? 'default', ); const { className, activeDeviceObservable, setActiveMediaDevice } = React.useMemo( () => setupDeviceSelector(kind, room ?? roomContext, track), @@ -63,10 +63,11 @@ export function useMediaDeviceSelect({ React.useEffect(() => { const listener = activeDeviceObservable.subscribe((deviceId) => { - if (deviceId && deviceId !== currentDeviceId) { - log.info('setCurrentDeviceId', deviceId); - setCurrentDeviceId(deviceId); + if (!deviceId) { + return; } + log.info('setCurrentDeviceId', deviceId); + setCurrentDeviceId(deviceId); }); return () => { listener?.unsubscribe(); diff --git a/packages/react/src/prefabs/ControlBar.tsx b/packages/react/src/prefabs/ControlBar.tsx index 8cc21f11b..0ea908146 100644 --- a/packages/react/src/prefabs/ControlBar.tsx +++ b/packages/react/src/prefabs/ControlBar.tsx @@ -56,7 +56,7 @@ export interface ControlBarProps extends React.HTMLAttributes { export function ControlBar({ variation, controls, - saveUserChoices = true, + saveUserChoices = false, onDeviceError, ...props }: ControlBarProps) { @@ -144,7 +144,9 @@ export function ControlBar({
saveAudioInputDeviceId(deviceId ?? '')} + onActiveDeviceChange={(_kind, deviceId) => + saveAudioInputDeviceId(deviceId ?? 'default') + } />
@@ -162,7 +164,9 @@ export function ControlBar({
saveVideoInputDeviceId(deviceId ?? '')} + onActiveDeviceChange={(_kind, deviceId) => + saveVideoInputDeviceId(deviceId ?? 'default') + } />
diff --git a/packages/react/src/prefabs/PreJoin.tsx b/packages/react/src/prefabs/PreJoin.tsx index 65dd2f34d..b5fd6dfe3 100644 --- a/packages/react/src/prefabs/PreJoin.tsx +++ b/packages/react/src/prefabs/PreJoin.tsx @@ -131,7 +131,7 @@ export function usePreviewDevice( }) : await createLocalAudioTrack({ deviceId }); - const newDeviceId = await track.getDeviceId(); + const newDeviceId = await track.getDeviceId(false); if (newDeviceId && deviceId !== newDeviceId) { prevDeviceId.current = newDeviceId; setLocalDeviceId(newDeviceId); @@ -248,8 +248,8 @@ export function PreJoin({ saveUsername, } = usePersistentUserChoices({ defaults: partialDefaults, - preventSave: !persistUserChoices, - preventLoad: !persistUserChoices, + preventSave: true, + preventLoad: true, }); // Initialize device settings diff --git a/packages/react/src/prefabs/VoiceAssistantControlBar.tsx b/packages/react/src/prefabs/VoiceAssistantControlBar.tsx index 41bf08339..ece660ec6 100644 --- a/packages/react/src/prefabs/VoiceAssistantControlBar.tsx +++ b/packages/react/src/prefabs/VoiceAssistantControlBar.tsx @@ -95,7 +95,9 @@ export function VoiceAssistantControlBar({
saveAudioInputDeviceId(deviceId ?? '')} + onActiveDeviceChange={(_kind, deviceId) => + saveAudioInputDeviceId(deviceId ?? 'default') + } />