Skip to content

Recording captures only channel 1 of multichannel audio interfaces → silence when the mic is on input 2+ #165

Description

@fututukamono

Summary

On a multichannel audio interface (Universal Audio Apollo, Focusrite, MOTU, etc.), Amical records near-silence if the microphone is on any input other than channel 1. Whisper then returns "no words detected", even though the interface, the mic, and all OS permissions are correct.

Environment

  • macOS (Apple Silicon), Amical 1.9.x, Local / Whisper Medium
  • Audio interface: Universal Audio Apollo Twin (2 preamps; front Hi-Z instrument = ch1, rear Mic 2 = ch2)
  • Microphone (SM58) on rear input 2 → Core Audio channel 2

What happens

  • Amical history shows repeated "no words detected".
  • The recorded WAVs ($TMPDIR/amical-audio/*.wav) are full length but ~-66 dBFS (digital silence).
  • Capturing the interface directly and measuring per channel shows the voice is on channel 2, while channel 1 is silent (it's the empty Hi-Z instrument input).
  • Zoom / Google Meet / other dictation apps capture the voice fine (they take stereo / the correct channel).

Root cause

The recorder requests a mono stream:

getUserMedia({ audio: { channelCount: 1, sampleRate, echoCancellation: false, noiseSuppression: false, autoGainControl: false } })

and the audio-recorder-processor AudioWorklet consumes only channel 0:

const channelData = input[0]; // channel 0 == interface channel 1

With channelCount: 1, Chromium hands over only the device's first channel, so any mic on channel 2+ is dropped. (Confirmed empirically: the recorded audio is bit-for-bit the interface's silent channel 1, not a downmix.)

Impact

Anyone using a pro audio interface with the mic on an input other than #1 — an extremely common studio configuration — gets unusable, silent dictation with no error explaining why.

Suggested fix

Capture at least two channels and let the worklet pick the channel that carries signal (or expose a channel selector). A minimal, backward-compatible change:

  • channelCount: 1channelCount: 2
  • worklet: const channelData = input[0];const channelData = input[1] || input[0];

The || input[0] keeps ordinary mono microphones working unchanged. A more complete fix could auto-select the loudest channel or add a UI channel picker. PR with the minimal version to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions