Switch capture devices if the default device changes
This is a bit of a hack, but is the only way I can see that we can update to using the new default device when the OS-level default changes. Hopefully the comments explain everything.
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
|||||||
ExternalE2EEKeyProvider,
|
ExternalE2EEKeyProvider,
|
||||||
Room,
|
Room,
|
||||||
RoomOptions,
|
RoomOptions,
|
||||||
|
Track,
|
||||||
} from "livekit-client";
|
} from "livekit-client";
|
||||||
import { useLiveKitRoom } from "@livekit/components-react";
|
import { useLiveKitRoom } from "@livekit/components-react";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
@@ -158,6 +159,43 @@ export function useLiveKit(
|
|||||||
if (room !== undefined && connectionState === ConnectionState.Connected) {
|
if (room !== undefined && connectionState === ConnectionState.Connected) {
|
||||||
const syncDevice = (kind: MediaDeviceKind, device: MediaDevice) => {
|
const syncDevice = (kind: MediaDeviceKind, device: MediaDevice) => {
|
||||||
const id = device.selectedId;
|
const id = device.selectedId;
|
||||||
|
|
||||||
|
// Detect if we're trying to use chrome's default device, in which case
|
||||||
|
// we need to to see if the default device has changed to a different device
|
||||||
|
// by comparing the group ID of the device we're using against the group ID
|
||||||
|
// of what the default device is *now*.
|
||||||
|
if (
|
||||||
|
id === "default" &&
|
||||||
|
kind === "audioinput" &&
|
||||||
|
room.options.audioCaptureDefaults?.deviceId === "default"
|
||||||
|
) {
|
||||||
|
const activeMicTrack = Array.from(
|
||||||
|
room.localParticipant.audioTracks.values()
|
||||||
|
).find((d) => d.source === Track.Source.Microphone)?.track;
|
||||||
|
|
||||||
|
const defaultDevice = device.available.find(
|
||||||
|
(d) => d.deviceId === "default"
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
defaultDevice &&
|
||||||
|
activeMicTrack &&
|
||||||
|
// only restart if the stream is still running: LiveKit will detect
|
||||||
|
// when a track stops & restart appropriately, so this is not our job.
|
||||||
|
// Plus, we need to avoid restarting again if the track is already in
|
||||||
|
// the process of being restarted.
|
||||||
|
activeMicTrack.mediaStreamTrack.readyState !== "ended" &&
|
||||||
|
defaultDevice.groupId !==
|
||||||
|
activeMicTrack.mediaStreamTrack.getSettings().groupId
|
||||||
|
) {
|
||||||
|
// It's different, so restart the track, ie. cause Livekit to do another
|
||||||
|
// getUserMedia() call with deviceId: default to get the *new* default device.
|
||||||
|
// Note that room.switchActiveDevice() won't work: Livekit will ignore it because
|
||||||
|
// the deviceId hasn't changed (was & still is default).
|
||||||
|
room.localParticipant
|
||||||
|
.getTrack(Track.Source.Microphone)
|
||||||
|
?.audioTrack?.restartTrack();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (id !== undefined && room.getActiveDevice(kind) !== id) {
|
if (id !== undefined && room.getActiveDevice(kind) !== id) {
|
||||||
room
|
room
|
||||||
.switchActiveDevice(kind, id)
|
.switchActiveDevice(kind, id)
|
||||||
@@ -165,6 +203,7 @@ export function useLiveKit(
|
|||||||
logger.error(`Failed to sync ${kind} device with LiveKit`, e)
|
logger.error(`Failed to sync ${kind} device with LiveKit`, e)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
syncDevice("audioinput", devices.audioInput);
|
syncDevice("audioinput", devices.audioInput);
|
||||||
|
|||||||
Reference in New Issue
Block a user