feat: add Linux support, replace keyboard lib with pynput

- Replace `keyboard` package (requires root on Linux) with pynput
  Listener for hotkey handling — works without root on X11/Wayland
- Enable system-site-packages in venv for PyGObject/AppIndicator
  so pystray uses StatusNotifierItem backend on KDE Wayland
- Use platform-appropriate fonts (sans-serif/monospace on Linux)
- Auto-size settings and vocabulary windows instead of hardcoded dims
- Update install.sh with --system-site-packages flag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
d-chrka 2026-03-19 19:13:26 +01:00
parent e1a3eba05a
commit 4efa66fc79
9 changed files with 867 additions and 766 deletions

22
.gitignore vendored
View File

@ -1,11 +1,11 @@
.venv-windows/
.venv-linux/
.venv/
__pycache__/
*.pyc
*.pyo
config_local.json
models/
*.log
.DS_Store
Thumbs.db
.venv-windows/
.venv-linux/
.venv/
__pycache__/
*.pyc
*.pyo
config_local.json
models/
*.log
.DS_Store
Thumbs.db

View File

@ -1,6 +1,6 @@
{
"hotkey": "ctrl+shift+space",
"model": "medium",
"language": "de",
"sample_rate": 16000
}
{
"hotkey": "ctrl+shift+space",
"model": "medium",
"language": "de",
"sample_rate": 16000
}

1478
dictate.py

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
@echo off
cd /d "%~dp0"
echo Creating Windows venv (.venv-windows)...
py -3.13 -m venv .venv-windows
set "VENV=%~dp0.venv-windows"
echo Installing dependencies...
"%VENV%\Scripts\pip" install --upgrade pip
"%VENV%\Scripts\pip" install -r requirements.txt
echo Installing CUDA 12 DLLs (required for GPU acceleration)...
"%VENV%\Scripts\pip" install -r requirements-cuda.txt
echo.
echo Done. Run start.bat to launch.
pause
@echo off
cd /d "%~dp0"
echo Creating Windows venv (.venv-windows)...
py -3.13 -m venv .venv-windows
set "VENV=%~dp0.venv-windows"
echo Installing dependencies...
"%VENV%\Scripts\python.exe" -m pip install --upgrade pip
"%VENV%\Scripts\python.exe" -m pip install -r requirements.txt
echo Installing CUDA 12 DLLs (required for GPU acceleration)...
"%VENV%\Scripts\python.exe" -m pip install -r requirements-cuda.txt
echo.
echo Done. Run start.bat to launch.
pause

View File

@ -3,7 +3,7 @@ set -e
cd "$(dirname "$0")"
echo "Creating Linux venv (.venv-linux)..."
python3 -m venv .venv-linux
python3 -m venv --system-site-packages .venv-linux
echo "Installing dependencies..."
.venv-linux/bin/pip install --upgrade pip

View File

@ -1,4 +1,4 @@
# Windows CUDA 12 DLLs required by ctranslate2 (faster-whisper backend)
# Install after requirements.txt on Windows with NVIDIA GPU
nvidia-cublas-cu12
nvidia-cudnn-cu12
# Windows CUDA 12 DLLs required by ctranslate2 (faster-whisper backend)
# Install after requirements.txt on Windows with NVIDIA GPU
nvidia-cublas-cu12
nvidia-cudnn-cu12

View File

@ -1,7 +1,6 @@
faster-whisper>=1.0.2
sounddevice>=0.4.6
numpy>=1.24
keyboard>=0.13
pystray>=0.19
Pillow>=9.5
pynput>=1.7.6
faster-whisper>=1.0.2
sounddevice>=0.4.6
numpy>=1.24
pystray>=0.19
Pillow>=9.5
pynput>=1.7.6

View File

@ -1,14 +1,14 @@
@echo off
cd /d "%~dp0"
set "VENV=%~dp0.venv-windows"
rem Machine-local config dir (device, compute_type, audio_device - not in git)
if not exist "%LOCALAPPDATA%\WhisperDictation" mkdir "%LOCALAPPDATA%\WhisperDictation"
set "WHISPER_LOCAL_DIR=%LOCALAPPDATA%\WhisperDictation"
rem CUDA 12 DLLs required by ctranslate2
set "PATH=%VENV%\Lib\site-packages\nvidia\cublas\bin;%VENV%\Lib\site-packages\nvidia\cudnn\bin;%PATH%"
"%VENV%\Scripts\python.exe" -u "%~dp0dictate.py"
pause
@echo off
cd /d "%~dp0"
set "VENV=%~dp0.venv-windows"
rem Machine-local config dir (device, compute_type, audio_device - not in git)
if not exist "%LOCALAPPDATA%\WhisperDictation" mkdir "%LOCALAPPDATA%\WhisperDictation"
set "WHISPER_LOCAL_DIR=%LOCALAPPDATA%\WhisperDictation"
rem CUDA 12 DLLs required by ctranslate2
set "PATH=%VENV%\Lib\site-packages\nvidia\cublas\bin;%VENV%\Lib\site-packages\nvidia\cudnn\bin;%PATH%"
"%VENV%\Scripts\python.exe" -u "%~dp0dictate.py"
pause

View File

@ -1,18 +1,18 @@
{
"words": [],
"replacements": [
{"from": "KRA", "to": "KRAH"},
{"from": "Atos", "to": "ATHOS"},
{"from": "Resistec", "to": "RESISTEC"},
{"from": "Resistek", "to": "RESISTEC"},
{"from": "HES", "to": "HEES"},
{"from": "Ackerschot", "to": "Ackerschott"},
{"from": "Carrois", "to": "Kauer"},
{"from": "Jouer fixe", "to": "Jour-Fixe"},
{"from": "Docuware", "to": "DocuWare"},
{"from": "Nates", "to": "Nejc"},
{"from": "Bittzeit", "to": "BitSight"},
{"from": "Kalmikow", "to": "Kalmykov"},
{"from": "Leifert", "to": "Leifer"}
]
}
{
"words": [],
"replacements": [
{"from": "KRA", "to": "KRAH"},
{"from": "Atos", "to": "ATHOS"},
{"from": "Resistec", "to": "RESISTEC"},
{"from": "Resistek", "to": "RESISTEC"},
{"from": "HES", "to": "HEES"},
{"from": "Ackerschot", "to": "Ackerschott"},
{"from": "Carrois", "to": "Kauer"},
{"from": "Jouer fixe", "to": "Jour-Fixe"},
{"from": "Docuware", "to": "DocuWare"},
{"from": "Nates", "to": "Nejc"},
{"from": "Bittzeit", "to": "BitSight"},
{"from": "Kalmikow", "to": "Kalmykov"},
{"from": "Leifert", "to": "Leifer"}
]
}