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 names
  • stop_audio_level_monitoring – Terminates active monitoring sessions
  • is_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:

  1. Device Discovery: Uses cpal::default_host() to enumerate available input devices and matches them against the names supplied by the UI
  2. Stream Construction: Builds input streams via device.build_input_stream with callbacks that receive raw audio samples in native format (F32, I16, or U16)
  3. Channel Processing: Converts multi-channel audio to mono using the audio_to_mono helper from audio_processing.rs
  4. 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
  5. State Management: Stores results in a thread-safe Arc<Mutex<Vec<AudioLevelData>>>
  6. Event Emission: A Tokio task gathers data every 100ms, constructs an AudioLevelUpdate with timestamp and levels, and emits it via app_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.rs route 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 AudioLevelUpdate events via app_handle.emit("audio-levels", &update)
  • Frontend integration: TypeScript uses invoke to start monitoring and listen('audio-levels') to receive real-time updates
  • Testing support: The simple_level_monitor.rs module 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →