# How Meetily Detects Bluetooth Playback Devices and Warns Users: A Complete Technical Guide

> Learn how Meetily detects Bluetooth playback devices and warns users with a Rust backend and React frontend. Understand the technical process for better audio recording quality.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-07-11

---

**Meetily monitors your active audio output device every 5 seconds using a Rust backend command and React frontend polling to detect Bluetooth playback devices and warn users about potential recording quality issues.**

The open-source Meetily application protects meeting recording quality by implementing a cross-platform Bluetooth playback detection system. This article examines the complete technical workflow from the Rust-based Tauri backend to the React frontend, showing exactly how the system identifies Bluetooth devices like AirPods and alerts users before audio quality degrades.

## Architecture Overview

The detection workflow spans two runtime environments. The **Tauri backend** handles OS-level audio device queries using platform-specific APIs, while the **React frontend** manages polling intervals, state persistence, and UI rendering. This separation ensures that Bluetooth detection works consistently across macOS, Windows, and Linux while maintaining a responsive user interface.

## OS-Level Device Query in Rust

The detection process begins in [`frontend/src-tauri/src/audio/playback_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/playback_monitor.rs), where the system queries the operating system for the current default output device.

On **macOS**, the implementation uses Core Audio. On **Windows**, it leverages WASAPI. **Linux** systems utilize PulseAudio or PipeWire. The `detect_active_output()` function returns device metadata including name, sample rate, and connection type.

```rust
// frontend/src-tauri/src/lib.rs
#[tauri::command]
async fn get_active_audio_output() -> Result<AudioOutputInfo, String> {
    let info = playback_monitor::detect_active_output()?; // platform-specific logic
    Ok(AudioOutputInfo {
        device_name: info.name,
        is_bluetooth: info.is_bluetooth,
        sample_rate: info.sample_rate,
        device_type: info.kind,
    })
}

```

The `get_active_audio_output` command is registered in [`frontend/src-tauri/src/lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/lib.rs) and exposed to the frontend via Tauri's invoke API.

## Bluetooth Identification Logic

Once the OS returns the active device, the Rust code examines the device name and properties to determine if it is a Bluetooth playback device.

The system sets the `is_bluetooth` flag to `true` when:
- The device name contains common Bluetooth keywords (e.g., "AirPods", "Bluetooth")
- The platform API explicitly flags the device as Bluetooth

This logic resides in [`frontend/src-tauri/src/audio/playback_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/playback_monitor.rs) alongside the platform-specific detection code. The result is packaged into an `AudioOutputInfo` struct containing the device name, Bluetooth status, sample rate, and device type.

## Frontend Polling and State Management

The React component `BluetoothPlaybackWarning` in [`frontend/src/components/BluetoothPlaybackWarning.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/BluetoothPlaybackWarning.tsx) handles the continuous monitoring of audio output devices.

The component uses a `useEffect` hook that calls `invoke('get_active_audio_output')` immediately on mount, then repeats every 5 seconds (5000ms) via `setInterval`.

```tsx
// frontend/src/components/BluetoothPlaybackWarning.tsx (simplified)
export function BluetoothPlaybackWarning({ checkInterval = 5000, enabled = true }) {
  const [isBluetoothActive, setIsBluetoothActive] = useState(false);
  const [deviceName, setDeviceName] = useState('');
  const [isDismissed, setIsDismissed] = useState(false);

  useEffect(() => {
    if (!enabled) return;

    const poll = async () => {
      const info = await invoke<AudioOutputInfo>('get_active_audio_output');
      if (info.is_bluetooth) {
        setIsBluetoothActive(true);
        setDeviceName(info.device_name);
      } else {
        setIsBluetoothActive(false);
        setIsDismissed(false);
      }
    };

    poll();                         // run immediately
    const id = setInterval(poll, checkInterval);
    return () => clearInterval(id);
  }, [checkInterval, enabled]);
  
  // ... render logic
}

```

When `is_bluetooth` returns `true`, the component stores the device name and activates the warning state. If the user switches to a non-Bluetooth output, the dismissal state automatically resets so future Bluetooth connections will trigger fresh warnings.

## Rendering the Warning UI

When a Bluetooth device is active and the user has not dismissed the alert, the component renders a yellow `Alert` component explaining the risks.

The warning specifically notes that recordings may be distorted or speed up when using Bluetooth playback devices. It suggests switching to wired headphones or computer speakers for optimal recording quality. Users can dismiss the warning via a close button, which sets the `isDismissed` state to `true` within the component.

The dismissal persistence is maintained only in component state (`isDismissed`), meaning the warning reappears if the user switches to a non-Bluetooth device and then back to Bluetooth, or if the component remounts.

## Backend Adaptations for Bluetooth Devices

Beyond warning users, Meetily adjusts its audio pipeline to accommodate Bluetooth-specific limitations. In [`frontend/src-tauri/src/audio/recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/recording_manager.rs), the system implements device-specific fallbacks.

When Bluetooth devices are detected:
- **Larger buffers** are applied (80-200ms) to handle Bluetooth latency variations
- On **macOS**, the microphone falls back to the built-in mic to avoid variable sample-rate issues that can occur when Bluetooth headphones handle both input and output

These backend adaptations ensure that even if users ignore the warning, the recording system maintains stability despite Bluetooth's inherent latency and sample-rate quirks.

## Summary

- **Cross-platform detection** occurs in [`playback_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/playback_monitor.rs) using Core Audio (macOS), WASAPI (Windows), or PulseAudio/PipeWire (Linux).
- **Bluetooth identification** relies on device name parsing and OS API flags to set the `is_bluetooth` boolean in the `AudioOutputInfo` struct.
- **Continuous monitoring** happens every 5 seconds via the `BluetoothPlaybackWarning` React component using Tauri's `invoke` API.
- **User warnings** appear as dismissible yellow alerts explaining potential distortion risks and recommending wired alternatives.
- **Recording stability** is maintained through larger buffers (80-200ms) and microphone fallbacks implemented in [`recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_manager.rs).

## Frequently Asked Questions

### How often does Meetily check for Bluetooth playback devices?

Meetily polls the active audio output device every 5 seconds (5000ms) by default. This interval is configurable via the `checkInterval` prop in the `BluetoothPlaybackWarning` component. The polling occurs through a `useEffect` hook that calls the Tauri command `get_active_audio_output` immediately on mount and then repeats via `setInterval` until the component unmounts.

### What triggers the Bluetooth detection flag in the backend?

The `is_bluetooth` flag in the `AudioOutputInfo` struct is set to `true` when the device name contains common Bluetooth keywords like "AirPods" or "Bluetooth", or when the platform-specific API explicitly identifies the device as Bluetooth. This logic executes in [`frontend/src-tauri/src/audio/playback_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/playback_monitor.rs) after querying the OS for the active output device.

### Why does Meetily warn users about Bluetooth playback devices?

Bluetooth audio introduces variable latency and can cause sample-rate mismatches that distort recordings or cause speed-up artifacts. The warning appears in a yellow alert component when `isBluetoothActive` is true and the user has not dismissed the notification, advising users to switch to wired headphones or computer speakers for optimal recording fidelity.

### How does Meetily handle recording when Bluetooth devices are in use?

According to the source code in [`frontend/src-tauri/src/audio/recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/recording_manager.rs), Meetily applies larger audio buffers (80-200ms) to compensate for Bluetooth latency. On macOS specifically, the system falls back to the built-in microphone to avoid the variable sample-rate issues that occur when Bluetooth headphones handle both playback and recording simultaneously.