diff --git a/.changeset/firefox-media-orb.md b/.changeset/firefox-media-orb.md new file mode 100644 index 0000000000..853c387895 --- /dev/null +++ b/.changeset/firefox-media-orb.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +Fix video and audio failing to play on Firefox with "no video with supported format and MIME type found". diff --git a/src/app/components/message/content/AudioContent.tsx b/src/app/components/message/content/AudioContent.tsx index 274b188e9f..0889b1864f 100644 --- a/src/app/components/message/content/AudioContent.tsx +++ b/src/app/components/message/content/AudioContent.tsx @@ -275,6 +275,12 @@ export function AudioContent({ controls={false} autoPlay ref={audioRef} + // See VideoContent: CORS opts this Range-streamed media out of Firefox's ORB. + crossOrigin={ + srcState.status === AsyncStatus.Success && !srcState.data.startsWith('blob:') + ? 'anonymous' + : undefined + } onVolumeChange={(e) => { localStorage.setItem(MEDIA_VOLUME_KEY, String((e.target as HTMLAudioElement).volume)); }} diff --git a/src/app/components/message/content/VideoContent.tsx b/src/app/components/message/content/VideoContent.tsx index 03a03f933e..da6cc81e0a 100644 --- a/src/app/components/message/content/VideoContent.tsx +++ b/src/app/components/message/content/VideoContent.tsx @@ -45,6 +45,7 @@ type RenderVideoProps = { onError: () => void; autoPlay: boolean; controls: boolean; + crossOrigin?: 'anonymous'; }; type VideoContentProps = { body: string; @@ -116,6 +117,11 @@ export const VideoContent = as<'div', VideoContentProps>( } }, [srcState.status]); + const streamsAuthenticatedMedia = + srcState.status === AsyncStatus.Success && + !url.startsWith('http') && + !srcState.data.startsWith('blob:'); + const handleLoad = () => { setLoad(true); setError(false); @@ -195,6 +201,10 @@ export const VideoContent = as<'div', VideoContentProps>( onError: handleError, autoPlay: false, controls: true, + // Firefox blocks media Range responses it cannot sniff as audio/video (mozilla bug + // 1880289); requesting with CORS opts out. External URLs are left alone since we + // cannot assume they send Access-Control-Allow-Origin. + crossOrigin: streamsAuthenticatedMedia ? 'anonymous' : undefined, })} )}