# How Meetily's Retranscription Feature Re‑processes Recorded Audio: A Complete Technical Guide

> Explore how Meetily's retranscription feature re-processes recorded audio using a Rust Tauri backend batch pipeline. Learn about its technical operation and database updates.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: deep-dive
- Published: 2026-07-18

---

**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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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.

```rust
// 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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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 via `get_or_init_whisper()` using `DEFAULT_WHISPER_MODEL`
- **`ParakeetEngine`** – Loaded via `get_or_init_parakeet()` using `DEFAULT_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`](https://github.com/Zackriya-Solutions/meetily/blob/main/transcripts.json) and updates (or creates) [`metadata.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/MeetingDetails/RetranscribeDialog.tsx) orchestrates the process:

```typescript
// 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:

```typescript
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:

```typescript
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:

```typescript
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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/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`](https://github.com/Zackriya-Solutions/meetily/blob/main/transcripts.json), ensuring that either both the database and file updates succeed, or neither persists, maintaining data integrity throughout the retranscription process.