mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Voice dictation for KDE Wayland: record, transcribe, clean up, paste
Ctrl+Space starts and stops a recording. The audio goes to OpenAI for transcription, a model on OpenRouter strips the fillers and restores punctuation, and the result is copied and pasted into the focused window. Only the Python standard library and PyQt6 — HTTP, multipart uploads and WAV writing are all hand-rolled. - pw-record captures raw 16 kHz mono PCM with a live level meter - the corner indicator is drawn through XWayland, since a Wayland client cannot position its own window - silence is caught before it costs an API call, relative to each recording's own noise floor, plus a filter for the stock phrases models invent when handed silence - audio and video files can be transcribed too, optionally with [mm:ss] timestamps, chunked through ffmpeg for long inputs - global shortcut installs as a KDE custom shortcut, with an evdev listener as a fallback until the session is restarted - Turkish and English interface, following the system locale by default
This commit is contained in:
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
# Dikte installer: dependency check, launchers, KDE shortcut.
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PY="$(command -v python3)"
|
||||
BIN_DIR="$HOME/.local/bin"
|
||||
APP_DIR="$HOME/.local/share/applications"
|
||||
AUTOSTART_DIR="$HOME/.config/autostart"
|
||||
SHORTCUT="${1:-Ctrl+Space}"
|
||||
|
||||
say() { printf ' %s\n' "$1"; }
|
||||
ok() { printf ' \033[32m✓\033[0m %s\n' "$1"; }
|
||||
warn() { printf ' \033[33m!\033[0m %s\n' "$1"; }
|
||||
|
||||
echo
|
||||
echo "Installing Dikte"
|
||||
echo "────────────────"
|
||||
|
||||
# 1. Dependencies ----------------------------------------------------------
|
||||
missing=()
|
||||
for cmd in pw-record wl-copy wl-paste ydotool ffmpeg; do
|
||||
command -v "$cmd" >/dev/null || missing+=("$cmd")
|
||||
done
|
||||
python3 -c 'import PyQt6.QtWidgets' 2>/dev/null || missing+=("python-pyqt6")
|
||||
|
||||
if ((${#missing[@]})); then
|
||||
warn "Missing: ${missing[*]}"
|
||||
say "Arch/CachyOS: sudo pacman -S --needed pipewire-audio wl-clipboard ydotool ffmpeg python-pyqt6"
|
||||
echo
|
||||
else
|
||||
ok "All dependencies present"
|
||||
fi
|
||||
|
||||
# 2. ydotoold --------------------------------------------------------------
|
||||
if command -v ydotool >/dev/null; then
|
||||
if systemctl --user is-active --quiet ydotool 2>/dev/null \
|
||||
|| systemctl --user is-active --quiet ydotoold 2>/dev/null; then
|
||||
ok "ydotoold is running (auto-paste ready)"
|
||||
else
|
||||
warn "ydotoold is not running — auto-paste will not work"
|
||||
say "systemctl --user enable --now ydotool"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3. Launchers -------------------------------------------------------------
|
||||
mkdir -p "$BIN_DIR" "$APP_DIR" "$AUTOSTART_DIR"
|
||||
ln -sf "$DIR/dikte.py" "$BIN_DIR/dikte"
|
||||
chmod +x "$DIR/dikte.py"
|
||||
ok "Command installed: $BIN_DIR/dikte"
|
||||
case ":$PATH:" in
|
||||
*":$BIN_DIR:"*) ;;
|
||||
*) warn "$BIN_DIR is not on your PATH — for fish: fish_add_path $BIN_DIR" ;;
|
||||
esac
|
||||
|
||||
cat > "$APP_DIR/dikte.desktop" <<EOF
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Dikte
|
||||
Comment=Voice dictation: record, transcribe, clean up, paste
|
||||
Exec=$PY $DIR/dikte.py
|
||||
Icon=audio-input-microphone
|
||||
Categories=Utility;AudioVideo;
|
||||
StartupNotify=false
|
||||
EOF
|
||||
ok "Application menu entry added"
|
||||
|
||||
cat > "$AUTOSTART_DIR/dikte.desktop" <<EOF
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Dikte
|
||||
Exec=$PY $DIR/dikte.py
|
||||
Icon=audio-input-microphone
|
||||
X-GNOME-Autostart-enabled=true
|
||||
StartupNotify=false
|
||||
EOF
|
||||
ok "Will start automatically on login"
|
||||
|
||||
# 4. KDE global shortcut ---------------------------------------------------
|
||||
cat > "$APP_DIR/dikte-toggle.desktop" <<EOF
|
||||
[Desktop Entry]
|
||||
Exec=$PY $DIR/dikte.py toggle
|
||||
Name=Dikte: start/stop recording
|
||||
NoDisplay=true
|
||||
StartupNotify=false
|
||||
Type=Application
|
||||
X-KDE-GlobalAccel-CommandShortcut=true
|
||||
EOF
|
||||
|
||||
if command -v kwriteconfig6 >/dev/null; then
|
||||
kwriteconfig6 --notify --file kglobalshortcutsrc \
|
||||
--group services --group dikte-toggle.desktop \
|
||||
--key _launch "$SHORTCUT"
|
||||
ok "KDE shortcut registered: $SHORTCUT"
|
||||
warn "KWin only reads this at startup, so the shortcut goes live after your"
|
||||
say "next login. Until then open Settings → Shortcut and turn on the"
|
||||
say "built-in listener to use it right away."
|
||||
else
|
||||
warn "kwriteconfig6 not found — add the shortcut via System Settings → Shortcuts"
|
||||
fi
|
||||
|
||||
echo
|
||||
ok "Done. Start it with: dikte"
|
||||
say "The settings window opens on first run; add your OpenAI and OpenRouter keys."
|
||||
echo
|
||||
Reference in New Issue
Block a user