Hold a user media stream open while we get devices
As per comment.
This commit is contained in:
parent
4a5b69800c
commit
17613837b6
2 changed files with 55 additions and 5 deletions
|
@ -14,10 +14,55 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
/**
|
||||
* Finds a media device with label matching 'deviceName'
|
||||
* @param deviceName The label of the device to look for
|
||||
* @param devices The list of devices to search
|
||||
* @returns A matching media device or undefined if no matching device was found
|
||||
*/
|
||||
export async function findDeviceByName(
|
||||
deviceName: string
|
||||
deviceName: string,
|
||||
devices: MediaDeviceInfo[]
|
||||
): Promise<string | undefined> {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const deviceInfo = devices.find((d) => d.label === deviceName);
|
||||
return deviceInfo?.deviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available audio input/output and video input devices
|
||||
* from the browser: a wrapper around mediaDevices.enumerateDevices()
|
||||
* that requests a stream and holds it while calling enumerateDevices().
|
||||
* This is because some browsers (Firefox) only return device labels when
|
||||
* the app has an active user media stream. In Chrome, this will get a
|
||||
* stream from the default camera which can mean, for example, that the
|
||||
* light for the FaceTime camera turns on briefly even if you selected
|
||||
* another camera. Once the Permissions API
|
||||
* (https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)
|
||||
* is ready for primetime, this should allow us to avoid this.
|
||||
*
|
||||
* @return The available media devices
|
||||
*/
|
||||
export async function getDevices(): Promise<MediaDeviceInfo[]> {
|
||||
let stream;
|
||||
try {
|
||||
stream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: true,
|
||||
video: true,
|
||||
});
|
||||
} catch (e) {
|
||||
logger.info("Couldn't get media stream for enumerateDevices: failing");
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
return await navigator.mediaDevices.enumerateDevices();
|
||||
} catch (error) {
|
||||
logger.warn("Unable to refresh WebRTC Devices: ", error);
|
||||
} finally {
|
||||
for (const track of stream.getTracks()) {
|
||||
track.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import { useRoomAvatar } from "./useRoomAvatar";
|
|||
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
|
||||
import { useLocationNavigation } from "../useLocationNavigation";
|
||||
import { useMediaHandler } from "../settings/useMediaHandler";
|
||||
import { findDeviceByName } from "../media-utils";
|
||||
import { findDeviceByName, getDevices } from "../media-utils";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -96,11 +96,16 @@ export function GroupCallView({
|
|||
if (widget && preload) {
|
||||
// In preload mode, wait for a join action before entering
|
||||
const onJoin = async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
// Get the available devices so we can match the selected device
|
||||
// to its ID. This involves getting a media stream (see docs on
|
||||
// the function) so we only do it once and re-use the result.
|
||||
const devices = await getDevices();
|
||||
|
||||
const { audioInput, videoInput } = ev.detail
|
||||
.data as unknown as JoinCallData;
|
||||
|
||||
if (audioInput !== null) {
|
||||
const deviceId = await findDeviceByName(audioInput);
|
||||
const deviceId = await findDeviceByName(audioInput, devices);
|
||||
if (!deviceId) {
|
||||
logger.warn("Unknown audio input: " + audioInput);
|
||||
} else {
|
||||
|
@ -112,7 +117,7 @@ export function GroupCallView({
|
|||
}
|
||||
|
||||
if (videoInput !== null) {
|
||||
const deviceId = await findDeviceByName(videoInput);
|
||||
const deviceId = await findDeviceByName(videoInput, devices);
|
||||
if (!deviceId) {
|
||||
logger.warn("Unknown video input: " + videoInput);
|
||||
} else {
|
||||
|
|
Loading…
Add table
Reference in a new issue