# How Incremental Audio Saving with Checkpoints Works in Meetily

> Discover how Meetily's incremental audio saving with checkpoints prevents data loss during recordings, ensuring your sessions are saved reliably.

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

---

**The Meetily desktop app prevents data loss during long recording sessions by writing 30-second MP4 checkpoint files to disk every 1,440,000 samples, then merging them into a single final audio file when the session ends.**

Incremental audio saving with checkpoints is a fault-tolerance mechanism implemented in the Rust-based core of [Zackriya-Solutions/meetily](https://github.com/Zackriya-Solutions/meetily). Instead of holding the entire recording in memory, the system periodically flushes buffered audio to disk as discrete checkpoint files, ensuring that even if the application crashes, the already-captured audio remains recoverable.

## Core Architecture

The implementation spans four layers across the Tauri-based backend. Each layer has a distinct responsibility in the checkpoint lifecycle.

### IncrementalAudioSaver ([`incremental_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/incremental_saver.rs))

The **`IncrementalAudioSaver`** struct in [`frontend/src-tauri/src/audio/incremental_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/incremental_saver.rs) manages the raw audio buffer and checkpoint persistence. It maintains a `checkpoint_buffer` vector that accumulates incoming **f32 PCM samples** and calculates the threshold for flushing data based on the configured sample rate.

Key responsibilities include:
- Calculating `checkpoint_interval_samples` (30 seconds at 48 kHz = 1,440,000 samples)
- Encoding buffered samples to MP4 format using FFmpeg
- Naming checkpoint files sequentially as `audio_chunk_{:03}.mp4` inside a hidden `.checkpoints/` directory
- Generating the FFmpeg concat list ([`concat_list.txt`](https://github.com/Zackriya-Solutions/meetily/blob/main/concat_list.txt)) during finalization

### RecordingSaver ([`recording_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_saver.rs))

Located at [`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`** owns an `Arc<AsyncMutex<IncrementalAudioSaver>>` (named `incremental_saver`). This wrapper instantiates the saver when a meeting starts with the `auto_save` flag enabled and forwards each incoming audio chunk via `save_chunk()`.

The saver handles meeting folder creation and ensures the `.checkpoints/` subdirectory exists before recording begins.

### RecordingManager ([`recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_manager.rs))

The **`RecordingManager`** in [`frontend/src-tauri/src/audio/recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/recording_manager.rs) controls the high-level recording lifecycle. It evaluates the `auto_save` parameter to determine whether checkpointing should be activated for a session and triggers the finalization sequence (`finalize_recording`) when the user stops recording.

### Tauri Command Layer ([`lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/lib.rs))

