fix(recorder): choose supported MediaRecorder mime (webm/mp4) and use it for blob/upload to improve playback compatibility
This commit is contained in:
parent
d0398408ac
commit
dde15813be
@ -4,6 +4,7 @@ import { Box, Button, Stack, Typography } from '@mui/material';
|
|||||||
export default function Recorder({ onTranscript }: { onTranscript?: (t: string) => void }) {
|
export default function Recorder({ onTranscript }: { onTranscript?: (t: string) => void }) {
|
||||||
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
|
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
|
||||||
const chunksRef = useRef<Blob[]>([]);
|
const chunksRef = useRef<Blob[]>([]);
|
||||||
|
const mimeRef = useRef<string>('audio/webm');
|
||||||
const [recording, setRecording] = useState(false);
|
const [recording, setRecording] = useState(false);
|
||||||
const [audioUrl, setAudioUrl] = useState<string | null>(null);
|
const [audioUrl, setAudioUrl] = useState<string | null>(null);
|
||||||
const [audioBlob, setAudioBlob] = useState<Blob | null>(null);
|
const [audioBlob, setAudioBlob] = useState<Blob | null>(null);
|
||||||
@ -29,7 +30,24 @@ export default function Recorder({ onTranscript }: { onTranscript?: (t: string)
|
|||||||
const stream = await requestStream();
|
const stream = await requestStream();
|
||||||
if (!stream) return;
|
if (!stream) return;
|
||||||
|
|
||||||
const mr = new MediaRecorder(stream);
|
// Pick a supported mimeType (Safari prefers audio/mp4, Chrome supports audio/webm)
|
||||||
|
const candidates = [
|
||||||
|
'audio/webm;codecs=opus',
|
||||||
|
'audio/webm',
|
||||||
|
'audio/mp4;codecs=opus',
|
||||||
|
'audio/mp4'
|
||||||
|
];
|
||||||
|
let selected: string | undefined;
|
||||||
|
for (const c of candidates) {
|
||||||
|
// @ts-ignore
|
||||||
|
if ((window as any).MediaRecorder && MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported(c)) {
|
||||||
|
selected = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mimeRef.current = selected || 'audio/webm';
|
||||||
|
|
||||||
|
const mr = selected ? new MediaRecorder(stream, { mimeType: selected }) : new MediaRecorder(stream);
|
||||||
mediaRecorderRef.current = mr;
|
mediaRecorderRef.current = mr;
|
||||||
chunksRef.current = [];
|
chunksRef.current = [];
|
||||||
|
|
||||||
@ -39,7 +57,7 @@ export default function Recorder({ onTranscript }: { onTranscript?: (t: string)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
mr.onstop = () => {
|
mr.onstop = () => {
|
||||||
const blob = new Blob(chunksRef.current, { type: 'audio/webm' });
|
const blob = new Blob(chunksRef.current, { type: mimeRef.current });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
setAudioUrl((prev) => {
|
setAudioUrl((prev) => {
|
||||||
if (prev) URL.revokeObjectURL(prev);
|
if (prev) URL.revokeObjectURL(prev);
|
||||||
@ -71,7 +89,8 @@ export default function Recorder({ onTranscript }: { onTranscript?: (t: string)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
form.append('audio', audioBlob, 'recording.webm');
|
const ext = mimeRef.current.includes('mp4') ? 'm4a' : 'webm';
|
||||||
|
form.append('audio', audioBlob, `recording.${ext}`);
|
||||||
const res = await fetch('/api/media/audio', {
|
const res = await fetch('/api/media/audio', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: form,
|
body: form,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user