How Meetily's Retranscription Module Reprocesses Meeting Audio

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 (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, 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):

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)
  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:

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 (line 49), making them available to the broader backend while maintaining clean separation of concerns.

Frontend Integration

To initiate retranscription from the TypeScript frontend:

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 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), 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, 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) updates the meeting's 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →