# How Meetily's Incremental Saver Handles Real-Time Audio File Writing in Rust

> Learn how Meetily's incremental saver in Rust writes real-time audio files by buffering and flushing 30-second MP4 checkpoints for crash recovery and minimal memory use.

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

---

**The IncrementalAudioSaver buffers 30-second chunks of audio data and flushes them to disk as MP4 checkpoints, enabling crash recovery while maintaining minimal memory footprint during recording sessions.**

Meetily is an open-source meeting recording application built with Tauri and Rust that captures simultaneous microphone and system audio streams. When **auto-save** is enabled, the system must continuously persist audio data without exhausting available RAM. The **IncrementalAudioSaver** component solves this by writing audio incrementally to disk rather than accumulating entire sessions in memory.

## Architecture of the Real-Time Audio Pipeline

### Channel-Based Stream Ingestion

In [`frontend/src-tauri/src/audio/recording_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/recording_saver.rs), the `RecordingSaver::start_accumulation` method establishes an unbounded `mpsc` channel to receive `AudioChunk` structs. When `auto_save` is set to `true`, the system calls `initialize_meeting_folder`, which creates a `.checkpoints/` subdirectory and instantiates `IncrementalAudioSaver::new`.

### AudioChunk Structure and Flow

Each `AudioChunk` (defined in [`recording_state.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_state.rs)) contains raw `Vec<f32>` samples captured at 48 kHz, accompanied by timestamp and device type metadata. The audio pipeline produces these chunks continuously and transmits them through the channel to a dedicated accumulation task spawned via `tokio::spawn`.

### The Accumulation Task

While the `is_saving` atomic flag remains `true`, the task iterates over the channel and hands each received chunk to the incremental saver via `incremental_saver.add_chunk(chunk)`. This decouples audio capture from disk I/O, preventing pipeline stalls.

## Checkpoint Strategy and Buffer Management

### 30-Second Flush Threshold

Inside [`frontend/src-tauri/src/audio/incremental_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/incremental_saver.rs), the `add_chunk` method wraps incoming data in an internal `AudioData` struct and appends it to `checkpoint_buffer`. When the buffer accumulates 30 seconds of audio (calculated as `sample_rate * 30` samples), the saver automatically triggers `save_checkpoint`.

### Atomic Checkpoint Writes

The `save_checkpoint` function concatenates all buffered chunks and invokes `encode_single_audio` from [`encode.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/encode.rs). This utility leverages FFmpeg to encode the raw f32 samples into a temporary MP4 file within `.checkpoints/`, named sequentially as `audio_chunk_XXX.mp4`. After writing completes, the checkpoint counter increments and the buffer clears, ensuring only **30 seconds of raw audio** resides in RAM at any moment.

### Memory Efficiency Guarantees

Because the system flushes checkpoints every 30 seconds, memory consumption remains constant regardless of recording duration. This design prevents the OOM (Out of Memory) errors that would occur if the application buffered hours of uncompressed audio data.

## Finalization and Recovery Operations

### Stopping the Recording

When the user ends the session, `RecordingSaver::stop_and_save` clears the `is_saving` flag, allowing the accumulation task to drain remaining chunks. The saver then invokes `incremental_saver.finalize()` to complete the process.

### Merging Checkpoints Without Re-Encoding

The `finalize` method first saves any residual buffered audio as a final checkpoint. It then calls `merge_checkpoints`, which generates a [`concat_list.txt`](https://github.com/Zackriya-Solutions/meetily/blob/main/concat_list.txt) file for FFmpeg and executes:

```bash
ffmpeg -f concat -safe 0 -i concat_list.txt -c copy -y audio.mp4

```

The `-c copy` flag performs a stream copy without re-encoding, producing the final merged file rapidly while preserving original quality. After successful merging, the system deletes the `.checkpoints/` directory.

### Crash Recovery Mechanism

If the application terminates unexpectedly, checkpoint files remain on disk atomically. The frontend can invoke `recover_audio_from_checkpoints` to locate all existing `audio_chunk_XXX.mp4` files and reconstruct the complete audio recording without data loss.

## Implementation Example

```rust
// Initialize the saver with auto-save enabled
let mut saver = RecordingSaver::default();
saver.set_meeting_name(Some("Team Standup".into()));
let audio_sender = saver.start_accumulation(true); // true enables incremental saving

// Stream chunks from the audio pipeline
for chunk in audio_chunks_from_pipeline {
    audio_sender.send(chunk).unwrap();
}

// Finalize when recording stops
let app_handle = app_handle.clone();
let duration = Some(125.3);
let final_path = saver.stop_and_save(&app_handle, duration).await?;
println!("Saved audio at {}", final_path.unwrap());

```

*If `auto_save` were `false`, the saver would skip `IncrementalAudioSaver` initialization and discard raw audio chunks, preserving only transcript segments.*

## Summary

- The **IncrementalAudioSaver** manages real-time audio file writing by buffering 30-second chunks and flushing them to disk as MP4 checkpoints.
- This architecture prevents memory exhaustion during long recording sessions while enabling crash recovery through atomic file writes.
- Finalization uses FFmpeg's concat demuxer with stream copying (`-c copy`) for rapid, lossless merging of checkpoint segments.
- Key source files include [`recording_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_saver.rs) for orchestration, [`incremental_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/incremental_saver.rs) for checkpoint logic, and [`encode.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/encode.rs) for FFmpeg integration.

## Frequently Asked Questions

### How much memory does the incremental saver use during recording?

The system maintains approximately 30 seconds of raw audio samples in memory at any given time. At 48 kHz with 32-bit float samples, this equates to roughly 5.76 MB (48,000 × 30 × 4 bytes), regardless of whether the recording lasts minutes or hours.

### What happens if the application crashes during a recording?

Checkpoint files written to the `.checkpoints/` directory persist on disk atomically. Upon restart, the application can invoke `recover_audio_from_checkpoints` to locate all `audio_chunk_XXX.mp4` files within the meeting folder and reconstruct the complete audio recording without data loss.

### Why does Meetily use 30-second intervals for checkpoints?

The 30-second threshold balances write frequency with I/O overhead. Shorter intervals would increase disk writes and FFmpeg encoding overhead, while longer intervals would increase memory consumption and risk greater data loss during crashes. Thirty seconds provides optimal resilience while maintaining minimal RAM usage.

### Does the final merge operation re-encode the audio?

No. The `merge_checkpoints` function utilizes FFmpeg's concat demuxer with the `-c copy` flag, which performs a stream copy without re-encoding. This preserves original audio quality and minimizes CPU usage during the finalization phase.