How Meetily’s Incremental Audio Saver Ensures Recording Persistence During Crashes and Power Loss
Meetily’s incremental audio saver writes raw audio to disk in 30-second atomic checkpoint files, enabling complete recording recovery after unexpected crashes or power failures through automated FFmpeg merging.
Meetily is an open-source meeting assistant built with Tauri and Rust. Its incremental audio saver module ensures no recorded audio is lost during system interruptions by persisting data to disk every 30 seconds rather than buffering entirely in memory.
Core Architecture of the Two-Stage Pipeline
The system implements a two-stage pipeline that separates continuous audio capture from final file assembly. This design minimizes memory usage while maximizing durability against process termination.
The 30-Second Checkpoint Strategy
In frontend/src-tauri/src/audio/incremental_saver.rs, the add_chunk() method (lines 52-70) accumulates audio samples and monitors the total count against checkpoint_interval_samples. When the buffer reaches the 30-second threshold, the system triggers save_checkpoint() to flush data to disk.
This frequent flushing ensures that maximum data loss is limited to 30 seconds of audio if a crash occurs between checkpoints.
Atomic Checkpoint Persistence
Each checkpoint file is written using atomic operations to prevent corruption during write operations or power loss.
Safe File Writing in save_checkpoint()
The save_checkpoint() implementation (lines 77-90 in incremental_saver.rs) encodes buffered samples to MP4 format using encode_single_audio, then writes to a temporary location before renaming. This atomic rename operation guarantees that checkpoint files are never partially written, even if the process terminates mid-write.
Checkpoints are stored in a hidden .checkpoints/ folder within the meeting directory, keeping intermediate files organized and invisible to users during active recording.
Graceful Finalization Process
When recording ends normally, the system consolidates all checkpoints into a single output file without re-encoding.
The finalize() Method
Located at lines 14-45 of incremental_saver.rs, finalize() first saves any remaining buffered audio as a final checkpoint. It then invokes merge_checkpoints() to concatenate all MP4 files using FFmpeg's concat demuxer, which combines segments without re-encoding to preserve audio quality and processing speed.
After successful merging, the .checkpoints/ directory is automatically removed via the cleanup_checkpoints command (lines 73-89) to eliminate temporary data.
Crash Recovery Implementation
If the application crashes or loses power before finalize() executes, the checkpoint files remain intact on disk for later reconstruction.
The recover_audio_from_checkpoints Command
The Tauri command recover_audio_from_checkpoints (lines 38-71 in incremental_saver.rs) scans for existing checkpoint files in the .checkpoints/ folder. It constructs a concat_list.txt file and executes the same FFmpeg concatenation process used during normal finalization.
The command returns an AudioRecoveryStatus enum indicating whether recovery succeeded, partially succeeded, or failed, allowing the frontend to notify users appropriately.
Automatic Recovery on Startup
Meetily can invoke this recovery command automatically on application startup. If a meeting folder contains orphaned checkpoints from a previous crash, the system reconstructs the audio.mp4 file without requiring user intervention.
Practical Implementation Examples
To enable incremental saving when starting a recording session:
let mut saver = RecordingSaver::new();
saver.set_meeting_name(Some("Team Sync".into()));
let audio_sender = saver.start_accumulation(true); // true enables incremental saver
// Stream audio chunks from capture pipeline
audio_sender.send(audio_chunk).unwrap();
To finalize and merge checkpoints when stopping:
let final_path = saver
.stop_and_save(&app_handle, Some(recording_duration))
.await?
.expect("Audio was saved");
println!("Final audio stored at {}", final_path);
To recover audio after a crash or power loss:
let recovery = recover_audio_from_checkpoints(
"/path/to/meeting_folder".into(),
48000,
).await?;
match recovery.status.as_str() {
"success" => println!("Recovered: {}", recovery.audio_file_path.unwrap()),
"partial" => println!("Partial recovery: {}", recovery.message),
_ => println!("Recovery failed: {}", recovery.message),
}
Key Source Files
The incremental audio saver spans several modules in the frontend/src-tauri/src/audio/ directory:
incremental_saver.rs– Core checkpoint logic, finalization, and recoveryrecording_saver.rs– Orchestrates recording sessions and meeting folder creationrecording_state.rs– Defines theAudioChunkstructure used for bufferingffmpeg.rs– Providesfind_ffmpeg_path()for checkpoint mergingencode.rs– Implementsencode_single_audiofor MP4 encoding
Summary
- Atomic checkpoints written every 30 seconds ensure no more than half a minute of audio is at risk during crashes
- Disk-based persistence survives process termination and power loss through durable file system operations
- Automatic recovery via
recover_audio_from_checkpointsreconstructs recordings from orphaned checkpoint files - FFmpeg concatenation merges segments without re-encoding, preserving quality and performance
- Cleanup operations remove temporary
.checkpoints/directories only after successful finalization
Frequently Asked Questions
How much audio data could be lost during a system crash?
At most 30 seconds of audio. The checkpoint_interval_samples threshold triggers a disk write every 30 seconds, meaning any crash occurring between checkpoints only loses the buffered audio since the last successful write to the .checkpoints/ folder.
Does the recovery process require manual user intervention?
No. While users can trigger recovery manually via the Tauri command, Meetily can automatically scan for checkpoint files on startup and reconstruct the audio without user action. The AudioRecoveryStatus return value indicates whether the operation succeeded, partially succeeded, or failed.
Why does Meetily use MP4 format for checkpoints instead of raw PCM?
MP4 provides efficient compression while maintaining seekability for FFmpeg concatenation. The encode_single_audio function in encode.rs handles the encoding, allowing the concat demuxer to merge files without re-encoding, which would be computationally expensive with raw PCM streams.
Is incremental saving enabled by default in Meetily?
Incremental saving is opt-in via the start_accumulation(true) parameter in RecordingSaver. When enabled, the system creates the .checkpoints/ directory and begins the 30-second checkpoint cycle; when disabled, audio remains in memory until finalization.
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 →