# How Meetily Implements Real-Time Audio Level Monitoring During Recording

> Discover how Meetily provides real-time audio level monitoring during recording using Rust and React. Get live visual feedback for your audio.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: internals
- Published: 2026-07-31

---

**Meetily's audio level monitoring system captures microphone input via Rust's CPAL library, calculates RMS and peak levels every 100 milliseconds, and streams the data to a React frontend through Tauri events to render live visual meters.**

Meetily, the open-source meeting recorder from Zackriya-Solutions, provides immediate visual feedback on microphone input health through a sophisticated real-time audio level monitoring pipeline. This system bridges low-level audio processing in Rust with a React-based user interface, enabling users to verify microphone levels and adjust gain before or during recording sessions.

## Rust Backend: Audio Capture and Level Calculation

### Initializing the AudioLevelMonitor

The core monitoring logic resides in [`src-tauri/src/audio/level_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/audio/level_monitor.rs). The `AudioLevelMonitor` struct creates a CPAL input stream for each selected device, configured to process audio callbacks via the `process_audio_levels` function. The implementation builds a thread-safe data pipeline using `Arc<Mutex<Vec<AudioLevelData>>>` to share calculated metrics across async boundaries.

```rust
// src-tauri/src/audio/level_monitor.rs (excerpt)
let stream = device.build_input_stream(
    &stream_config,
    move |data: &[f32], _| {
        process_audio_levels(data, channels, &device_name, &device_type, level_data_clone.clone());
    },
    |err| error!("Audio stream error: {}", err),
    None,
)?;
stream.play()?;

```

### RMS and Peak Processing

Within each audio callback, the system converts multi-channel PCM data to mono before computing two essential metrics: **RMS** (root mean square) representing average power, and **peak** indicating maximum amplitude. These values determine the visual height of the level bars and the position of the peak marker in the UI.

### Emitting Tauri Events

A dedicated Tokio task packages the current `AudioLevelData` into an `AudioLevelUpdate` struct and emits it via Tauri's event system every 100 milliseconds. The emission continues while `AudioLevelState.is_monitoring` remains true, delivering roughly ten updates per second to the frontend.

```rust
// Periodic emission from src-tauri/src/audio/level_monitor.rs
tokio::spawn(async move {
    let mut interval = interval(Duration::from_millis(100));
    while AUDIO_LEVEL_STATE.is_monitoring.load(Ordering::SeqCst) {
        interval.tick().await;
        app_handle.emit("audio-levels", &update).ok();
    }
});

```

## Frontend Integration: React and Tauri Events

### Starting the Monitoring Session

The `DeviceSelection` component in [`frontend/src/components/DeviceSelection.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/DeviceSelection.tsx) initiates monitoring by invoking the Tauri command `start_audio_level_monitoring` with the selected device names. This triggers the Rust backend to begin CPAL stream processing and the 100ms emission loop.

```tsx
// Inside DeviceSelection.tsx
const startAudioLevelMonitoring = async () => {
  const deviceNames = inputDevices.map(d => d.name);
  await invoke('start_audio_level_monitoring', { deviceNames });
  setIsMonitoring(true);
  setShowLevels(true);
};

```

### Listening for Real-Time Updates

The frontend registers an event listener using `listen('audio-levels', …)` (implemented around lines 74-90 of [`DeviceSelection.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/DeviceSelection.tsx)). Each incoming payload replaces the component's `audioLevels` Map, keyed by device name, triggering React re-renders with fresh RMS and peak values.

```tsx
useEffect(() => {
  const unlisten = await listen<AudioLevelUpdate>('audio-levels', event => {
    const levels = new Map<string, AudioLevelData>();
    event.payload.levels.forEach(l => levels.set(l.device_name, l));
    setAudioLevels(levels);
  });

  return () => unlisten?.();
}, [isMonitoring]);

```

## Visualizing Levels in the UI

### Rendering Audio Meters

Level visualization occurs in [`frontend/src/components/AudioLevelMeter.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/AudioLevelMeter.tsx), where the `AudioLevelMeter` and `CompactAudioLevelMeter` components receive data from the `audioLevels` Map. The system renders a distinct meter for each input device, allowing users to monitor multiple microphones simultaneously.

```tsx
{showLevels && inputDevices.map(dev => (
  <AudioLevelMeter
    key={dev.name}
    rmsLevel={audioLevels.get(dev.name)?.rms_level ?? 0}
    peakLevel={audioLevels.get(dev.name)?.peak_level ?? 0}
    isActive={audioLevels.get(dev.name)?.is_active ?? false}
    deviceName={dev.name}
    size="small"
  />
))}

```

### Logarithmic Scaling and Color Coding

To ensure low-level sounds remain visible, the meter applies `log10` logarithmic scaling to raw amplitude values. The UI renders a color gradient transitioning from **green** through **yellow** to **red** based on intensity, with an optional thin marker indicating peak levels. An `isActive` flag drives a pulsing activity dot that confirms the microphone is detecting sound above the noise floor.

## User Controls and Lifecycle

Users control the monitoring lifecycle through explicit Tauri commands. Invoking `start_audio_level_monitoring` activates the CPAL streams and begins the emission loop, while `stop_audio_level_monitoring` halts processing and clears visual indicators. This architecture allows users to verify microphone health, check for hardware issues, and optimize gain staging before initiating full recording sessions.

## Summary

- Meetily's **real-time audio level monitoring** combines Rust's CPAL library with Tauri's event bridge to deliver approximately ten updates per second to the React frontend.
- The `AudioLevelMonitor` struct in [`src-tauri/src/audio/level_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/audio/level_monitor.rs) calculates **RMS** and **peak** values from raw PCM samples and emits them via the `audio-levels` event every 100 milliseconds.
- The `DeviceSelection` component listens for these events in [`frontend/src/components/DeviceSelection.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/DeviceSelection.tsx) and maintains a Map of `AudioLevelData` keyed by device name to drive component re-renders.
- The `AudioLevelMeter` component applies logarithmic scaling and color coding (green to red) to visualize microphone levels, with an `isActive` flag controlling a pulsing activity indicator.

## Frequently Asked Questions

### How often does Meetily update the audio level meters?

The system calculates levels continuously in the Rust audio callback but packages and emits updates via the `audio-levels` Tauri event every **100 milliseconds**, resulting in approximately ten visual updates per second during recording or monitoring sessions.

### What audio metrics does the system calculate for visualization?

According to the source code in [`src-tauri/src/audio/level_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/audio/level_monitor.rs), the system computes **RMS** (root mean square) for average power and **peak** (maximum amplitude) for spike detection, converting multi-channel input to mono before performing calculations.

### Can users monitor multiple microphones simultaneously?

Yes. The `AudioLevelMonitor` maintains a `Vec<AudioLevelData>` within a shared `Arc<Mutex<...>>` structure, and the frontend renders an `AudioLevelMeter` component for each device in the `audioLevels` Map, enabling parallel visualization of multiple audio sources.

### How does the frontend know when audio is actually being detected?

The Rust backend sets an `is_active` boolean flag in the `AudioLevelData` struct when the input signal exceeds a defined threshold. The React frontend uses this flag to display a pulsing activity dot alongside the logarithmically-scaled level bars, providing immediate confirmation that the microphone is capturing sound.