Expand description
Dual audio capture for Tauri 2 — microphone + system audio (WASAPI loopback) with WebRTC AEC3 echo cancellation.
Extracted from the production desktop app of SubcueAI.
┌─────────────┐ ┌─────────────┐ ┌───────────┐
│ mic capture │───▶│ resampler │───▶│ APM │──▶ FrameEvent::Pcm (mic)
└─────────────┘ │ to 16k f32 │ │ near-end │
└─────────────┘ └───────────┘
┌─────────────┐ ┌─────────────┐ ┌───────────┐
│ loopback* │───▶│ resampler │───▶│ APM │──▶ FrameEvent::Pcm (loopback)
└─────────────┘ │ to 16k f32 │ │ reverse │
*Windows only └─────────────┘ └───────────┘Mic and loopback are emitted as independent 16 kHz mono PCM streams
(no additive mix), so the JS side can route each to its own consumer —
e.g. two STT sockets tagged “local speaker” vs “remote party”. A
mixer::Mixer utility is included if you want a single combined
stream instead.
On Windows the loopback (system output) feed doubles as the far-end reference for WebRTC AEC3, so speaker bleed is cancelled from the mic before your app ever sees it. On macOS the plugin runs mic-only: Apple’s voice-processing I/O (VPIO) already does AEC at the OS level, and system-audio capture requires ScreenCaptureKit, which is out of scope here.
Modules§
Structs§
- Audio
Session - Capture
Options - What to capture and how to process it. All flags are orthogonal; defaults give you the full pipeline (mic + loopback + APM).
Enums§
- Error
- Frame
Event - Events emitted to the JS side over the Tauri
Channel. - PcmSource
- Which physical source a PCM frame came from. Mic and loopback frames arrive interleaved on the same channel; consumers split on this tag — e.g. mic → “local speaker” STT, loopback → “remote party” STT.
Functions§
- init
- Initializes the plugin. Registers
start/stop/permission_statuscommands and, on Windows, resolves a bundledwebrtc-apm.dllthrough Tauri’s resource resolver (works fortauri devandtauri buildalike).