fix config issue, add args parse, cleanup sys tray
This commit is contained in:
parent
452561fb5b
commit
8de60d7739
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ web/.node-persist/*
|
|||||||
agent-mAId/output.wav
|
agent-mAId/output.wav
|
||||||
agent-mAId/build/*
|
agent-mAId/build/*
|
||||||
agent-mAId/dist/main.exe
|
agent-mAId/dist/main.exe
|
||||||
|
agent-mAId/output.wav
|
||||||
|
@ -16,9 +16,12 @@ import time
|
|||||||
import json5
|
import json5
|
||||||
import wave
|
import wave
|
||||||
import pyperclip
|
import pyperclip
|
||||||
|
import argparse
|
||||||
|
import atexit
|
||||||
|
|
||||||
# # Load configuration from config.json
|
# # Load configuration from config.json
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
|
"api_key": "xxx",
|
||||||
"kb_key": "ctrl",
|
"kb_key": "ctrl",
|
||||||
"mouse_btn": "left",
|
"mouse_btn": "left",
|
||||||
"model": "distil-whisper-large-v3-en",
|
"model": "distil-whisper-large-v3-en",
|
||||||
@ -26,20 +29,29 @@ DEFAULT_CONFIG = {
|
|||||||
"action": "type" # type, copy
|
"action": "type" # type, copy
|
||||||
}
|
}
|
||||||
|
|
||||||
def load_config():
|
def parse_args():
|
||||||
|
"""Parse command line arguments for config file."""
|
||||||
|
parser = argparse.ArgumentParser(description='Run the AI transcription app.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--config', type=str, help='Path to config file', default=None
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def load_config(config_path=None):
|
||||||
"""Load the configuration file, adjusting for PyInstaller's temp path when bundled."""
|
"""Load the configuration file, adjusting for PyInstaller's temp path when bundled."""
|
||||||
config = DEFAULT_CONFIG.copy() # Start with default configuration
|
config = DEFAULT_CONFIG.copy() # Start with default configuration
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Determine if the script is running as a PyInstaller bundle
|
if config_path is None:
|
||||||
if getattr(sys, 'frozen', False):
|
# Determine if the script is running as a PyInstaller bundle
|
||||||
# If running in a bundle, use the temp path where PyInstaller extracts files
|
if getattr(sys, 'frozen', False):
|
||||||
config_path = os.path.join(sys._MEIPASS, 'config.json')
|
# If running in a bundle, use the temp path where PyInstaller extracts files
|
||||||
else:
|
config_path = os.path.join(sys._MEIPASS, 'config.json')
|
||||||
# If running in development (normal execution), use the local directory
|
else:
|
||||||
config_path = os.path.join(os.path.dirname(__file__), 'config.json')
|
# If running in development (normal execution), use the local directory
|
||||||
|
config_path = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||||
|
|
||||||
print('Trying to load config from:', config_path)
|
print(f'Trying to load config from: {config_path}')
|
||||||
with open(config_path, 'r') as config_file:
|
with open(config_path, 'r') as config_file:
|
||||||
loaded_config = json5.load(config_file)
|
loaded_config = json5.load(config_file)
|
||||||
# Update the default config with any values from config.json
|
# Update the default config with any values from config.json
|
||||||
@ -47,6 +59,7 @@ def load_config():
|
|||||||
|
|
||||||
except FileNotFoundError as ex:
|
except FileNotFoundError as ex:
|
||||||
print("Config file not found, using defaults." + ex.strerror)
|
print("Config file not found, using defaults." + ex.strerror)
|
||||||
|
raise ex
|
||||||
except json5.JSONDecodeError as ex:
|
except json5.JSONDecodeError as ex:
|
||||||
print("Error decoding config file, using defaults." + ex.msg)
|
print("Error decoding config file, using defaults." + ex.msg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -55,7 +68,13 @@ def load_config():
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
# Load the config
|
# Load the config
|
||||||
config = load_config()
|
# config = load_config()
|
||||||
|
# Parse command line arguments
|
||||||
|
args = parse_args()
|
||||||
|
|
||||||
|
# Load the config from the specified path or default location
|
||||||
|
config = load_config(args.config)
|
||||||
|
|
||||||
# Extract API key and button from the config file
|
# Extract API key and button from the config file
|
||||||
API_KEY = config['api_key']
|
API_KEY = config['api_key']
|
||||||
KB_KEY = config['kb_key']
|
KB_KEY = config['kb_key']
|
||||||
@ -63,6 +82,7 @@ MOUSE_BTN = config['mouse_btn']
|
|||||||
MODEL = config['model']
|
MODEL = config['model']
|
||||||
POST_TRANSCRIBE = config['action']
|
POST_TRANSCRIBE = config['action']
|
||||||
|
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
AUTO_START_PATH = os.path.expanduser(r"~\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup") # For autostart
|
AUTO_START_PATH = os.path.expanduser(r"~\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup") # For autostart
|
||||||
|
|
||||||
@ -131,7 +151,8 @@ def transcribe_audio(memory_stream):
|
|||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
|
|
||||||
transcription_time = end_time - start_time
|
transcription_time = end_time - start_time
|
||||||
print(f"Transcription took: {transcription_time:.2f} seconds.")
|
print(f"Transcription took: {transcription_time:.2f} seconds. Result: {transcription.text}")
|
||||||
|
log_transcription_time(transcription_time)
|
||||||
|
|
||||||
return transcription.text
|
return transcription.text
|
||||||
|
|
||||||
@ -150,16 +171,32 @@ def add_to_autostart():
|
|||||||
shell.ShellExecuteW(None, "runas", "cmd.exe", f'/C mklink "{shortcut_path}" "{script_path}"', None, 1)
|
shell.ShellExecuteW(None, "runas", "cmd.exe", f'/C mklink "{shortcut_path}" "{script_path}"', None, 1)
|
||||||
print("App added to autostart.")
|
print("App added to autostart.")
|
||||||
|
|
||||||
def quit_app(icon):
|
icon = None # Global variable to store the tray icon object
|
||||||
"""Quit the tray application."""
|
def cleanup_and_exit():
|
||||||
icon.stop()
|
"""Clean up the tray icon and exit the application."""
|
||||||
|
global icon
|
||||||
|
if icon:
|
||||||
|
print("Stopping and removing tray icon...")
|
||||||
|
icon.stop() # Stop the tray icon to remove it from the tray
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
def setup_tray_icon():
|
def setup_tray_icon():
|
||||||
|
global icon
|
||||||
"""Setup system tray icon and menu."""
|
"""Setup system tray icon and menu."""
|
||||||
#icon_image = Image.new('RGB', (64, 64), color=(255, 0, 0)) # Red icon as an example
|
if getattr(sys, 'frozen', False):
|
||||||
icon_image = Image.open('mic.webp')
|
# If running as a bundle, use the temp path where PyInstaller extracts files
|
||||||
|
icon_path = os.path.join(sys._MEIPASS, 'mic.webp')
|
||||||
|
else:
|
||||||
|
# If running in development (normal execution), use the local directory
|
||||||
|
icon_path = os.path.join(os.path.dirname(__file__), 'mic.webp')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load the tray icon
|
||||||
|
icon_image = Image.open(icon_path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Icon file not found at {icon_path}")
|
||||||
|
icon_image = Image.new('RGB', (64, 64), color=(255, 0, 0)) # Red icon as an example
|
||||||
|
return
|
||||||
|
|
||||||
menu = (
|
menu = (
|
||||||
item('Register to Autostart', add_to_autostart),
|
item('Register to Autostart', add_to_autostart),
|
||||||
@ -169,10 +206,26 @@ def setup_tray_icon():
|
|||||||
icon = pystray.Icon("mAId", icon_image, menu=pystray.Menu(*menu))
|
icon = pystray.Icon("mAId", icon_image, menu=pystray.Menu(*menu))
|
||||||
icon.run()
|
icon.run()
|
||||||
|
|
||||||
|
# Ensure the tray icon is removed when the app exits
|
||||||
|
atexit.register(cleanup_and_exit)
|
||||||
|
|
||||||
response_times = []
|
response_times = []
|
||||||
ma_window_size = 10 # Moving average over the last 10 responses
|
ma_window_size = 10 # Moving average over the last 10 responses
|
||||||
|
def log_transcription_time(transcription_time):
|
||||||
|
"""Logs the transcription time and updates the moving average."""
|
||||||
|
global response_times
|
||||||
|
|
||||||
|
# Add the transcription time to the list
|
||||||
|
response_times.append(transcription_time)
|
||||||
|
|
||||||
|
# If the number of logged times exceeds the window size, remove the oldest entry
|
||||||
|
if len(response_times) > ma_window_size:
|
||||||
|
response_times.pop(0)
|
||||||
|
|
||||||
|
# Calculate and print the moving average
|
||||||
|
moving_average = sum(response_times) / len(response_times)
|
||||||
|
print(f"Moving Average of Transcription Time (last {ma_window_size} responses): {moving_average:.2f} seconds.")
|
||||||
|
|
||||||
|
|
||||||
def main_loop():
|
def main_loop():
|
||||||
"""Continuously listen for key or mouse press and transcribe audio."""
|
"""Continuously listen for key or mouse press and transcribe audio."""
|
||||||
@ -201,7 +254,10 @@ def main_loop():
|
|||||||
pyperclip.copy(transcribed_text)
|
pyperclip.copy(transcribed_text)
|
||||||
print("Transcribed text copied to clipboard.")
|
print("Transcribed text copied to clipboard.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
# Start the tray icon in a separate thread so it doesn't block the main functionality
|
# Start the tray icon in a separate thread so it doesn't block the main functionality
|
||||||
tray_thread = threading.Thread(target=setup_tray_icon)
|
tray_thread = threading.Thread(target=setup_tray_icon)
|
||||||
tray_thread.daemon = True
|
tray_thread.daemon = True
|
||||||
|
@ -5,7 +5,7 @@ a = Analysis(
|
|||||||
['main.py'],
|
['main.py'],
|
||||||
pathex=[],
|
pathex=[],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[('config.json', '.'), ('mic.webp', '.')],
|
||||||
hiddenimports=[],
|
hiddenimports=[],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
@ -14,6 +14,7 @@ a = Analysis(
|
|||||||
noarchive=False,
|
noarchive=False,
|
||||||
optimize=0,
|
optimize=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
pyz = PYZ(a.pure)
|
pyz = PYZ(a.pure)
|
||||||
|
|
||||||
exe = EXE(
|
exe = EXE(
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user