Voice dictation plugin for Steam Deck using faster-whisper with context-aware transcription.
- Push-to-Talk: Hold button combo (default: L1+R1) to record
- Configurable buttons: Choose 1-5 button combinations from any Steam Deck controller buttons
- Game presets: Switch between game profiles with different chat systems (WoW, Generic)
- Channel-aware: Speak channel prefixes like "party pull boss" and it routes to the right chat channel
- Test Recording: Built-in 3-second test with automatic transcription display
- Context-aware: Optional WoW addon integration for better accuracy with zone, boss, and party context
- Fast transcription: Uses faster-whisper for efficient CPU-based speech recognition
- Auto-type: Automatically types transcribed text into active window via ydotool
- Toast notifications: Optional notifications when recording starts/stops
-
Download
decktation.zipfrom GitHub Releases -
Extract and install:
unzip decktation.zip sudo cp -r decktation /home/deck/homebrew/plugins/
-
Setup keyboard simulation (one-time):
sudo /home/deck/homebrew/plugins/decktation/setup_ydotoold.sh
-
Restart Decky or reload plugins from Decky settings
All dependencies are pre-bundled in the release.
- Open Quick Access Menu (... button on Steam Deck)
- Navigate to Decktation plugin
- Select your game from the Game dropdown
- Enable the plugin (waits for Whisper model to load)
- (Optional) Change the button combination in the plugin UI
- In any app/game: hold [button1]+[button2] together to record, release to transcribe and type
Decktation ships with two presets configured in game_presets.json:
| Preset | Behavior |
|---|---|
| World of Warcraft | Presses Enter to open chat, types channel prefix + message, presses Enter to send |
| Generic | Types text directly into whatever window is focused — no Enter presses |
In WoW mode, start your message with a channel name to route it to the right channel:
"party let's go" → /p let's go
"raid: focus adds first" → /raid focus adds first
"say, hello everyone" → /s hello everyone
"guild heads up" → /g heads up
"type search term" → types directly without opening chat
Separators supported: space, colon, comma, or period after the channel name. Case-insensitive.
Available WoW channels: say, party, raid, guild, officer, yell, instance, whisper, type
You can add channels beyond the built-in ones (e.g. WoW's numbered channels /1, /2) by editing two config files.
Step 1 — add the channel command to game_presets.json under the preset's channels map:
"channels": {
"say": "/s ",
"party": "/p ",
"one": "/1 ",
"two": "/2 "
}Step 2 — add the spoken trigger words to channel_languages.json under each language's channels map:
"en": {
"channels": {
"one": ["one", "channel one"],
"two": ["two", "channel two"]
}
}After saving both files, saying "one hello" or "channel one hello" will send /1 hello.
You can add as many trigger words per channel as you like (e.g., aliases in multiple languages). The key in channel_languages.json must match the key in game_presets.json.
Edit game_presets.json to add new games — no code changes needed. Each preset specifies:
chat_open_key— key to open the chat box ("enter"ornull)chat_send_key— key to send the message ("enter"ornull)default_channel— channel to use when no prefix is spokenchannels— map of spoken words to slash-command prefixeswhisper_prompt— vocabulary hint for the Whisper model
The plugin uses a configurable button combo for push-to-talk. You can set 1–5 buttons from the plugin UI.
Available buttons:
- L1, R1 (bumpers) — Default combo
- L2, R2 (triggers)
- L5, R5 (back grips) — note: intercepted by Steam in some modes
- A, B, X, Y (face buttons)
- WoW chat: Dictate messages with correct channel routing (party, raid, guild, etc.)
- Generic text input: Type player names, search terms, chat in any game without a keyboard
- Web browsing: Fill forms, search, comment
- Discord/messaging: Send messages hands-free
- Any text input: Works in any active window using the Generic preset
For improved accuracy with WoW-specific vocabulary, install the included WoW addon and run convert_wow_context.py --watch. It reads your current zone, target, party members, and class/spec from the game and feeds them to Whisper as context.
See doc/TESTING_GUIDE.md for setup instructions.
- Check Decky Loader logs:
/tmp/decky-*.log - Ensure all Python dependencies are installed
- Restart Decky Loader
- Ensure the plugin is enabled
- Check that Steam Deck mic is working (test in another app)
- Verify ydotoold is running:
pgrep ydotoold - Check logs:
/tmp/decktation.log
- Try a different button combination in the plugin UI
- Avoid L5/R5 as Steam may intercept these buttons
- Check
/tmp/decktation.logfor controller listener errors - Verify controller listener is running:
pgrep -f controller_listener
- Default
basemodel is recommended (good balance) - For faster: use
tinymodel (edit wow_voice_chat.py line 28) - For accuracy: use
smallmodel (slower, needs more resources)
- Speech recognition: faster-whisper (CTranslate2 backend)
- Model: base (150MB, ~2-4s transcription time)
- Input: Steam Deck microphone or connected headset
- Controller input: evdev (separate subprocess to avoid Steam interception)
- Output: Keyboard simulation via ydotool (bundled)
- Game presets:
game_presets.json— data-driven, no code changes needed to add games - Dependencies: Pre-bundled Python 3.11 libraries in
lib/folder - Architecture: TypeScript frontend + Python backend + separate controller listener process
npm install # Install Node dependencies
npm run build # Compile TypeScript to dist/index.js
npm run watch # Watch mode for development
# Unit tests (no hardware required)
python3 -m venv .venv && .venv/bin/pip install pytest
.venv/bin/pytest tests/ -vCI runs unit tests and the TypeScript build on every push via GitHub Actions.
- All processing happens locally on your Steam Deck
- No data sent to external servers
- Whisper model downloads from HuggingFace (one-time)
Built with:
- faster-whisper - Efficient Whisper implementation
- Decky Loader - Steam Deck plugin framework
MIT
