How Meetily's Import and Enhance Feature Enables Re-Transcribing Recordings

Meetily's Import and Enhance feature allows users to import external audio files for initial transcription and re-transcribe existing meetings with different AI models or languages by re-running the same Voice Activity Detection (VAD) and transcription pipeline on the original audio.

Meetily is an open-source meeting assistant that provides a complete transcription pipeline for audio processing. The Import functionality creates new meetings from external audio files, while the Enhance capability enables re-transcription with alternative providers like Whisper or Parakeet, or different language settings, without requiring the original source file again.

The Import Pipeline Architecture

The import process follows a strict six-stage pipeline implemented in Rust within the Tauri backend. Each stage emits progress events to keep the frontend responsive while processing large audio files up to 20 GB.

File Selection and Validation

The entry point select_and_validate_audio_command in frontend/src-tauri/src/audio/import.rs opens a native file dialog and performs fast validation checks. This includes verifying file existence, enforcing size limits, checking supported extensions, and extracting duration metadata without loading the entire file into memory.

#[tauri::command]
pub async fn select_and_validate_audio_command<R: Runtime>(
    app: AppHandle<R>,
) -> Result<Option<AudioFileInfo>, String> {
    // Opens native file-picker filtered to supported extensions
    // Validates: existence → size limit (20 GB) → allowed extension → duration
}

If extract_duration_from_metadata succeeds, the system avoids the expensive full audio decode until the user confirms the import.

Audio Decoding and Resampling

Once validation passes, start_import_audio_command checks the global IMPORT_IN_PROGRESS atomic flag to prevent concurrent imports, then spawns the run_import background task. This task copies the source file to a new meeting folder and decodes it using decode_audio_file_with_progress, then resamples the audio to 16 kHz mono PCM using to_whisper_format_with_progress—a requirement for both Whisper and Parakeet transcription engines.

Voice Activity Detection (VAD)

