diff --git a/apps/admin/src/features/recorder/Recorder.tsx b/apps/admin/src/features/recorder/Recorder.tsx index 165a31f..c81088d 100644 --- a/apps/admin/src/features/recorder/Recorder.tsx +++ b/apps/admin/src/features/recorder/Recorder.tsx @@ -6,6 +6,8 @@ export default function Recorder() { const chunksRef = useRef([]); const [recording, setRecording] = useState(false); const [audioUrl, setAudioUrl] = useState(null); + const [audioBlob, setAudioBlob] = useState(null); + const [uploadKey, setUploadKey] = useState(null); const [error, setError] = useState(''); const requestStream = async (): Promise => { @@ -39,6 +41,7 @@ export default function Recorder() { if (prev) URL.revokeObjectURL(prev); return url; }); + setAudioBlob(blob); // stop all tracks to release mic stream.getTracks().forEach(t => t.stop()); }; @@ -52,6 +55,31 @@ export default function Recorder() { setRecording(false); }; + const uploadAudio = async () => { + try { + setError(''); + setUploadKey(null); + if (!audioBlob) { + setError('No audio to upload'); + return; + } + const form = new FormData(); + form.append('audio', audioBlob, 'recording.webm'); + const res = await fetch('/api/media/audio', { + method: 'POST', + body: form, + }); + if (!res.ok) { + const txt = await res.text(); + throw new Error(`Upload failed: ${res.status} ${txt}`); + } + const data = await res.json(); + setUploadKey(data.key || 'uploaded'); + } catch (e: any) { + setError(e?.message || 'Upload failed'); + } + }; + useEffect(() => { return () => { if (audioUrl) URL.revokeObjectURL(audioUrl); @@ -64,6 +92,7 @@ export default function Recorder() { + {error && {error}} {audioUrl && ( @@ -71,6 +100,11 @@ export default function Recorder() {