How Meetily's Import Feature Processes External Audio Files: A Technical Deep Dive

Meetily converts pre-recorded audio files (MP4, WAV, MP3) into fully searchable meetings by running them through a staged pipeline that validates, decodes, resamples, performs voice-activity detection, and transcribes the content using either Whisper or Parakeet engines.

Meetily, an open-source meeting intelligence platform from Zackriya-Solutions, provides a robust import system that transforms existing recordings into structured meeting data. The import feature processes external audio files through a cancellable, progress-tracked pipeline implemented in Rust within the Tauri backend. This allows users to retroactively analyze interviews, lectures, or archived calls using the same high-quality speech-to-text infrastructure as live recordings.

Import Pipeline Architecture and Safety Mechanisms

The core import logic resides in frontend/src-tauri/src/audio/import.rs, which implements a stateful workflow guarded by global atomic flags. The system uses IMPORT_IN_PROGRESS and IMPORT_CANCELLED flags to ensure only one import runs at a time while allowing safe abortion from the UI.

The ImportGuard RAII type manages these flags automatically, setting IMPORT_IN_PROGRESS on construction and clearing it on drop—even if the thread panics. This prevents zombie states where the application believes an import is still running after a crash.

// Conceptual usage within start_import_audio_command
let _guard = ImportGuard::new();
// ... pipeline executes ...
// Flag cleared automatically when _guard drops

File Selection and Validation

The import process begins with the select_and_validate_audio_command, which opens a native file dialog via tauri_plugin_dialog. Selected files undergo rigorous validation through validate_audio_file:

  • Extension checking against AUDIO_EXTENSIONS (MP4, WAV, MP3)
  • Size validation enforcing a 20 GB maximum limit
  • Duration extraction using a two-tier approach

For duration detection, the system first attempts extract_duration_from_metadata using the symphonia crate for fast metadata probing. If metadata is unavailable or corrupt, it falls back to a full decode pass, ensuring accurate duration reporting without unnecessary overhead for well-formed files.

Meeting Folder Initialization and File Handling

Once validated, the pipeline creates a dedicated meeting folder under the user's recordings directory via create_meeting_folder (defined in audio/common.rs). This generates a unique subdirectory and initializes a placeholder metadata.json file.

The source audio file is then copied into this folder as audio.<ext> using std::fs::copy wrapped in spawn_blocking. This prevents the synchronous I/O operation from blocking the Tokio async runtime, maintaining UI responsiveness during large file transfers.

Audio Decoding and Format Normalization

The copied file proceeds through decode_audio_file_with_progress, which reads the audio into an AudioDecoded struct containing sample rate, channel count, and duration. Progress callbacks emit Tauri events (import-progress) with the stage labeled "decoding".

Next, to_whisper_format_with_progress resamples the audio to Whisper-compatible specifications: 16 kHz sample rate and mono channel format. This standardization ensures optimal transcription accuracy regardless of the source file's original specifications, with progress events emitted under the "resampling" stage.

Voice Activity Detection and Segment Optimization

The normalized audio feeds into get_speech_chunks_with_progress from audio/vad.rs. For batch imports, the VAD uses a 2000 ms redemption time—longer than live capture—to bridge natural pauses in speech without splitting continuous sentences. The function returns a vector of SpeechSegment structs containing raw samples and precise timestamps.

To prevent transcription truncation artifacts, the pipeline checks for segments exceeding 25 seconds. Long segments are split at silence boundaries using split_segment_at_silence (located in audio/common.rs), optimizing chunk sizes for the transcription engine while preserving semantic boundaries.

Transcription Engine Selection and Execution

Meetily supports dual transcription backends selected via the provider parameter:

  • WhisperEngine — OpenAI's Whisper model, loaded lazily via get_or_init_whisper
  • ParakeetEngine — NVIDIA's Parakeet model, initialized via get_or_init_parakeet

The chosen engine processes each speech segment asynchronously, returning transcribed text alongside confidence scores. The engine selection occurs at runtime, allowing users to choose between local Whisper inference or GPU-accelerated Parakeet processing without restarting the application.

