diff --git a/backend/apps/voice_notes/tasks.py b/backend/apps/voice_notes/tasks.py index ba9ec17..97a3163 100644 --- a/backend/apps/voice_notes/tasks.py +++ b/backend/apps/voice_notes/tasks.py @@ -26,6 +26,9 @@ def transcribe_voice_note_task(self, note_id: int, language: str = 'auto') -> No duration = AudioProcessingService.get_audio_duration(note.audio_file) if duration: note.duration = timedelta(seconds=duration) + # Persist duration before the (slow) transcription call so the UI can + # show the clip length and a meaningful estimate while it processes. + note.save(update_fields=['duration']) result = transcription_service.transcribe_audio(note.audio_file, language) diff --git a/frontend/src/pages/NoteDetailPage.tsx b/frontend/src/pages/NoteDetailPage.tsx index d3ff20e..a9a91ba 100644 --- a/frontend/src/pages/NoteDetailPage.tsx +++ b/frontend/src/pages/NoteDetailPage.tsx @@ -133,12 +133,26 @@ const NoteDetailPage: React.FC = () => { () => voiceNotesAPI.get(noteId), { enabled: !!noteId, + // Poll while transcription is in flight so the page updates itself; stop + // once it reaches a terminal state. + refetchInterval: (data) => (data?.data?.status === 'processing' ? 2500 : false), onError: () => { toast.error('Failed to load voice note'); }, } ); + // Elapsed-time ticker for the processing indicator. + const isProcessing = noteData?.data?.status === 'processing'; + const [elapsed, setElapsed] = useState(0); + useEffect(() => { + if (!isProcessing) return; + const start = Date.now(); + setElapsed(0); + const timer = setInterval(() => setElapsed((Date.now() - start) / 1000), 500); + return () => clearInterval(timer); + }, [isProcessing]); + const { data: foldersData } = useQuery(['folders'], () => foldersAPI.list()); const folders = foldersData?.data || []; @@ -349,14 +363,40 @@ const NoteDetailPage: React.FC = () => { )} - {note.status === 'processing' && ( -
+ Transcribing speech and identifying speakers{clip ? ` in your ${clip} recording` : ''}. + Short clips finish in a few seconds; longer recordings take a bit more. +
+