whisper-dictation/main.py

112 lines
3.3 KiB
Python

# main.py
import os
import queue
import sys
import threading
def _setup_error_log():
"""Last-resort error log for crashes before tray appears (frozen mode)."""
if not getattr(sys, "frozen", False):
return
import traceback
if os.name == "nt":
log_dir = os.path.join(os.environ.get("LOCALAPPDATA", ""), "WhisperDictation")
else:
log_dir = os.path.join(os.path.expanduser("~"), ".local", "share", "WhisperDictation")
os.makedirs(log_dir, exist_ok=True)
log_path = os.path.join(log_dir, "error.log")
sys.excepthook = lambda *args: open(log_path, "a").write(
"".join(traceback.format_exception(*args)) + "\n"
)
def main():
_setup_error_log()
from whisper_app import app, config, audio, transcriber, hotkey
from whisper_app import overlay, tray, log_window, settings_window, vocab_window
import tkinter as tk
config.load_config()
config.load_vocab()
# Tkinter root (hidden)
root = tk.Tk()
root.withdraw()
app.overlay_tk = root
# Log queue — connect before model load so early messages appear
log_q: queue.Queue = queue.Queue()
app.set_log_queue(log_q)
# Windows
overlay.create(root)
log_win = log_window.create(
root, log_q,
on_settings=lambda: settings_window.open(root, _reload),
on_vocab=lambda: vocab_window.open(root),
)
# Load model in background so the tray appears immediately
threading.Thread(target=transcriber.load_model, daemon=True).start()
# Audio stream with device hotplug monitoring
app.audio_manager = audio.AudioManager()
app.audio_manager.start()
# Hotkey
def _on_release():
threading.Thread(target=transcriber.stop_and_transcribe, daemon=True).start()
app.hotkey_listener = hotkey.HotkeyListener(
config.config["hotkey"],
on_press=_start_recording,
on_release=_on_release,
)
# Tray
icon = tray.create(
on_settings=lambda: settings_window.open(root, _reload),
on_vocab=lambda: vocab_window.open(root),
on_show_log=lambda: root.after(0, log_window.show),
on_quit=lambda: _quit(icon),
)
threading.Thread(target=icon.run, daemon=True).start()
app.log(f"Bereit. Hotkey: {config.config['hotkey']}")
root.mainloop()
app.audio_manager.stop()
def _start_recording():
from whisper_app import app, transcriber
app.audio_chunks = []
transcriber.set_state(app.AppState.RECORDING)
app.log("Recording...")
def _reload():
from whisper_app import app, config, transcriber, hotkey
if app.hotkey_listener:
app.hotkey_listener.stop()
threading.Thread(target=transcriber.load_model, daemon=True).start()
if app.audio_manager:
app.audio_manager.restart()
app.hotkey_listener = hotkey.HotkeyListener(
config.config["hotkey"],
on_press=_start_recording,
on_release=lambda: threading.Thread(
target=transcriber.stop_and_transcribe, daemon=True).start(),
)
app.log(f"Hotkey aktualisiert: {config.config['hotkey']}")
def _quit(icon):
from whisper_app import app
if app.audio_manager:
app.audio_manager.stop()
icon.stop()
if app.overlay_tk:
app.overlay_tk.after(0, app.overlay_tk.quit)
if __name__ == "__main__":
import multiprocessing
multiprocessing.freeze_support()
main()