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.
- 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.
- 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.
Clone the repository:
git clone https://github.com/wa7chen/mic-ducker.git
cd mic-duckerCreate a virtual environment and install the package:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txtYou can also use the Makefile:
make installList audio devices:
make list-devicesStart in dry-run mode:
make dry-runDry-run mode prints microphone levels and duck/restore decisions without changing system volume.
Run MicDucker:
make runStop 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=2The equivalent direct command is:
.venv/bin/mic-ducker run --device 2 --ducked-volume 25 --threshold -32 --attack 0.25 --release 1.0For backwards-compatible convenience, the run subcommand may be omitted:
.venv/bin/mic-ducker --dry-run --verboseMicDucker 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 enrollThis 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-gatedTune in dry-run mode first:
make dry-run-speaker-gatedIf your own speech is rejected, lower the threshold:
make run-speaker-gated SPEAKER_THRESHOLD=0.86If speaker bleed still triggers ducking, raise the threshold:
make run-speaker-gated SPEAKER_THRESHOLD=0.95The 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.
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=15No microphone input:
make list-devices
make run DEVICE=YOUR_INPUT_DEVICE_IDPermission 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-gatedThen tune:
make run-speaker-gated THRESHOLD=-28 ATTACK=0.4 SPEAKER_THRESHOLD=0.95Your own speech is rejected by the voiceprint gate:
make enroll
make dry-run-speaker-gated SPEAKER_THRESHOLD=0.86Run tests:
make testRun the CLI from source:
.venv/bin/python -m mic_ducker --helpProject 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
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.jsonMicDucker is released under the MIT License. See LICENSE.