Three commands exposed in [`frontend/src-tauri/src/lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/lib.rs) allow the React frontend to interact with the checkpoint system:
- **`has_audio_checkpoints`** – Verifies if checkpoint files exist for a given meeting folder
- **`recover_audio_from_checkpoints`** – Merges existing checkpoints into a single audio file after a crash
- **`cleanup_checkpoints`** – Removes the `.checkpoints/` directory following successful finalization

## The Checkpoint Lifecycle

The incremental audio saving process follows a strict six-stage pipeline to ensure data integrity.

### 1. Initialization

When `RecordingSaver::start_meeting` is invoked with `auto_save = true`, the system creates a hidden subdirectory inside the meeting folder:

```rust
let checkpoints_dir = meeting_folder.join(".checkpoints");
std::fs::create_dir_all(&checkpoints_dir)?;

```

This directory stores temporary MP4 segments until finalization.

### 2. Chunk Accumulation

As audio data arrives from the capture device, samples are appended to the `checkpoint_buffer`:

```rust
// Inside incremental_saver.rs
self.checkpoint_buffer.extend_from_slice(&audio_samples);
self.total_samples += audio_samples.len();

```

The buffer grows until it reaches the calculated threshold.

### 3. Checkpoint Trigger

The saver continuously compares `total_samples` against `checkpoint_interval_samples`. When the buffer contains 30 seconds of audio (1,440,000 samples at 48 kHz), the system triggers a flush.

### 4. Saving a Checkpoint

The `save_checkpoint()` method encodes the buffer to MP4 and writes it to disk:

```rust
fn save_checkpoint(&mut self) -> Result<()> {
    if self.checkpoint_buffer.is_empty() {
        warn!("Attempted to save empty checkpoint, skipping");
        return Ok(());
    }
    let checkpoint_path = self.checkpoints_dir
        .join(format!("audio_chunk_{:03}.mp4", self.checkpoint_count));
    
    // Encode checkpoint_buffer to MP4 via FFmpeg
    encode_to_mp4(&self.checkpoint_buffer, &checkpoint_path)?;
    
    self.checkpoint_count += 1;
    self.checkpoint_buffer.clear();
    info!("Saved checkpoint {} to {:?}", self.checkpoint_count, checkpoint_path);
    Ok(())
}

```

Each checkpoint is an independent, playable MP4 file.

### 5. Finalization

When the user stops the recording, `finalize_recording` performs three operations:
1. Saves any remaining data in `checkpoint_buffer` as a final checkpoint
2. Generates a [`concat_list.txt`](https://github.com/Zackriya-Solutions/meetily/blob/main/concat_list.txt) file listing all checkpoints in sequence
3. Invokes FFmpeg with the concat demuxer to produce `audio.mp4` in the meeting root:

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

```

### 6. Cleanup

After successful merging, the system removes the `.checkpoints/` directory to reclaim disk space.

## Crash Recovery and Data Integrity

If the application terminates unexpectedly, the checkpoint files persist on disk. The frontend can detect and recover this data using Tauri commands:

```typescript
// React component checking for recoverable audio
const hasCheckpoints = await invoke('has_audio_checkpoints', {
  meetingFolder: '/path/to/Meetily/Meetings/Team Standup'
});

if (hasCheckpoints) {
  await invoke('recover_audio_from_checkpoints', {
    meetingFolder: '/path/to/Meetily/Meetings/Team Standup'
  });
}

```

The recovery process executes the same FFmpeg concatenation routine used during normal finalization, ensuring consistent output regardless of how the recording ended.

## Implementation Code Examples

### Starting a Recording with Checkpoints Enabled

```rust
use meetily::audio::RecordingSaver;

// Initialize saver with base storage folder
let mut saver = RecordingSaver::new("/home/user/Meetily")?;

// Start meeting with auto_save = true to enable checkpoints
saver.start_meeting("Q4 Planning Session", true)?;

// Audio chunks are automatically checkpointed every 30 seconds
saver.save_audio_chunk(AudioData { samples: pcm_data })?;

```

### Recovering Audio After a Crash

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

async function recoverSession(meetingPath: string): Promise<void> {
  const exists = await invoke('has_audio_checkpoints', {
    meetingFolder: meetingPath
  });
  
  if (exists) {
    await invoke('recover_audio_from_checkpoints', {
      meetingFolder: meetingPath
    });
    await invoke('cleanup_checkpoints', {
      meetingFolder: meetingPath
    });
  }
}

```

### Internal Checkpoint Saving Logic

```rust
// From incremental_saver.rs - threshold checking
fn process_audio_chunk(&mut self, samples: &[f32]) -> Result<()> {
    self.checkpoint_buffer.extend_from_slice(samples);
    
    if self.checkpoint_buffer.len() >= self.checkpoint_interval_samples {
        self.save_checkpoint()?;
    }
    Ok(())
}

```

## Summary

- **Incremental audio saving with checkpoints** in Meetily prevents data loss by flushing 30-second MP4 segments to disk instead of storing the entire recording in memory.
- The **`IncrementalAudioSaver`** manages buffer thresholds (1,440,000 samples) and FFmpeg encoding in [`frontend/src-tauri/src/audio/incremental_saver.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/incremental_saver.rs).
- Checkpoint files follow the naming pattern `audio_chunk_{:03}.mp4` and reside in a hidden `.checkpoints/` folder until finalization.
- The **`RecordingSaver`** and **`RecordingManager`** coordinate to enable checkpointing via the `auto_save` flag and handle the concatenation of segments into a final `audio.mp4`.
- Three Tauri commands—**`has_audio_checkpoints`**, **`recover_audio_from_checkpoints`**, and **`cleanup_checkpoints`**—provide the frontend with tools for crash recovery and cleanup.

## Frequently Asked Questions

### How often does Meetily save audio checkpoints?

Meetily saves audio checkpoints every **30 seconds** of recorded audio. At the default 48 kHz sample rate, this translates to every **1,440,000 samples**. This interval balances data safety with disk I/O overhead, ensuring minimal audio loss in case of crashes while maintaining performance.

### What happens if Meetily crashes during a recording?

If the application crashes, the checkpoint files already written to the `.checkpoints/` directory remain intact on disk. When the app restarts, the frontend can call the **`recover_audio_from_checkpoints`** command, which uses FFmpeg to concatenate all existing `audio_chunk_{:03}.mp4` files into a complete `audio.mp4` file. Only the audio recorded since the last checkpoint (maximum 30 seconds) is lost.

### Where are the checkpoint files stored?

Checkpoint files are stored in a hidden subdirectory named `.checkpoints/` inside the specific meeting folder. For example, if your meeting is named "Team Standup," the checkpoints reside at `~/Meetily/Meetings/Team Standup/.checkpoints/audio_chunk_000.mp4`. This location is created automatically when a meeting starts with `auto_save` enabled.

### How does the final audio file get created from checkpoints?

During finalization, the `IncrementalAudioSaver` first writes any remaining buffered audio as a final checkpoint. It then generates an FFmpeg concat list ([`concat_list.txt`](https://github.com/Zackriya-Solutions/meetily/blob/main/concat_list.txt)) enumerating all checkpoint files in sequence. Finally, it executes `ffmpeg -f concat -safe 0 -i concat_list.txt -c copy audio.mp4` to produce a single concatenated file without re-encoding, preserving original quality and maximizing performance.