from vosk import Model, KaldiRecognizer import sounddevice as sd import json import pyperclip # Biblioteka do obsługi schowka import pyautogui import sys import tkinter as tk from threading import Thread # Ścieżka do modelu model_path = "./vosk-model-small-pl-0.22" model = Model(model_path) recognizer = KaldiRecognizer(model, 16000) listening = False # Flaga stanu nasłuchiwania emacs_mode = False # Flaga trybu Emacs # Funkcja obsługi danych audio def callback(indata, frames, time, status): if status: print(f"Status: {status}", file=sys.stderr) # Konwersja danych na `bytes` data = bytes(indata) if recognizer.AcceptWaveform(data): result = json.loads(recognizer.Result()) text = result.get("text", "") if text: print(f"Rozpoznano: {text}") insert_text_with_clipboard(text) # Funkcja kopiowania do schowka i wklejania def insert_text_with_clipboard(text): try: pyperclip.copy(text) # Kopiowanie tekstu do schowka if emacs_mode: pyautogui.hotkey('shift', 'insert') # Wklejanie w trybie Emacs else: pyautogui.hotkey('ctrl', 'v') # Standardowe wklejanie pyautogui.press('space') # Dodanie spacji (opcjonalne) except Exception as e: print(f"Błąd podczas wklejania tekstu: {e}", file=sys.stderr) # Funkcja nasłuchiwania i rozpoznawania mowy def listen_and_type(): global listening print("Słucham... (naciśnij Stop, aby zatrzymać)") try: with sd.RawInputStream(samplerate=16000, blocksize=8000, dtype='int16', channels=1, callback=callback): while listening: pass # Nasłuchiwanie trwa w pętli except Exception as e: print(f"Błąd podczas nasłuchiwania: {e}", file=sys.stderr) # Funkcje sterujące GUI def toggle_listening(): global listening if listening: listening = False update_button_state() print("Nasłuchiwanie zatrzymane.") else: listening = True update_button_state() thread = Thread(target=listen_and_type) thread.daemon = True thread.start() def toggle_emacs_mode(): global emacs_mode emacs_mode = not emacs_mode update_emacs_button_state() mode = "Emacs" if emacs_mode else "Standard" print(f"Tryb wklejania: {mode}") # Aktualizacja stanu przycisków def update_button_state(): if listening: toggle_button.config(text="Stop", bg="red", fg="white") else: toggle_button.config(text="Start", bg="lightgrey", fg="black") def update_emacs_button_state(): if emacs_mode: emacs_button.config(text="Tryb: Emacs", bg="blue", fg="white") else: emacs_button.config(text="Tryb: Standard", bg="lightgrey", fg="black") # Funkcja obsługi skrótu klawiszowego def handle_shortcut(event): if event.keysym == 'F1': # F1 jako skrót klawiszowy toggle_listening() # Tworzenie GUI def create_gui(): global toggle_button, emacs_button root = tk.Tk() root.title("Vosk Rozpoznawanie Mowy") root.geometry("300x200") toggle_button = tk.Button(root, text="Start", command=toggle_listening, width=15, bg="lightgrey", fg="black") toggle_button.pack(pady=10) emacs_button = tk.Button(root, text="Tryb: Standard", command=toggle_emacs_mode, width=15, bg="lightgrey", fg="black") emacs_button.pack(pady=10) exit_button = tk.Button(root, text="Wyjście", command=root.destroy, width=15) exit_button.pack(pady=10) # Dodanie skrótu klawiszowego root.bind("", handle_shortcut) root.mainloop() # Uruchomienie GUI if __name__ == "__main__": create_gui()