How Meetily Performs Real-Time Audio Level Monitoring: A Technical Deep Dive
Meetily performs real-time audio level monitoring using a three-layer architecture that bridges TypeScript frontend code with Rust audio processing, calculating RMS and peak levels every 100ms via CPAL streams and Tauri events.
Meetily, an open-source meeting assistant from the Zackriya-Solutions/meetily repository, implements sophisticated real-time audio level monitoring to visualize microphone input during calls. This system leverages Rust's performance for low-latency audio processing while maintaining a reactive TypeScript frontend through Tauri's event system. The architecture processes raw audio samples to compute RMS and peak levels, transmitting updates to the UI every 100 milliseconds.
Three-Layer Architecture for Real-Time Audio Level Monitoring
Tauri Command Layer
The entry point for real-time audio level monitoring resides in frontend/src-tauri/src/lib.rs. This file exposes three primary Tauri commands that handle the lifecycle of the monitoring system:
start_audio_level_monitoring– Initializes monitoring for specified device namesstop_audio_level_monitoring– Terminates active monitoring sessionsis_audio_level_monitoring– Returns the current monitoring state
The start_audio_level_monitoring command accepts a vector of device names from the frontend and forwards the request to the audio subsystem:
#[tauri::command]
async fn start_audio_level_monitoring<R: Runtime>(app: AppHandle<R>, device_names: Vec<String>) -> Result<(), String> {
audio::simple_level_monitor::start_monitoring(app, device_names).await
.map_err(|e| format!("Failed to start audio level monitoring: {}", e))
}
Audio Monitor Module
The core implementation lives in frontend/src-tauri/src/audio/level_monitor.rs. This module handles device discovery, stream management, sample processing, and metric calculation using the following workflow:
- Device Discovery: Uses
cpal::default_host()to enumerate available input devices and matches them against the names supplied by the UI - Stream Construction: Builds input streams via
device.build_input_streamwith callbacks that receive raw audio samples in native format (F32, I16, or U16) - Channel Processing: Converts multi-channel audio to mono using the
audio_to_monohelper fromaudio_processing.rs - Level Calculation: Computes three metrics for each audio buffer:
- RMS level: √(Σx²/N) representing average signal power
- Peak level: max(|x|) indicating the highest instantaneous amplitude
- Active flag: Boolean threshold (rms > 0.001) indicating speech presence
- State Management: Stores results in a thread-safe
Arc<Mutex<Vec<AudioLevelData>>> - Event Emission: A Tokio task gathers data every 100ms, constructs an
AudioLevelUpdatewith timestamp and levels, and emits it viaapp_handle.emit("audio-levels", &update)
A simplified version exists in frontend/src-tauri/src/audio/simple_level_monitor.rs that generates synthetic sinusoidal data for UI testing without accessing hardware.
Frontend Event Handling
The TypeScript frontend subscribes to the "audio-levels" event using Tauri's listen API. When the Rust backend emits updates, the UI receives structured data containing timestamps and per-device metrics (RMS level, peak level, and activity status), enabling near-real-time visual meter updates for each monitored device.
Code Implementation Examples
Starting Monitoring from the Frontend
The following TypeScript pattern initializes monitoring and subscribes to level updates:
import { invoke } from '@tauri-apps/api/tauri';
import { listen } from '@tauri-apps/api/event';
// Start monitoring specific devices
async function startMonitoring() {
const devices = ['Built-in Microphone', 'BlackHole 2ch'];
await invoke('start_audio_level_monitoring', { device_names: devices });
}
// Subscribe to real-time level updates
listen<{ timestamp: number; levels: { device_name: string; rms_level: number; peak_level: number; is_active: boolean }[] }>('audio-levels')
.then(unsub => {
console.log('Listening for audio level updates');
// Call unsub() to stop listening
});
Stopping the Monitor
To terminate active monitoring sessions:
import { invoke } from '@tauri-apps/api/tauri';
async function stopMonitoring() {
await invoke('stop_audio_level_monitoring');
}
Rust Unit Testing
Direct testing of the audio module without the frontend:
#[tokio::test]
async fn test_level_monitor() {
use tauri::test::MockApp;
let app = MockApp::new();
let devices = vec!["Test Mic".to_string()];
audio::level_monitor::AudioLevelMonitor::new()
.start_monitoring(app.handle(), devices)
.await
.expect("Failed to start level monitoring");
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
assert!(audio::level_monitor::is_monitoring());
}
Summary
- Three-layer architecture: Tauri commands in
lib.rsroute to the audio module, which processes CPAL streams and emits events back to the frontend - Core metrics: RMS (√(Σx²/N)), peak amplitude (max|x|), and activity threshold (rms > 0.001) calculated in
level_monitor.rs - 100ms update cycle: Tokio tasks aggregate audio data and emit
AudioLevelUpdateevents viaapp_handle.emit("audio-levels", &update) - Frontend integration: TypeScript uses
invoketo start monitoring andlisten('audio-levels')to receive real-time updates - Testing support: The
simple_level_monitor.rsmodule provides synthetic data generation for UI development without hardware dependencies
Frequently Asked Questions
How does Meetily calculate audio levels from raw samples?
Meetily calculates RMS (Root Mean Square) and peak levels from raw audio buffers in frontend/src-tauri/src/audio/level_monitor.rs. The RMS formula √(Σx²/N) represents the average power of the signal, while the peak value captures the maximum absolute amplitude. The system also applies a threshold (rms > 0.001) to determine if audio is currently active.
What is the update frequency for audio level changes in the UI?
The system emits updates every 100 milliseconds via a Tokio async task that gathers accumulated AudioLevelData from all monitored devices and sends it to the frontend through Tauri's event system as an AudioLevelUpdate struct.
Why does Meetily use CPAL for audio monitoring instead of Web APIs?
Meetily uses CPAL (Cross-Platform Audio Library) because it provides direct, low-latency access to system audio devices from Rust, bypassing browser sandbox restrictions that limit Web Audio API functionality in Tauri applications. CPAL enables the app to enumerate specific input devices by name and capture raw sample data for precise RMS calculations.
How does the system handle multiple audio devices simultaneously?
The start_audio_level_monitoring command accepts a Vec<String> of device names. For each device, the system creates an independent CPAL input stream using device.build_input_stream, processes samples in parallel threads, and aggregates results into a single AudioLevelUpdate event that contains per-device metrics for the frontend.
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 →