The ContinuousVadProcessor in frontend/src-tauri/src/audio/vad.rs processes the resampled audio to isolate speech chunks while preserving natural utterance boundaries. It configures Silero VAD with specific parameters optimized for batch processing:

  • Sample rate: 16 kHz (required by transcription engines)
  • Redemption time: 2,000 ms (keeps natural pauses within the same utterance)
  • Minimum speech time: 250 ms (prevents tiny fragments that violate Whisper's 100 ms minimum segment rule)
// VAD configuration in vad.rs
ContinuousVadProcessor::new(
    16000,  // sample_rate
    2000,   // redemption_time_ms for batch imports
    250,    // min_speech_time_ms
)

Segmentation and Splitting

Long speech segments exceeding 25 seconds are automatically split at silence boundaries using split_segment_at_silence. This ensures compliance with Whisper's architectural constraints while maintaining semantic coherence by breaking only at natural pauses.

Transcription Engine Execution

Each speech segment is dispatched to the selected transcription provider. The system initializes the appropriate engine via get_or_init_whisper or get_or_init_parakeet in import.rs, then calls engine.transcribe_audio_with_confidence to generate text with confidence scores. The pipeline accumulates results across all segments while maintaining temporal order.

Database Persistence

The final stage inserts a new meeting record into the SQLite database using create_meeting_with_transcripts, writes the transcript array to transcripts.json, and generates metadata.json with import timestamps and configuration details. This creates a complete, queryable meeting record within the Meetily ecosystem.

The Enhance (Retranscription) Workflow

The Enhance feature leverages the same processing pipeline but operates on existing meeting folders rather than creating new ones. When users select "Retranscribe" to switch languages or upgrade from Whisper to Parakeet, the frontend invokes start_retranscription_command located in frontend/src-tauri/src/audio/retranscription.rs.

#[tauri::command]
pub async fn start_retranscription_command<R: Runtime>(
    app: AppHandle<R>,
    meeting_id: String,
    meeting_folder_path: String,
    language: Option<String>,
    model: Option<String>,
    provider: Option<String>,
) -> Result<RetranscriptionStarted, String> {
    // Checks RETRANSCRIPTION_IN_PROGRESS flag
    // Loads existing audio from meeting_folder_path
    // Re-runs stages 3-7 of the import pipeline
}

Unlike import, enhancement works in-place: it reads the existing audio file from the meeting folder, re-processes it through VAD and transcription with the new parameters, overwrites the previous transcripts.json, and updates metadata.json with a retranscribed_at timestamp while preserving original metadata fields.

// Metadata update in retranscription.rs
obj.insert("retranscribed_at".to_string(), serde_json::json!(now));
obj.insert("status".to_string(), serde_json::json!("completed"));

Frontend Integration Examples

Importing New Audio with React

The frontend communicates with the Rust backend via Tauri's invoke API. The following TypeScript example demonstrates file selection and import initiation with progress monitoring:

import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';

async function importExternalAudio() {
  // Step 1: Select and validate
  const info = await invoke('select_and_validate_audio_command');
  if (!info) return; // User cancelled dialog
  
  // Step 2: Start import with specific provider
  await invoke('start_import_audio_command', {
    source_path: info.path,
    title: info.filename,
    language: 'en',
    model: 'large-v3',
    provider: 'whisper', // or 'parakeet'
  });
}

// Monitor progress events
listen('import-progress', (event) => {
  const { stage, progress_percentage, message } = event.payload;
  console.log(`[${stage}] ${progress_percentage}%: ${message}`);
});

Retranscribing Existing Meetings

To enhance an existing meeting with a different language or model:

async function enhanceMeeting(meetingId: string, folderPath: string) {
  await invoke('start_retranscription_command', {
    meeting_id: meetingId,
    meeting_folder_path: folderPath,
    language: 'es',        // Switch to Spanish
    model: 'large-v3',     // Upgrade model size
    provider: 'parakeet',  // Switch provider
  });
}

Both operations emit granular progress events (import-progress or retranscription-progress) and support cancellation via cancel_import_command and cancel_retranscription_command, which set the IMPORT_CANCELLED or RETRANSCRIPTION_CANCELLED atomic flags checked at each pipeline stage.

Cancellation and Concurrency Control

The system maintains separate atomic boolean flags for import and retranscription operations to prevent race conditions:

These flags allow users to cancel long-running transcription jobs without corrupting the database or leaving partial files, as each pipeline stage checks the cancellation flag before proceeding.

Summary

  • Import creates new meetings by validating, copying, and transcribing external audio files through a six-stage pipeline involving VAD, segmentation, and AI transcription.
  • Enhance re-transcribes existing meetings in-place by re-running the same pipeline with different languages, models, or providers, updating metadata with retranscribed_at timestamps.
  • The 16 kHz mono PCM format requirement ensures compatibility with both Whisper and Parakeet engines.
  • Silero VAD with 2-second redemption time and 250 ms minimum speech duration optimizes transcription quality for batch processing.
  • All operations provide granular progress events and cancellation support through Tauri commands in frontend/src-tauri/src/audio/import.rs and retranscription.rs.

Frequently Asked Questions

How does Meetily handle large audio files during import?

Meetily validates file size against a 20 GB limit during the selection phase using select_and_validate_audio_command in frontend/src-tauri/src/audio/import.rs. The system extracts metadata without loading the entire file, then processes audio in chunks during decoding and VAD to maintain low memory footprint regardless of file size.

Can I switch between Whisper and Parakeet providers when re-transcribing?

Yes. The start_retranscription_command accepts a provider parameter that switches between Whisper and Parakeet engines. The pipeline initializes the requested engine via get_or_init_whisper or get_or_init_parakeet, then re-processes the original audio file with the new provider while preserving the meeting ID and folder structure.

What happens to the original transcription when I enhance a meeting?

The enhancement process overwrites the existing transcripts.json file with new results and updates metadata.json with a retranscribed_at timestamp. The original audio file remains untouched in the meeting folder, allowing unlimited re-transcription attempts with different configurations.

Why does Meetily use 16 kHz mono PCM format for transcription?

Both Whisper and Parakeet transcription engines require 16 kHz mono PCM audio input. Meetily's to_whisper_format_with_progress function in the audio processing pipeline handles resampling and channel conversion automatically, ensuring optimal compatibility and transcription accuracy regardless of the source file's original format.

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 →