How Meetily's Retranscription Feature Re‑processes Recorded Audio: A Complete Technical Guide
Meetily's retranscription feature allows users to re‑run previously recorded meeting audio through the transcription engine with different language, model, or provider settings by executing a batch pipeline in the Rust Tauri backend that emits real‑time progress events and atomically updates the database.
Meetily's retranscription feature operates as a batch‑style analogue to the live transcription pipeline, enabling users to experiment with different AI models or language settings without re‑recording meetings. According to the Meetily source code (Zackriya‑Solutions/meetily), this functionality is fully encapsulated in the Rust Tauri core within frontend/src-tauri/src/audio/retranscription.rs and exposed through three specialized commands that manage the entire workflow from audio decoding to database persistence.
The Three Core Tauri Commands Driving Retranscription
The retranscription workflow is controlled by three distinct Tauri commands registered in frontend/src-tauri/src/lib.rs:
start_retranscription_command– Initiates the batch retranscription process with configurable parameters.cancel_retranscription_command– Signals cancellation via an atomic flag to abort processing.is_retranscription_in_progress_command– Queries the current state to prevent duplicate operations.
When a user clicks "Retranscribe" in the UI, the React frontend invokes start_retranscription_command through the Tauri bridge, passing the meeting ID, folder path, and optional overrides for language, model, and provider.
The 10‑Stage Retranscription Pipeline Explained
The start_retranscription function in retranscription.rs executes a deterministic series of stages, each emitting a retranscription-progress event that the frontend consumes to display real‑time status updates.
Stage 1: Guard & Flag Setup
A RetranscriptionGuard atomically sets the global RETRANSLATION_IN_PROGRESS flag while clearing the RETRANSCRIPTION_CANCELLED flag. This prevents concurrent retranscription operations and establishes the cancellation mechanism.
// From retranscription.rs
RetranscriptionGuard::acquire()?;
RETRANSCRIPTION_CANCELLED.store(false, Ordering::SeqCst);
Stage 2: Locate Audio File
The system locates the source audio using find_audio_file(), which first checks for common filenames (audio.mp4, audio.wav) then scans the meeting folder for any extension defined in constants::AUDIO_EXTENSIONS.
Stage 3: Decode & Resample
The located file undergoes decoding via decode_audio_file() from frontend/src-tauri/src/audio/decoder.rs on a dedicated blocking thread. The audio is then resampled to 16 kHz mono using to_whisper_format to match the engine's input requirements.
Stage 4: Voice‑Activity Detection (VAD)
The get_speech_chunks_with_progress function (defined in frontend/src-tauri/src/audio/vad.rs) processes the audio with a 2‑second redemption window (VAD_REDEMPTION_TIME_MS = 2000). This removes silence while keeping short pauses within speech segments. Valid speech chunks are returned as SpeechSegment structs and emitted as progress updates.
Stage 5: Segment Splitting
To improve transcription accuracy, segments exceeding 25 seconds are split at silence boundaries using split_segment_at_silence(segment, MAX_SEGMENT_SAMPLES). This prevents the engine from processing unwieldy audio chunks.
Stage 6: Engine Selection
The pipeline supports two transcription engines based on the provider parameter:
WhisperEngine– Loaded viaget_or_init_whisper()usingDEFAULT_WHISPER_MODELParakeetEngine– Loaded viaget_or_init_parakeet()usingDEFAULT_PARAKEET_MODEL
Both engines are lazily initialized and cached for subsequent use.
Stage 7: Transcription Loop
Each speech segment is sent to the selected engine using engine.transcribe_audio() or engine.transcribe_audio_with_confidence(). The system skips empty or very short segments (< 100 ms) and aggregates confidence scores across all processed audio.
Stage 8: Database Update
Transcripts are persisted atomically using a SQLx transaction that first deletes existing transcripts for the meeting (DELETE FROM transcripts…) then inserts the new results. This guarantees data consistency even if the operation encounters issues during filesystem operations.
Stage 9: Filesystem Output
The pipeline writes the transcript array to transcripts.json and updates (or creates) metadata.json with retranscription metadata including retranscribed_at, status: "completed", and source: "retranscription".
Stage 10: Completion
A final retranscription-progress event emits stage "complete" with 100% progress, followed by a retranscription-complete event containing a summary payload with segment counts and processing duration.
How Cancellation Works
At any point, the frontend can invoke cancel_retranscription_command, which sets the RETRANSCRIPTION_CANCELLED atomic boolean. Every pipeline stage checks this flag via RETRANSCRIPTION_CANCELLED.load(Ordering::SeqCst), and if set, the task aborts with an anyhow!("Retranscription cancelled") error surfaced through the retranscription-error event.
Configuration Constraints and Provider Requirements
Meetily's retranscription feature only supports Whisper‑based providers. The get_configured_whisper_model function reads the transcript_settings table to validate the current provider. If the user has selected a non‑Whisper provider, the command returns an error requiring the user to switch to a compatible provider before proceeding.
Frontend Integration: React and TypeScript
The UI layer in frontend/src/components/MeetingDetails/RetranscribeDialog.tsx orchestrates the process:
// Initiate retranscription
await invoke('start_retranscription_command', {
meeting_id: meeting.id,
meeting_folder_path: meeting.folder_path,
language: selectedLanguage,
model: selectedModel,
provider: selectedProvider // "localWhisper" or "parakeet"
});
Real‑time progress monitoring uses Tauri's event system:
await listen<RetranscriptionProgress>('retranscription-progress', (event) => {
setProgress(event.payload.progress_percentage);
setStage(event.payload.stage);
setMessage(event.payload.message);
});
Completion and error handling follow a similar pattern:
await listen<RetranscriptionResult>('retranscription-complete', (e) => {
toast.success(`Retranscribed ${e.payload.segments_count} segments`);
});
await listen<RetranscriptionError>('retranscription-error', (e) => {
toast.error(`Retranscription failed: ${e.payload.error}`);
});
Cancellation is triggered simply:
await invoke('cancel_retranscription_command');
Summary
Meetily's retranscription feature provides a robust batch processing pipeline that repurposes the live transcription infrastructure for recorded audio:
- Atomic operations ensure database consistency through transactional updates in
retranscription.rs - Real‑time feedback flows through Tauri events (
retranscription-progress,retranscription-complete) to the React frontend - Flexible engine selection supports both Whisper and Parakeet models with lazy initialization
- Intelligent preprocessing includes VAD with a 2‑second redemption window and automatic segment splitting at 25‑second boundaries
- Safe cancellation uses atomic flags checked at every stage to prevent orphaned processes
Frequently Asked Questions
What file formats does Meetily's retranscription feature support?
The retranscription pipeline supports any audio format listed in constants::AUDIO_EXTENSIONS within the Tauri Rust core. The find_audio_file() function specifically looks for audio.mp4, audio.wav, and other common extensions, while the decode_audio_file() function in decoder.rs handles container decoding and format conversion to the required 16 kHz mono PCM.
Can I cancel a retranscription job after it starts?
Yes. The frontend can invoke cancel_retranscription_command at any time, which sets the RETRANSCRIPTION_CANCELLED atomic flag. The pipeline checks this flag between every stage—including during VAD processing and transcription—and aborts immediately with a cancellation error propagated via the retranscription-error event.
Why does Meetily only allow Whisper providers for retranscription?
The get_configured_whisper_model function explicitly validates that the configured provider is Whisper‑compatible because the retranscription pipeline relies on specific Whisper engine methods like transcribe_audio_with_confidence and the to_whisper_format resampling utility. Support for additional providers would require implementing equivalent batch processing interfaces in their respective engine modules.
How does Meetily ensure no data loss when replacing existing transcripts?
The system uses an atomic SQLx transaction that executes DELETE FROM transcripts WHERE meeting_id = ? followed by bulk INSERT operations for the new segments. This happens before the filesystem writes to transcripts.json, ensuring that either both the database and file updates succeed, or neither persists, maintaining data integrity throughout the retranscription process.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →