Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-02-24 18:12:00 -08:00
commit f0d893c53a
1 changed files with 9 additions and 24 deletions

View File

@ -339,16 +339,13 @@ export default function VoicePage() {
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
setAudioUrl(url); setAudioUrl(url);
// --- Three-tier transcription cascade --- // Use live transcript immediately (best quality in practice)
const liveResult = wsFullText || (segmentsRef.current.length > 0
// Show immediate live text while we process
const immediateLive = wsFullText || (segmentsRef.current.length > 0
? segmentsRef.current.map(s => s.text).join(' ') ? segmentsRef.current.map(s => s.text).join(' ')
: capturedLive); : capturedLive);
if (immediateLive) setFinalTranscript(immediateLive); setFinalTranscript(liveResult || '');
// Tier 1: Upload + batch API // Upload audio file in background (needed for AUDIO note, not for transcript)
let bestTranscript = '';
try { try {
setStatus({ message: 'Uploading recording...', type: 'loading' }); setStatus({ message: 'Uploading recording...', type: 'loading' });
const uploadForm = new FormData(); const uploadForm = new FormData();
@ -360,36 +357,24 @@ export default function VoicePage() {
setUploadedFileUrl(uploadResult.url); setUploadedFileUrl(uploadResult.url);
setUploadedMimeType(uploadResult.mimeType); setUploadedMimeType(uploadResult.mimeType);
setUploadedFileSize(uploadResult.size); setUploadedFileSize(uploadResult.size);
setStatus({ message: 'Transcribing...', type: 'loading' });
const tForm = new FormData();
tForm.append('audio', blob, 'voice-note.webm');
const tRes = await authFetch('/api/voice/transcribe', { method: 'POST', body: tForm });
if (tRes.ok) {
const tResult = await tRes.json();
bestTranscript = tResult.text || '';
}
} }
} catch { } catch {
console.warn('Tier 1 (batch API) failed'); console.warn('Audio upload failed');
} }
// Tier 2: WebSocket / Web Speech API (already captured) // If no live transcript at all, try offline Parakeet as last resort
if (!bestTranscript) bestTranscript = immediateLive || ''; if (!liveResult) {
// Tier 3: Offline Parakeet.js
if (!bestTranscript) {
try { try {
setStatus({ message: 'Loading offline model...', type: 'loading' }); setStatus({ message: 'Loading offline model...', type: 'loading' });
const { transcribeOffline } = await import('@/lib/parakeetOffline'); const { transcribeOffline } = await import('@/lib/parakeetOffline');
bestTranscript = await transcribeOffline(blob, (p) => setOfflineProgress(p)); const offlineText = await transcribeOffline(blob, (p) => setOfflineProgress(p));
setFinalTranscript(offlineText);
setOfflineProgress(null); setOfflineProgress(null);
} catch { } catch {
setOfflineProgress(null); setOfflineProgress(null);
} }
} }
setFinalTranscript(bestTranscript);
setStatus(null); setStatus(null);
setState('done'); setState('done');
}, [audioUrl, stopSpeechRecognition, cleanupStreaming]); }, [audioUrl, stopSpeechRecognition, cleanupStreaming]);