# lel Python X11 transcription daemon that records audio, runs Whisper, logs the transcript, and can optionally run AI post-processing before injecting text. ## Requirements - X11 (not Wayland) - `ffmpeg` - `faster-whisper` - `pactl` (PulseAudio utilities for mic selection) - Tray icon deps: `gtk3` - i3 window manager (focus metadata via i3 IPC) - Python deps: `pillow`, `python-xlib`, `faster-whisper`, `PyGObject`, `i3ipc` ## Python Daemon Install Python deps: ```bash pip install -r requirements.txt ``` Run: ```bash python3 src/leld.py --config ~/.config/lel/config.json ``` Open settings: ```bash python3 src/leld.py --settings --config ~/.config/lel/config.json ``` ## Config Create `~/.config/lel/config.json`: ```json { "hotkey": "Cmd+m", "edit_hotkey": "Cmd+n", "ffmpeg_input": "pulse:default", "ffmpeg_path": "", "whisper_model": "base", "whisper_lang": "en", "whisper_device": "cpu", "record_timeout_sec": 120, "edit_record_timeout_sec": 120, "injection_backend": "clipboard", "edit_injection_backend": "clipboard", "languages": { "en": { "code": "en", "hotkey": "Cmd+m", "label": "English" }, "ptBR": { "code": "pt-BR", "hotkey": "Cmd+b", "label": "Português (Brasil)" } }, "edit_language_detection": { "enabled": true, "provider": "langdetect", "fallback_code": "en" }, "context_capture": { "provider": "i3ipc", "on_focus_change": "abort" }, "context_rules": [ { "tag": "terminal", "match": { "class": "Alacritty" }, "ai_enabled": false }, { "tag": "chat", "match": { "title_contains": "Slack" }, "ai_prompt_file": "/home/thales/.config/lel/prompts/slack.txt" } ], "ai_enabled": true, "ai_model": "llama3.2:3b", "ai_temperature": 0.0, "ai_system_prompt_file": "", "ai_base_url": "http://localhost:11434/v1/chat/completions", "ai_api_key": "", "ai_timeout_sec": 20, "edit_ai_enabled": true, "edit_ai_temperature": 0.0, "edit_ai_system_prompt_file": "", "edit_window": { "width": 800, "height": 400 } } ``` Env overrides: - `WHISPER_MODEL`, `WHISPER_LANG`, `WHISPER_DEVICE` - `WHISPER_FFMPEG_IN` - `LEL_RECORD_TIMEOUT_SEC`, `LEL_HOTKEY`, `LEL_INJECTION_BACKEND` - `LEL_EDIT_RECORD_TIMEOUT_SEC`, `LEL_EDIT_HOTKEY`, `LEL_EDIT_INJECTION_BACKEND` - `LEL_FFMPEG_PATH` - `LEL_AI_ENABLED`, `LEL_AI_MODEL`, `LEL_AI_TEMPERATURE`, `LEL_AI_SYSTEM_PROMPT_FILE` - `LEL_AI_BASE_URL`, `LEL_AI_API_KEY`, `LEL_AI_TIMEOUT_SEC` - `LEL_EDIT_AI_ENABLED`, `LEL_EDIT_AI_TEMPERATURE`, `LEL_EDIT_AI_SYSTEM_PROMPT_FILE` - `LEL_CONTEXT_PROVIDER`, `LEL_CONTEXT_ON_FOCUS_CHANGE` - `LEL_LANGUAGES_JSON`, `LEL_EDIT_LANG_FALLBACK` ## systemd user service ```bash mkdir -p ~/.local/bin cp src/leld.py ~/.local/bin/leld.py cp systemd/lel.service ~/.config/systemd/user/lel.service systemctl --user daemon-reload systemctl --user enable --now lel ``` ## Usage - Press the hotkey once to start recording. - Press it again to stop and transcribe. - The transcript is logged to stderr. - Press the edit hotkey to open the edit window; click Apply to edit using spoken instructions. - Default language hotkeys: English `Cmd+m`, Portuguese (Brazil) `Cmd+b`. Edit workflow notes: - Uses the X11 primary selection (currently selected text). - Opens a floating GTK window with the selected text. - Records your spoken edit instruction until you click Apply. Injection backends: - `clipboard`: copy to clipboard and inject via Ctrl+Shift+V (GTK clipboard + XTest) - `injection`: type the text with simulated keypresses (XTest) AI provider: - Generic OpenAI-compatible chat API at `ai_base_url` Context capture: - `context_capture` stores the focused window at hotkey time (via i3 IPC). - If focus changes before injection, the workflow aborts (interpreted as a cancel). - `context_rules` lets you match on app/title and override AI/injection behavior. Control: ```bash make run ```