| Windows (no Python needed) | ⚡ Download TapAccumulator.zip |
| Run from source | See Installation below |
The .exe is fully self-contained — extract the zip, run TapAccumulator.exe, done.
Requires Windows 10 or 11 · x64.
Your Bluetooth earbuds have a button. Right now it only does one thing — play/pause. TapAccumulator intercepts that button, counts how many times you press it in quick succession, and fires a different command for each pattern. Completely hands-free.
Tap ×2 → Lock the workstation
Tap ×3 → Open Spotify
Tap ×4 → Run a Python script
Tap ×5 → Anything you want
It works alongside YouTube, Spotify, and any other media app — your content keeps playing uninterrupted while TapAccumulator silently counts your taps in the background.
- Multi-tap sequences — register distinct actions for 2 through 8 taps
- Rolling timeout accumulator — configurable silence window before a sequence fires
- Three capture modes — Mix (smart default), Hook (passive), Reclaim (exclusive)
- Shell command execution — run any executable, script, URL, or batch file
- Voice confirmation (TTS) — optional Windows SAPI speech text per macro
- Modern dark UI — tactical industrial design, live event stream, real-time tap counter
- Always-on system tray — custom earbud icon, toggle listener, reclaim focus on demand
- First-run onboarding — welcome modal with full usage guide, shown once
- Hook mode warning — notifies you of phantom-tap risk from auto-replay on startup
- Persistent JSON storage — macros and settings survive restarts, human-readable files
- Boot-storm guard — ignores spurious Windows media events during startup grace period
- Non-destructive settings upgrades — new keys merge in without overwriting your config
| Dashboard | Tap Commands | Settings |
|---|---|---|
![]() |
![]() |
![]() |
Earbud button press
│
▼
┌────────────────────────┐
│ Unified Input Filter │ stamps every keyboard/mouse/scroll event
│ _should_ignore() │ rejects signals within the threshold window
│ (pynput) │ boot guard · debounce · input delta check
└───────────┬────────────┘
│ clean signal confirmed
▼
┌────────────────────────┐
│ Rolling Accumulator │ asyncio queue with configurable timeout
│ async_worker() │ counts taps, waits for silence
└───────────┬────────────┘
│ sequence complete
▼
┌────────────────────────┐
│ Macro Executor │ fires shell command via subprocess.Popen
│ execute_action() │ speaks confirmation text via Windows SAPI
└────────────────────────┘
| Mode | How it works | Best for |
|---|---|---|
| Mix ⭐ | Registers a silent SMTC media session at startup. When another app steals media focus, attempts to hook into that session first. Falls back to re-registration if hook fails. | Everything — the default |
| Hook | Never fights for the media session. Passively attaches a playback_info_changed listener to whatever app is currently playing. Keyboard, mouse, and scroll timestamps filter local presses from genuine earbud taps. |
YouTube or Spotify always running |
| Reclaim | Owns the SMTC session exclusively. Watchdog thread re-registers if another app steals it. | Nothing else playing in the background |
Mix is the recommended default. It adapts automatically to whatever is playing without interrupting it.
⚠️ Hook and Mix modes may register phantom taps caused by browser auto-replay or media automation tools that toggle playback state programmatically. If this affects you, switch to Reclaim in Settings.
- Go to the Releases page
- Download
TapAccumulator.zip - Extract it anywhere
- Run
TapAccumulator.exe
No Python. No installs. No dependencies.
- Windows 10 or Windows 11
- Python 3.8 or newer
- A Bluetooth earbud or wireless headset with a media button
# 1. Clone the repository
git clone https://github.com/vyixor/tapaccumulator.git
cd tapaccumulator
# 2. Install dependencies
pip install -r requirements.txt
# 3. Run
python tapaccumulator.pycustomtkinter==5.2.2
Pillow==12.2.0
pynput==1.8.2
pystray==0.19.5
pywin32==311
winotify==1.1.0
winsdk==1.0.0b10
All dependencies target Windows. This project does not run on macOS or Linux — it uses WinRT, SMTC, and Windows SAPI APIs.
- Open ⌘ Tap Commands in the sidebar
- Select a tap count using the chip selector (2 – 8)
- Enter a shell command in the SHELL COMMAND field
- Optionally add a SUCCESS SPEECH TEXT phrase — spoken aloud by Windows SAPI when the macro fires
- Click ⚡ Register Command
# Lock workstation
rundll32.exe user32.dll,LockWorkStation
# Launch applications
start spotify
notepad.exe
"C:\Program Files\MyApp\app.exe"
# Run scripts
python "C:\scripts\my_script.py"
cmd /c "C:\scripts\batch.bat"
# Open URLs
start https://github.com
# Volume and system
nircmd.exe mutesysvolume 2
shutdown /s /t 60
taskkill /f /im chrome.exeAll settings live in %APPDATA%\TapAccumulator\settings.json and can be edited directly. Changes are picked up on next launch. The Settings page in the UI exposes all values with descriptions.
{
"theme": "System",
"capture_mode": "mix",
"timeout": 1.5,
"startup_grace": 5.0,
"hook_threshold": 0.22,
"tap_debounce_ms": 280,
"aggressive_focus_recovery": true,
"recovery_interval": 8.0,
"tts_voice_index": 0,
"tts_rate": 0,
"tts_volume": 100,
"run_in_background": true,
"start_minimized": false
}| Key | Description | Default |
|---|---|---|
theme |
"Dark" · "Light" · "System" |
"System" |
capture_mode |
"mix" · "hook" · "reclaim" |
"mix" |
timeout |
Seconds of silence before sequence fires | 1.5 |
startup_grace |
Boot-storm guard window in seconds | 5.0 |
hook_threshold |
Local-input filter window in seconds | 0.22 |
tap_debounce_ms |
Minimum gap between accepted taps (ms) | 280 |
recovery_interval |
Reclaim watchdog polling interval (seconds) | 8.0 |
tts_voice_index |
SAPI voice: 0 = default, 1/2/3 = other installed voices |
0 |
tts_rate |
SAPI speech rate: -10 (slow) → +10 (fast) |
0 |
tts_volume |
SAPI speech volume: 0 – 100 |
100 |
start_minimized |
Start directly to system tray without showing window | false |
Macros are stored in %APPDATA%\TapAccumulator\macros.json:
{
"2": {
"type": "shell",
"command": "calc.exe",
"speech_text": "Calculator opened"
},
"3": {
"type": "shell",
"command": "start spotify",
"speech_text": "Opening Spotify"
}
}tapaccumulator/
├── tapaccumulator.py # UI, DataManager, tray, settings, modals
├── engine.py # TapEngine — SMTC, hook, filter, accumulator, TTS
├── requirements.txt
├── build_exe.bat # Nuitka build script → produces TapAccumulator.exe
├── README.md
├── LICENSE
├── icons/
│ ├── icon.ico # Window title bar icon
│ └── icon.png # README and general use
└── assets/
├── demo.gif
├── screenshot_dashboard.png
├── screenshot_macros.png
└── screenshot_settings.png
The engine runs on a dedicated daemon thread with its own asyncio event loop, completely isolated from the UI thread.
| Method | Responsibility |
|---|---|
_setup_our_session() |
Registers a silent looping wmp.MediaPlayer as a legitimate SMTC session |
_start_input_tracker() |
Hooks keyboard, mouse clicks, and scroll wheel via pynput to stamp _last_input_time |
_should_ignore() |
Unified three-layer filter: boot guard → debounce → input delta |
_setup_session_watcher() |
Attaches to GlobalSystemMediaTransportControlsSessionManager, hooks playback_info_changed |
_respond_to_session_change() |
Mix mode decision tree: hook new session → or re-register ours |
async_worker() |
Rolling-timeout asyncio queue — counts taps, dispatches on silence |
_execute_speech_pipeline() |
COM-safe SAPI TTS via pythoncom.CoInitialize() in a short-lived thread |
TapAccumulator places a custom earbud icon in your system tray at startup — it is always present whether the window is open or closed.
| Action | Result |
|---|---|
| Show TapAccumulator | Brings the window to the foreground |
| Toggle Earbud Listener | Pauses or resumes tap detection, shows Windows notification |
| Reclaim Media Focus | Re-registers the SMTC session to bring media button routing back to TapAccumulator |
| Exit | Fully closes the application |
Closing the window hides it to tray. It does not terminate the engine.
Taps aren't being detected
- Make sure the startup grace period (default 5s) has elapsed — the event stream will show
Engine READYwhen it's active - Try switching capture mode to
reclaimifmixisn't working with your device - Check
%APPDATA%\TapAccumulator\tapaccumulator.logfor detailed engine output
Taps are registering twice
- Increase
tap_debounce_msin Settings (try350or400) - Some Bluetooth drivers fire two events per press — the debounce guard handles this but may need tuning for your adapter
Phantom taps when YouTube auto-replays
- Expected in
hookandmixmodes — see the hook warning on startup - Switch to
reclaimmode in Settings for exclusive media button control
Speech text not playing
- Confirm
pywin32is installed:pip install pywin32 - Try a different
tts_voice_indexin settings — index 0 is the Windows default voice - Check the log for
TTS Thread Failureerrors
App doesn't appear in taskbar
- It's minimized to the system tray — look for the amber earbud icon in the notification area
- Right-click it and select Show TapAccumulator
Pull requests are welcome. Please open an issue first to discuss any significant changes.
Areas where contributions would be most useful:
- Testing across different Bluetooth earbud brands, adapters, and drivers
- Additional action types — HTTP webhooks, AutoHotkey integration, key simulation
- macOS/Linux equivalent using platform-native media key APIs
MIT License — free for personal and commercial use.
Built by vyixor
If TapAccumulator saved you a trip to the keyboard, a ⭐ star is appreciated.