Data Persistence and Atomic Output

Successfully transcribed segments are aggregated into TranscriptSegment records by create_transcript_segments (shared utility in audio/common.rs). The system calculates average confidence scores across all segments to provide an overall quality metric.

Database persistence occurs through create_meeting_with_transcripts, which executes within a single SQLite transaction using sqlx. This ensures atomicity—either the meeting and all transcripts commit together, or the entire operation rolls back on failure.

File outputs use atomic write patterns to prevent corruption:

  • write_transcripts_json and write_import_metadata create temporary files first
  • Upon successful write, files are renamed to transcripts.json and metadata.json
  • This prevents partial JSON files from persisting if the application crashes during I/O

Frontend Integration and Progress Monitoring

Throughout the pipeline, emit_progress dispatches Tauri events to the frontend, enabling real-time progress bars. The UI receives import-progress events containing:

  • stage: "copying", "decoding", "resampling", "vad", "transcribing", or "saving"
  • progress_percentage: 0-100 integer
  • message: Human-readable status description

Completion triggers an import-complete event with the meeting ID and processing statistics. Errors emit import-error with diagnostic details, while non-fatal warnings (such as "no speech detected") propagate via import-warning events.

Cancellation is supported through cancel_import_command, which sets IMPORT_CANCELLED. Pipeline stages check this flag at safe boundaries, aborting execution and cleaning up the temporary meeting folder if the user requests termination.

Frontend Implementation Example

To initiate an import from TypeScript:

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

await invoke('start_import_audio_command', {
  sourcePath: '/Users/alice/Downloads/meeting.mp4',
  title: 'Quarterly Review',
  language: 'en',
  model: undefined,      // Use default model
  provider: 'whisper',   // or 'parakeet'
});

Listen for progress updates:

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

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

Cancel an ongoing import:

await invoke('cancel_import_command');

Summary

  • Meetily's import feature converts external audio files into structured meetings using a staged pipeline implemented in frontend/src-tauri/src/audio/import.rs.
  • The system enforces 20 GB file limits, validates formats, and extracts duration using symphonia metadata probing with fallback decoding.
  • Audio processing includes 16 kHz mono resampling, 2000 ms VAD redemption time, and intelligent splitting of segments exceeding 25 seconds.
  • Users can select between Whisper and Parakeet transcription engines, with lazy initialization and confidence scoring.
  • All operations are cancellable via global flags, progress-tracked through Tauri events, and atomically persisted to SQLite and JSON files.

Frequently Asked Questions

What audio file formats does Meetily support for import?

Meetily supports MP4, WAV, and MP3 files through the AUDIO_EXTENSIONS validation check in validate_audio_file. The system uses the symphonia crate for format-agnostic metadata extraction and can handle various codecs within these containers, falling back to full decode analysis when metadata probes fail.

How does Meetily handle large audio files during the import process?

Files up to 20 GB are supported. The pipeline uses spawn_blocking to wrap std::fs::copy operations, preventing synchronous I/O from blocking the async runtime. Decoding and resampling occur in streaming fashion with progress callbacks, ensuring the UI remains responsive even when processing multi-hour recordings.

Can I cancel an audio import after it has started?

Yes. The frontend can invoke cancel_import_command, which sets the global IMPORT_CANCELLED atomic flag. The pipeline checks this flag between stages (copying, decoding, VAD, transcription), aborts cleanly, and removes the partially created meeting folder. The ImportGuard RAII type ensures the IMPORT_IN_PROGRESS flag clears automatically regardless of cancellation or panic.

What is the difference between the Whisper and Parakeet transcription providers?

Whisper (OpenAI) runs via WhisperEngine and provides robust general-purpose transcription suitable for most use cases. Parakeet (NVIDIA) runs via ParakeetEngine and leverages GPU acceleration for potentially faster inference on compatible hardware. Both engines implement the same async trait interface and return confidence scores, allowing seamless substitution via the provider parameter without changing the pipeline logic.

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 →