Firefox audio output issues fix (#1510)

---------

Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
Timo
2023-09-19 15:10:14 +02:00
committed by GitHub
parent c2bc4651cf
commit 4aec5c34f3
4 changed files with 38 additions and 18 deletions

View File

@@ -28,6 +28,7 @@ import { createMediaDeviceObserver } from "@livekit/components-core";
import { Observable } from "rxjs";
import {
isFirefox,
useAudioInput,
useAudioOutput,
useVideoInput,
@@ -65,7 +66,8 @@ function useObservableState<T>(
function useMediaDevice(
kind: MediaDeviceKind,
fallbackDevice: string | undefined,
usingNames: boolean
usingNames: boolean,
alwaysDefault: boolean = false
): MediaDevice {
// Make sure we don't needlessly reset to a device observer without names,
// once permissions are already given
@@ -86,18 +88,19 @@ function useMediaDevice(
const available = useObservableState(deviceObserver, []);
const [selectedId, select] = useState(fallbackDevice);
return useMemo(
() => ({
return useMemo(() => {
const devId = available.some((d) => d.deviceId === selectedId)
? selectedId
: available.some((d) => d.deviceId === fallbackDevice)
? fallbackDevice
: available.at(0)?.deviceId;
return {
available,
selectedId: available.some((d) => d.deviceId === selectedId)
? selectedId
: available.some((d) => d.deviceId === fallbackDevice)
? fallbackDevice
: available.at(0)?.deviceId,
selectedId: alwaysDefault ? undefined : devId,
select,
}),
[available, selectedId, fallbackDevice, select]
);
};
}, [available, selectedId, fallbackDevice, select, alwaysDefault]);
}
const deviceStub: MediaDevice = {
@@ -120,10 +123,17 @@ interface Props {
}
export const MediaDevicesProvider: FC<Props> = ({ children }) => {
// Counts the number of callers currently using device names
// Counts the number of callers currently using device names.
const [numCallersUsingNames, setNumCallersUsingNames] = useState(0);
const usingNames = numCallersUsingNames > 0;
// Use output device names for output devices on all platforms except FF.
const useOutputNames = usingNames && !isFirefox();
// Setting the audio device to sth. else than 'undefined' breaks echo-cancellation
// and even can introduce multiple different output devices for one call.
const alwaysUseDefaultAudio = isFirefox();
const [audioInputSetting, setAudioInputSetting] = useAudioInput();
const [audioOutputSetting, setAudioOutputSetting] = useAudioOutput();
const [videoInputSetting, setVideoInputSetting] = useVideoInput();
@@ -136,7 +146,8 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
const audioOutput = useMediaDevice(
"audiooutput",
audioOutputSetting,
usingNames
useOutputNames,
alwaysUseDefaultAudio
);
const videoInput = useMediaDevice(
"videoinput",
@@ -150,7 +161,9 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
}, [setAudioInputSetting, audioInput.selectedId]);
useEffect(() => {
if (audioOutput.selectedId !== undefined)
// Skip setting state for ff output. Redundent since it is set to always return 'undefined'
// but makes it clear while debugging that this is not happening on FF. + perf ;)
if (audioOutput.selectedId !== undefined && !isFirefox())
setAudioOutputSetting(audioOutput.selectedId);
}, [setAudioOutputSetting, audioOutput.selectedId]);