How the Incremental Audio Saver Prevents Data Loss During Long Recording Sessions in Meetily
TLDR: The incremental audio saver in Meetily caps memory usage to 30 seconds of audio and flushes checkpoints to disk, ensuring that a crash or power loss never loses more than half a minute of recording.
Meetily is an open-source meeting recorder that handles long recording sessions without exhausting system memory or risking total data loss from unexpected crashes. By implementing a checkpoint-based incremental audio saver, the application maintains a constant RAM footprint while continuously persisting audio segments to disk. This architecture, implemented in the Rust backend, guarantees that every recorded minute is safely stored in recoverable MP4 fragments before the next minute begins.
Checkpoint-Based Buffering Strategy
The core protection mechanism relies on a rotating in-memory buffer that never exceeds a 30-second window of audio data. In frontend/src-tauri/src/audio/incremental_saver.rs (lines 17-22), the IncrementalAudioSaver struct maintains a checkpoint_buffer that accumulates mixed audio chunks during active recording.
At a sample rate of 48 kHz, this buffer holds approximately 1,440,000 samples before triggering a flush. This hard limit guarantees that RAM usage remains constant regardless of whether the meeting lasts five minutes or five hours, preventing the memory exhaustion that would occur if the entire session were held in memory.
Automatic Checkpoint Creation Process
Each time the audio pipeline produces a new segment, the add_chunk method appends it to the buffer and checks the accumulated sample count. According to the implementation in incremental_saver.rs (lines 52-73), when the buffer exceeds the 30-second threshold, the saver automatically invokes save_checkpoint and then clears the buffer.
This logic ensures that no more than 30 seconds of audio is ever held only in memory. The process repeats throughout the recording session, creating a sequence of discrete audio segments without user intervention.
Robust Checkpoint File Format
Checkpoints are written as complete MP4 files (audio_chunk_###.mp4) rather than raw binary dumps. As implemented in incremental_saver.rs (lines 91-101), each checkpoint uses the encode_single_audio routine from frontend/src-tauri/src/audio/encode.rs to produce a fully self-contained, independently-decodable audio file.
Because each checkpoint follows standard MP4 formatting, a system crash that occurs after a checkpoint write leaves a recoverable segment on disk. This design eliminates the risk of corrupted partial files that can occur with proprietary streaming formats that require finalization headers.
Graceful Finalization and Merge
When recording stops, the finalize method (lines 14-33 in incremental_saver.rs) writes any remaining buffered audio as a final checkpoint, then merges all checkpoint files into a single audio.mp4. The merge operation uses FFmpeg's concat demuxer, which concatenates segments without re-encoding, preserving original audio quality and completing in seconds regardless of total recording duration.
This approach separates the latency-sensitive recording process from the final assembly step, ensuring that the user interface remains responsive even while processing hours of audio.
Crash Recovery Mechanism
If the application crashes before finalize completes, the Tauri command recover_audio_from_checkpoints (exposed in incremental_saver.rs lines 38-71) scans the .checkpoints directory and rebuilds the full audio file. The command generates an FFmpeg concat list from all discovered checkpoint files and recreates the complete audio.mp4.
Because checkpoints persist on disk immediately after each 30-second window, no audio data is lost even if the process terminates unexpectedly. The recovery command can be invoked manually or automatically on the next application launch via frontend/src-tauri/src/audio/recording_commands.rs.
Automatic Cleanup
After a successful merge or recovery operation, the cleanup_checkpoints command (lines 73-89 in incremental_saver.rs) removes the .checkpoints folder and all temporary MP4 segments. This keeps the meeting directory tidy while preserving the final merged file, preventing disk space leakage from accumulated temporary files over multiple recording sessions.
Implementation Example
The following Rust code demonstrates the typical lifecycle of the incremental audio saver during a recording session:
use std::path::PathBuf;
// 1️⃣ Initialise the saver when a meeting starts (auto-save enabled)
let meeting_folder = PathBuf::from("/path/to/meeting_folder");
let mut saver = IncrementalAudioSaver::new(meeting_folder.clone(), 48_000)?;
// 2️⃣ Add incoming audio chunks (called for each VAD-filtered chunk)
fn on_new_chunk(chunk: AudioChunk) -> Result<()> {
saver.add_chunk(chunk) // ← writes a checkpoint every 30s
}
// 3️⃣ When the user stops recording, finalize the audio file
let final_path = saver.finalize().await?; // Merges all checkpoints → audio.mp4
println!("Saved final recording to {}", final_path.display());
// 4️⃣ If the app crashes before finalize, recover later:
let status = recover_audio_from_checkpoints(
meeting_folder.to_string_lossy().into(),
48_000,
).await?;
println!("Recovery status: {}", status.status);
These calls wrap the methods defined in incremental_saver.rs and integrate with the broader recording workflow managed by recording_saver.rs, using FFmpeg helpers from ffmpeg.rs for binary location and encoding.
Summary
- Bounded memory usage: The
checkpoint_buffernever holds more than 30 seconds of audio, preventing RAM exhaustion during long sessions. - Automatic disk persistence: The
add_chunkmethod triggerssave_checkpointevery 30 seconds, writing independently-decodable MP4 files to disk. - Crash resilience: If the app terminates unexpectedly,
recover_audio_from_checkpointscan reconstruct the full recording from the.checkpointsdirectory. - Fast finalization: The
finalizemethod uses FFmpeg's concat demuxer to merge segments without re-encoding, producing the finalaudio.mp4instantly. - Automatic cleanup: The
cleanup_checkpointscommand removes temporary files after successful merging, maintaining disk hygiene.
Frequently Asked Questions
What happens if Meetily crashes during a recording?
If Meetily crashes before the user stops the recording, the recover_audio_from_checkpoints command can reconstruct the complete audio file. Because the incremental audio saver writes a new MP4 checkpoint to disk every 30 seconds, the maximum data loss is limited to the last half-minute of audio. The recovery process scans the .checkpoints directory, builds an FFmpeg concat list, and merges the segments into a final audio.mp4.
How much RAM does the incremental audio saver use?
The saver uses a fixed memory buffer equivalent to 30 seconds of audio at the configured sample rate (approximately 1,440,000 samples at 48 kHz). This constant footprint applies regardless of the total meeting duration, ensuring that recording a ten-hour session consumes the same RAM as recording a five-minute session.
Can I recover audio if the app closes unexpectedly?
Yes. The checkpoint files are written as standard MP4 containers that are independently decodable. If the application closes or the system loses power, the checkpoint files remain in the meeting's .checkpoints folder. You can recover the audio by invoking the recover_audio_from_checkpoints Tauri command, which concatenates all available checkpoints without re-encoding.
Why does Meetily use MP4 for checkpoints instead of raw PCM?
Meetily uses MP4 files for checkpoints because they are complete, self-contained audio files that can be played independently and concatenated efficiently using FFmpeg's concat demuxer. Raw PCM would require additional metadata tracking and would not support the same level of corruption resilience or ease of recovery that standard MP4 containers provide.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →