Skip to content

wa7chen/mic-ducker

Repository files navigation

MicDucker

MicDucker is a small macOS utility that lowers system output volume while your microphone detects speech, then restores the previous volume after you stop talking.

It is built for the "voice assistant in a car" effect: music, videos, or speaker audio automatically move into the background while you speak.

Features

  • Lowers macOS system output volume while speech-like microphone input is active.
  • Restores the previous output volume after a configurable quiet period.
  • Uses attack/release timing to avoid reacting to short clicks or bursts.
  • Optional local voiceprint gate to reduce false triggers from speaker bleed, room noise, or other people.
  • Dry-run mode for tuning without changing system volume.
  • No cloud service and no telemetry.

Requirements

  • macOS
  • Python 3.11 or newer
  • A microphone available through Core Audio

MicDucker uses AppleScript to read and set macOS output volume. On first use, macOS may ask for microphone permission for Terminal or the app that launches Python.

Installation

Clone the repository:

git clone https://github.com/wa7chen/mic-ducker.git
cd mic-ducker

Create a virtual environment and install the package:

python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt

You can also use the Makefile:

make install

Quick Start

List audio devices:

make list-devices

Start in dry-run mode:

make dry-run

Dry-run mode prints microphone levels and duck/restore decisions without changing system volume.

Run MicDucker:

make run

Stop it with Ctrl-C.

By default, the Makefile uses the current macOS input device. If you want a specific microphone, pass DEVICE:

make run DEVICE=2

The equivalent direct command is:

.venv/bin/mic-ducker run --device 2 --ducked-volume 25 --threshold -32 --attack 0.25 --release 1.0

For backwards-compatible convenience, the run subcommand may be omitted:

.venv/bin/mic-ducker --dry-run --verbose

Voiceprint Gate

MicDucker can require a local voiceprint match before lowering volume. This is useful when the microphone can hear your speakers and speaker bleed would otherwise trigger ducking.

Enroll your voice:

make enroll

This records the microphone for 30 seconds and saves a local feature vector:

~/.config/mic-ducker/voiceprint.json

Raw audio is not saved by the enrollment command. The saved file contains metadata and numeric features used for local similarity checks.

Run with speaker matching:

make run-speaker-gated

Tune in dry-run mode first:

make dry-run-speaker-gated

If your own speech is rejected, lower the threshold:

make run-speaker-gated SPEAKER_THRESHOLD=0.86

If speaker bleed still triggers ducking, raise the threshold:

make run-speaker-gated SPEAKER_THRESHOLD=0.95

The voiceprint gate is a lightweight local heuristic, not a security or authentication system. It is designed to reduce audio-ducking false positives, not to identify speakers with forensic reliability.

Tuning

Common parameters:

Parameter Default Meaning
THRESHOLD / --threshold -32 Microphone level in dBFS required to consider audio speech-like. Less negative is stricter.
ATTACK / --attack 0.25 Seconds above threshold before ducking. Higher values ignore short bursts.
RELEASE / --release 1.0 Seconds of quiet before restoring volume.
DUCKED_VOLUME / --ducked-volume 25 Temporary macOS output volume while speaking.
SPEAKER_THRESHOLD / --speaker-threshold 0.92 Minimum voiceprint similarity when speaker gate is enabled.

Examples:

# Too many false triggers
make run THRESHOLD=-28 ATTACK=0.4

# Your voice is missed
make run THRESHOLD=-36 ATTACK=0.2

# Lower background audio more aggressively
make run DUCKED_VOLUME=15

Troubleshooting

No microphone input:

make list-devices
make run DEVICE=YOUR_INPUT_DEVICE_ID

Permission denied or no audio:

  • Open macOS System Settings.
  • Check Privacy & Security -> Microphone.
  • Allow access for Terminal, iTerm, or the app launching Python.

Speaker audio still triggers ducking:

make run-speaker-gated

Then tune:

make run-speaker-gated THRESHOLD=-28 ATTACK=0.4 SPEAKER_THRESHOLD=0.95

Your own speech is rejected by the voiceprint gate:

make enroll
make dry-run-speaker-gated SPEAKER_THRESHOLD=0.86

Development

Run tests:

make test

Run the CLI from source:

.venv/bin/python -m mic_ducker --help

Project layout:

mic_ducker/
  __main__.py       CLI, enrollment, and runtime loop
  audio_level.py    dBFS calculation
  core.py           ducking state machine
  system_volume.py  macOS output volume control
  voiceprint.py     local voiceprint feature extraction and matching
tests/
  test_*.py

Privacy

MicDucker runs locally. It does not send microphone audio or voiceprint data to a remote service.

The optional voiceprint enrollment stores a numeric feature vector at ~/.config/mic-ducker/voiceprint.json. Delete that file to remove the enrolled voiceprint:

rm ~/.config/mic-ducker/voiceprint.json

License

MicDucker is released under the MIT License. See LICENSE.

About

Local macOS microphone-triggered system audio ducking with optional voiceprint gating.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors