fix windows hotkey performance

This commit is contained in:
Andrew Ward
2024-05-05 18:19:50 +01:00
parent 960fd8c572
commit 3843a93c09
3 changed files with 55 additions and 27 deletions

View File

@@ -65,7 +65,8 @@ To get this script working you will need to install the following on the relevan
* pip install pydub * pip install pydub
* pip install keyboard * pip install keyboard
* pip install pystray * pip install pystray
* pip install playsound * pip install pygame
### Mac ### Mac
@@ -88,10 +89,19 @@ To get this script working you will need to install the following on the relevan
pip install --upgrade pip # Ensure pip is updated pip install --upgrade pip # Ensure pip is updated
pip install pyinstaller # Install PyInstaller pip install pyinstaller # Install PyInstaller
OLD:
python -m PyInstaller --onefile --windowed text-to-mic.py python -m PyInstaller --onefile --windowed text-to-mic.py
New
python -m PyInstaller --onefile --add-data "assets;assets" text-to-mic.py
## Mac ## Mac
brew install python brew install python
pip3 install pyinstaller pip3 install pyinstaller
OLD
pyinstaller --onefile --windowed text-to-mic.py pyinstaller --onefile --windowed text-to-mic.py
New
pyinstaller --onefile --add-data "assets:assets" text-to-mic.py

View File

@@ -7,7 +7,7 @@ import wave
import webbrowser import webbrowser
import json import json
import keyboard import keyboard
import pygame import sys
from pystray import Icon as icon, MenuItem as item, Menu as menu from pystray import Icon as icon, MenuItem as item, Menu as menu
from PIL import Image, ImageDraw from PIL import Image, ImageDraw
@@ -16,6 +16,7 @@ from openai import OpenAI
from dotenv import load_dotenv from dotenv import load_dotenv
from pathlib import Path from pathlib import Path
from pydub import AudioSegment from pydub import AudioSegment
from audioplayer import AudioPlayer
@@ -107,9 +108,9 @@ class Application(tk.Tk):
def setup_hotkeys(self): def setup_hotkeys(self):
# Register global hotkeys # Register global hotkeys
keyboard.add_hotkey('ctrl+shift+r', lambda: self.hotkey_record_trigger()) keyboard.add_hotkey('ctrl+shift+0', lambda: self.hotkey_record_trigger())
keyboard.add_hotkey('ctrl+shift+s', lambda: self.hotkey_stop_trigger() ) keyboard.add_hotkey('ctrl+shift+9', lambda: self.hotkey_stop_trigger() )
keyboard.add_hotkey('ctrl+shift+l', lambda: self.hotkey_play_last_audio_trigger() ) keyboard.add_hotkey('ctrl+shift+8', lambda: self.hotkey_play_last_audio_trigger() )
def hotkey_play_last_audio_trigger(self): def hotkey_play_last_audio_trigger(self):
if hasattr(self, 'last_audio_file'): if hasattr(self, 'last_audio_file'):
@@ -122,30 +123,42 @@ class Application(tk.Tk):
self.play_sound('assets/wrong-short.wav') self.play_sound('assets/wrong-short.wav')
if self.recording: if self.recording:
self.stop_recording(auto_play=False) self.stop_recording(auto_play=False)
self.recording=False
# Sounds from https://mixkit.co/free-sound-effects/notification/ # Sounds from https://mixkit.co/free-sound-effects/notification/
def hotkey_record_trigger(self): def hotkey_record_trigger(self):
if self.recording: if self.recording:
self.play_sound('assets/mixkit-message-pop-alert-2354.mp3') self.play_sound('assets/pop.wav')
self.submit_text() self.submit_text()
else: else:
input_device_index = self.input_device_index.get() # Assuming input_device_index is a StringVar if not self.recording:
input_device_id = self.available_input_devices.get(input_device_index) self.start_recording(play_confirm_sound=True)
if input_device_id is None: else:
self.play_sound('assets/please-select-input.wav') self.stop_recording(auto_play=True)
return
self.play_sound('assets/mixkit-message-pop-alert-2354.mp3')
self.toggle_recording()
def play_sound(self, sound_file): def play_sound(self, sound_file):
pygame.init() player = AudioPlayer(self.resource_path(sound_file))
pygame.mixer.init() player.play(block=True)
sound = pygame.mixer.Sound(sound_file)
sound.play() def resource_path(self, relative_path):
"""Get the absolute path to the resource, works for development and PyInstaller."""
try:
# When running in a PyInstaller bundle, use the '_MEIPASS' directory
base_path = sys._MEIPASS
except AttributeError:
# When running live, use the directory where this file is located
base_path = os.path.dirname(os.path.abspath(__file__))
return os.path.join(base_path, relative_path)
return os.path.join(base_path, relative_path)
def initialize_gui(self): def initialize_gui(self):
@@ -233,13 +246,13 @@ class Application(tk.Tk):
instruction_window.geometry("400x300") # Width x Height instruction_window.geometry("400x300") # Width x Height
instructions = """How to use Hotkeys instructions = """How to use Hotkeys
ctrl+shift+r ctrl+shift+0
This starts a recording, then converts to text and plays when you press this hotkey again. This starts a recording, then converts to text and plays when you press this hotkey again.
ctrl+shift+s ctrl+shift+9
If you are recording, you can press this hotkey to stop recording without playing If you are recording, you can press this hotkey to stop recording without playing
ctrl+shift+l ctrl+shift+8
This replays the last audio clip played This replays the last audio clip played
""" """
@@ -618,16 +631,19 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
def stop_recording_btn_change(self, btn_text): def stop_recording_btn_change(self, btn_text):
self.record_button.config(text=btn_text) self.record_button.config(text=btn_text)
def start_recording(self):
def start_recording(self, play_confirm_sound=False):
input_device_index = self.input_device_index.get() # Assuming input_device_index is a StringVar input_device_index = self.input_device_index.get() # Assuming input_device_index is a StringVar
input_device_id = self.available_input_devices.get(input_device_index) input_device_id = self.available_input_devices.get(input_device_index)
if input_device_id is None: if input_device_id is None:
if play_confirm_sound:
self.play_sound('assets/please-select-input.wav')
else:
messagebox.showerror("Error", "Selected audio device is not available.") messagebox.showerror("Error", "Selected audio device is not available.")
return return
device_info = self.get_device_info(input_device_id) device_info = self.get_device_info(input_device_id)
sample_rate = int(device_info['defaultSampleRate']) sample_rate = int(device_info['defaultSampleRate'])
@@ -653,6 +669,8 @@ https://www.scorchsoft.com/blog/text-to-mic-for-meetings/
self.p = pyaudio.PyAudio() self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=pyaudio.paInt16, channels=1, rate=sample_rate, input=True, frames_per_buffer=1024, input_device_index=input_device_id) self.stream = self.p.open(format=pyaudio.paInt16, channels=1, rate=sample_rate, input=True, frames_per_buffer=1024, input_device_index=input_device_id)
if play_confirm_sound:
self.play_sound('assets/pop.wav')
def record(): def record():
while self.recording: while self.recording:

View File

@@ -5,7 +5,7 @@ a = Analysis(
['text-to-mic.py'], ['text-to-mic.py'],
pathex=[], pathex=[],
binaries=[], binaries=[],
datas=[], datas=[('assets', 'assets')],
hiddenimports=[], hiddenimports=[],
hookspath=[], hookspath=[],
hooksconfig={}, hooksconfig={},
@@ -29,7 +29,7 @@ exe = EXE(
upx=True, upx=True,
upx_exclude=[], upx_exclude=[],
runtime_tmpdir=None, runtime_tmpdir=None,
console=False, console=True,
disable_windowed_traceback=False, disable_windowed_traceback=False,
argv_emulation=False, argv_emulation=False,
target_arch=None, target_arch=None,