wip handle firefox error

This commit is contained in:
lebaudantoine
2026-08-22 22:02:37 +02:00
parent 06494371cc
commit 13f2c25299
5 changed files with 30 additions and 5 deletions
@@ -14,6 +14,7 @@ import {
type RoomOptions,
VideoPresets,
} from 'livekit-client'
import { getMediaDeviceFailure } from '@/features/rooms/livekit/utils/mediaPermissions'
import { keys } from '@/api/queryKeys'
import { queryClient } from '@/api/queryClient'
import { Screen } from '@/layout/Screen'
@@ -231,7 +232,7 @@ export const Conference = ({
backgroundColor: 'primaryDark.50 !important',
})}
onError={(e) => {
const failure = MediaDeviceFailure.getFailure(e)
const failure = getMediaDeviceFailure(e)
if (failure && failure !== MediaDeviceFailure.Other) return
// connect() was aborted by a disconnect() before the join completed
@@ -14,6 +14,7 @@ import {
type PermissionKind,
} from '@/stores/permissions'
import {
getMediaDeviceFailure,
noteDeviceReady,
onMediaPermissionError,
} from '../utils/mediaPermissions'
@@ -83,7 +84,7 @@ function useWarmupPermissions(): WarmupState {
bothReady()
} catch (error) {
if (
MediaDeviceFailure.getFailure(error as Error) ===
getMediaDeviceFailure(error as Error) ===
MediaDeviceFailure.PermissionDenied &&
!isSystemPermissionError(error)
) {
@@ -21,6 +21,7 @@ import {
syncDeviceAvailability,
} from '@/stores/deviceAvailability'
import { captureMediaEvent } from '@/features/analytics/telemetry'
import { getMediaDeviceFailure } from '../utils/mediaPermissions'
import { getOS } from '@/utils/os'
type MediaDeviceAlert = {
@@ -63,7 +64,7 @@ export const useWatchMediaDeviceErrors = (): MediaDeviceAlert & {
useEffect(() => {
const onDeviceError = (error: Error, kind?: MediaDeviceKind) => {
const failure = MediaDeviceFailure.getFailure(error)
const failure = getMediaDeviceFailure(error)
if (!failure) return
if (failure != MediaDeviceFailure.Other) {
void captureMediaEvent('media-device-error', {
@@ -1,5 +1,6 @@
import { isWeb } from '@livekit/components-core'
import { MediaDeviceFailure, Track } from 'livekit-client'
import { getMediaDeviceFailure } from '../utils/mediaPermissions'
import React, { useState } from 'react'
import {
ConnectionStateToast,
@@ -101,7 +102,7 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
}
}
if (MediaDeviceFailure.getFailure(error) != MediaDeviceFailure.Other) {
if (getMediaDeviceFailure(error) !== MediaDeviceFailure.Other) {
return
}
@@ -22,6 +22,27 @@ import { getOS } from '@/utils/os'
*/
export type MediaPath = 'join_preview' | 'room'
/**
* LiveKit only maps NotReadableError/TrackStartError to DeviceInUse.
* Firefox reports a device held by another app as
* `AbortError: Starting videoinput failed` (or audioinput), which LiveKit
* classifies as Other. Normalise it here; every classification in the app
* should go through this instead of MediaDeviceFailure.getFailure.
*/
export const getMediaDeviceFailure = (
error: Error
): MediaDeviceFailure | undefined => {
const failure = MediaDeviceFailure.getFailure(error)
if (
failure === MediaDeviceFailure.Other &&
error.name === 'AbortError' &&
/^Starting (video|audio)input failed/i.test(error.message)
) {
return MediaDeviceFailure.DeviceInUse
}
return failure
}
export const PERMISSION_KIND: Record<
'audioinput' | 'videoinput',
PermissionKind
@@ -40,7 +61,7 @@ export const onMediaPermissionError = (
kind?: PermissionKind,
path: MediaPath = 'join_preview'
) => {
const failure = MediaDeviceFailure.getFailure(e)
const failure = getMediaDeviceFailure(e)
if (failure === MediaDeviceFailure.PermissionDenied) {
void classifyPermissionError(e, kind).then((scope) => {