Meetily Audio Level Monitoring Architecture: Real-Time Rust Implementation in Tauri

Meetily implements a self-contained Rust subsystem using CPAL for cross-platform audio capture, computing RMS and peak levels every 100 milliseconds, and transmitting metrics to the frontend via Tauri events.

Meetily's audio level monitoring architecture provides real-time volume visualization through a Rust-based backend integrated into the Tauri application shell. Located in the Zackriya-Solutions/meetily repository, this system captures raw PCM data from input devices, processes the waveforms into normalized metrics, and streams updates to the TypeScript frontend via asynchronous event emitters. The design separates device management from signal processing, ensuring low-latency feedback for UI volume meters.

Core Architecture Components

The monitoring system centers on the AudioLevelMonitor struct defined in frontend/src-tauri/src/audio/level_monitor.rs. This component orchestrates device discovery, stream management, and periodic metric emission.

AudioLevelMonitor Struct

The AudioLevelMonitor struct maintains the complete state for active monitoring sessions. It owns lists of target devices, manages active CPAL streams, and holds a shared buffer of computed level data via Arc<Mutex<Vec<AudioLevelData>>>. When initialized through the start_monitoring method, the struct discovers devices by name using find_device_by_name, constructs input streams for each device, and spawns a tokio task that emits level updates every 100 milliseconds.

CPAL Integration

CPAL (Cross-platform Audio Library) provides the low-level hardware abstraction for accessing input devices across macOS, Windows, and Linux. The monitor constructs cpal::Stream instances for each selected device, configuring callbacks that receive raw audio samples in f32 format. These callbacks forward decoded PCM data to the processing pipeline immediately upon capture.

Simple Level Monitor Fallback

For UI development and testing scenarios where hardware access is unavailable, frontend/src-tauri/src/audio/simple_level_monitor.rs provides a mock implementation. This module generates synthetic audio level data that mimics the real monitor's output format, allowing frontend developers to test volume meter components without requiring physical audio hardware.

Signal Processing Pipeline

Raw audio data undergoes channel normalization and metric calculation before transmission to the frontend.

Mono Conversion

Multi-channel audio inputs are normalized to mono through the audio_to_mono helper function in frontend/src-tauri/src/audio/audio_processing.rs. This conversion collapses interleaved multi-channel buffers into single-channel data, ensuring that level calculations remain consistent regardless of whether the source device provides mono, stereo, or surround input.

RMS and Peak Calculation

The process_audio_levels function computes two primary metrics from the mono buffer:

  • RMS Level: The root mean square calculated as √(mean of squared samples), representing the perceived loudness
  • Peak Level: The maximum absolute sample value, indicating the highest instantaneous amplitude

Both values are clamped to the 0-1 range. An activity flag is set when rms > 0.001, providing a simple noise gate to distinguish silence from active audio.

Real-Time Data Flow

The architecture implements a five-stage pipeline that moves data from hardware to UI:

  1. Initialization: The frontend invokes a Tauri command (registered in frontend/src-tauri/src/lib.rs) with a list of device names, triggering AudioLevelMonitor::start_monitoring.
  2. Stream Construction: The monitor creates CPAL input streams for each device, each running in its own callback context.
  3. Sample Processing: Stream callbacks convert raw samples to f32, invoke audio_to_mono, then process_audio_levels to compute RMS and peak values.
  4. Buffer Storage: Computed AudioLevelData structs are pushed into the shared Arc<Mutex<Vec<>>> buffer.
  5. Event Emission: A tokio::interval configured to Duration::from_millis(100) clones the buffer, clears it to prevent stale data, constructs an AudioLevelUpdate, and emits it via app_handle.emit("audio-levels", &update).

Global State Management

A lazy-static AUDIO_LEVEL_STATE structure containing an AtomicBool controls the global monitoring lifecycle. All processing loops check this flag before continuing; invoking stop_monitoring flips this boolean, immediately halting all CPAL streams and canceling the emission task. This ensures clean shutdown without resource leaks or ghost threads.

Frontend Integration

The TypeScript frontend subscribes to the "audio-levels" event channel using Tauri's event listener API:

import { listen } from '@tauri-apps/api/event';

listen<{
  timestamp: number;
  levels: {
    device_name: string;
    device_type: string;
    rms_level: number;
    peak_level: number;
    is_active: boolean;
  }[];
}>('audio-levels', event => {
  const { timestamp, levels } = event.payload;
  setAudioLevels(levels); // Update React/Vue state driving VU meters
});

To initiate monitoring, the frontend invokes the start command:

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

await invoke('start_audio_level_monitor', {
  deviceNames: ['Built-in Microphone', 'USB Audio Device'],
});

Extensibility and Current Limitations

The architecture supports several extension points. The Duration::from_millis(100) interval can be exposed as a configurable parameter to adjust UI refresh rates. The rms > 0.001 activity threshold currently hardcoded as a noise floor could be parameterized for different microphone sensitivities.

Output device monitoring remains unsupported because most operating systems lack simple loopback APIs for capture. The current implementation returns explicit errors for output device requests, though platform-specific extensions (such as WASAPI loopback on Windows) could be added without modifying the core pipeline.

Summary

Meetily's audio level monitoring architecture delivers real-time volume metrics through:

  • Device Abstraction: CPAL integration in level_monitor.rs provides cross-platform hardware access
  • Signal Normalization: audio_to_mono ensures consistent processing across channel configurations
  • Metric Calculation: RMS and peak computations in process_audio_levels provide both perceptual and peak amplitude data
  • Asynchronous Communication: 100ms Tauri events transmit data via the "audio-levels" channel
  • Lifecycle Control: Global AUDIO_LEVEL_STATE provides immediate shutdown capabilities

Frequently Asked Questions

How does Meetily calculate audio levels from raw PCM data?

Meetily processes raw PCM samples through the process_audio_levels function in level_monitor.rs. The pipeline first converts multi-channel audio to mono using audio_to_mono from audio_processing.rs, then calculates RMS as the square root of the mean squared samples and peak as the maximum absolute sample value. Both metrics are normalized to a 0-1 float range before transmission.

What is the update frequency for audio level metrics in Meetily?

The system emits AudioLevelUpdate events every 100 milliseconds via a tokio::interval configured with Duration::from_millis(100). This interval balances real-time responsiveness with CPU usage, providing smooth visual feedback without overwhelming the frontend with excessive updates.

Can Meetily monitor output audio devices for level metering?

Currently, Meetily only supports input device monitoring. The architecture explicitly blocks output device monitoring because most operating systems lack a standardized loopback capture API. The code returns a descriptive error when output monitoring is requested, though the modular design in level_monitor.rs would accommodate platform-specific loopback implementations (like WASAPI on Windows) as future extensions.

How does the frontend receive audio level updates from the Rust backend?

The frontend listens to Tauri events on the "audio-levels" channel using the listen function from @tauri-apps/api/event. The Rust backend emits structured payloads containing timestamps and vectors of AudioLevelData structs (including device names, RMS levels, peak levels, and activity flags) via app_handle.emit("audio-levels", &update) every 100ms.

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 →