# How Meetily's Retranscription Module Reprocesses Meeting Audio

> Discover how Meetily's retranscription module reprocesses meeting audio efficiently using Rust and Whisper. Learn about its unique concurrency control and chunked processing for updated transcriptions.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: internals
- Published: 2026-07-14

---

**Meetily's retranscription module uses a Rust-based Tauri backend to reprocess recorded meeting audio through Whisper, employing a global atomic flag for concurrency control, chunked 30-second audio processing, and metadata tracking to update transcription results without re-recording.**

Meetily (from Zackriya-Solutions/meetily) provides a powerful retranscription feature that allows users to re-run Whisper transcription on previously recorded meetings. This functionality, implemented entirely in the Rust Tauri backend, enables users to experiment with different languages, models, or providers while maintaining data integrity through atomic state management and persistent metadata updates.

## Command Registration and Public API

The retranscription feature exposes three Tauri commands in [`frontend/src-tauri/src/lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/lib.rs) (lines 742-744):

- **`start_retranscription_command`** – Launches a background retranscription task with configurable parameters
- **`cancel_retranscription_command`** – Stops an in-progress job and releases the atomic lock
- **`is_retranscription_in_progress_command`** – Reports the current processing state to prevent duplicate invocations

These commands form the public API that the TypeScript frontend invokes to manage the retranscription lifecycle.

## Core Retranscription Logic

The heavy lifting occurs in [`frontend/src-tauri/src/audio/retranscription.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/retranscription.rs), which orchestrates audio decoding, Whisper inference, and result aggregation.

### Concurrency Control with Atomic Flags

To prevent race conditions, the module uses a **global atomic flag** named `RETRANSLATION_IN_PROGRESS` (lines 19-26):

```rust
use std::sync::atomic::{AtomicBool, Ordering};

static RETRANSLATION_IN_PROGRESS: AtomicBool = AtomicBool::new(false);

```

When `start_retranscription` (lines 89-105) receives a request, it attempts to swap the flag to `true` using `Ordering::SeqCst`. If the flag is already set, the function returns an error immediately, ensuring only one retranscription job runs concurrently.

### The Audio Processing Pipeline

The `run_retranscription` function (lines 171-188) executes the actual processing workflow:

1. **Audio Decoding**: The `decoder` module reads the stored `.wav` or `.mp3` file from the meeting folder (see [`audio/decoder.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/audio/decoder.rs))
2. **Whisper Engine Initialization**: `whisper_engine::WhisperEngine` instantiates with the user-selected model and provider
3. **Chunked Transcription**: The audio stream splits into **30-second windows**, with each window sent to Whisper for inference
4. **Progress Emission**: The backend emits `retranscription-progress` events (line 510) to update the frontend UI with real-time status

This chunked approach prevents memory exhaustion on large meeting files while maintaining transcription accuracy.

## Metadata Persistence and Provenance

After successful completion, `write_retranscription_metadata` (lines 723-756) updates the meeting's [`metadata.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/metadata.json):

```rust
fn write_retranscription_metadata(path: &Path) -> anyhow::Result<()> {
    let mut obj = read_json(path)?;
    let now = chrono::Utc::now().to_rfc3339();
    obj.insert("retranscribed_at".into(), json!(now));
    obj.insert("source".into(), json!("retranscription"));
    write_json(path, &obj)
}

```

This preserves existing fields while adding a `retranscribed_at` timestamp and marking the `source` as `"retranscription"`, creating a clear audit trail of the processing history.

## Cancellation and State Guarding

The module provides safe cancellation through `cancel_retransmission` (lines 84-85), which clears the atomic flag and aborts the background task. Additionally, all public command wrappers (lines 823-831) first verify `is_retranscription_in_progress` to reject duplicate invocations before processing begins.

## Module Organization

The retranscription utilities are re-exported from [`frontend/src-tauri/src/audio/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/mod.rs) (line 49), making them available to the broader backend while maintaining clean separation of concerns.

## Frontend Integration

To initiate retranscription from the TypeScript frontend:

```typescript
await invoke('start_retranscription_command', {
  meeting_id: '2024-07-14-09-00',
  meeting_folder_path: '/path/to/meeting',
  language: 'en',
  model: 'base',
  provider: 'whisper'
});

```

The backend handles the request asynchronously, emitting progress events until the final metadata update completes.

## Summary

- **Atomic concurrency control**: The `RETRANSLATION_IN_PROGRESS` flag prevents simultaneous retranscription jobs using `Ordering::SeqCst` for thread safety
- **Chunked processing**: Audio splits into 30-second windows to balance memory usage and Whisper API efficiency
- **Metadata provenance**: Each run updates [`metadata.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/metadata.json) with `retranscribed_at` timestamps and `"retranscription"` source tags
- **Safe cancellation**: Background tasks can be aborted via `cancel_retranscription_command`, which clears the atomic lock and halts processing
- **Rust-based architecture**: The entire workflow runs in the Tauri backend ([`frontend/src-tauri/src/audio/retranscription.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/retranscription.rs)), isolating heavy audio processing from the frontend

## Frequently Asked Questions

### How does Meetily prevent concurrent retranscription jobs?

The system uses a global `AtomicBool` named `RETRANSLATION_IN_PROGRESS` that is checked atomically before starting any new job. If the flag is already `true`, the `start_retranscription` function returns an error immediately, ensuring only one retranscription process runs at a time to prevent resource conflicts and data corruption.

### What audio formats does the retranscription module support?

According to the source code in [`frontend/src-tauri/src/audio/decoder.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/decoder.rs), the module reads stored `.wav` and `.mp3` files from the meeting folder. The decoder handles format conversion before passing raw audio to the Whisper engine for transcription.

### Can users change the Whisper model or language during retranscription?

Yes. The `start_retranscription` function accepts optional parameters for `language`, `model`, and `provider`. Users can reprocess existing meeting files with different Whisper models (e.g., switching from `base` to `large`) or translate to different languages without re-recording the original audio.

### Where does Meetily store retranscription timestamps?

After successful completion, the `write_retranscription_metadata` function (lines 723-756 in [`retranscription.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/retranscription.rs)) updates the meeting's [`metadata.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/metadata.json) file with a `retranscribed_at` field containing the ISO 8601 timestamp and sets the `source` field to `"retranscription"`, creating a permanent record of when and how the transcription was generated.