From 40ad24f27c9431088dd774e814be888733255973 Mon Sep 17 00:00:00 2001 From: McElwain Date: Wed, 1 Apr 2026 08:30:39 -0500 Subject: [PATCH] initial import of transcriber --- audiotext.spec | 126 +++ config.ini | 15 + requirements.txt | Bin 0 -> 752 bytes res/img/file-explorer.png | Bin 0 -> 230 bytes res/img/icon-dark.png | Bin 0 -> 61810 bytes res/img/icon-light.png | Bin 0 -> 60880 bytes res/img/icon.icns | Bin 0 -> 51395 bytes res/img/icon.ico | Bin 0 -> 35259 bytes res/locales/en/LC_MESSAGES/app.mo | Bin 0 -> 1988 bytes res/locales/en/LC_MESSAGES/app.po | 117 +++ res/locales/en/LC_MESSAGES/main_controller.po | 69 ++ res/locales/en/LC_MESSAGES/main_window.po | 62 ++ res/locales/es/LC_MESSAGES/app.mo | Bin 0 -> 2134 bytes res/locales/es/LC_MESSAGES/app.po | 116 +++ res/locales/es/LC_MESSAGES/main_controller.po | 69 ++ res/locales/es/LC_MESSAGES/main_window.po | Bin 0 -> 3550 bytes src/app.py | 71 ++ src/controller/__init__.py | 0 .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 150 bytes .../main_controller.cpython-313.pyc | Bin 0 -> 18688 bytes src/controller/main_controller.py | 354 ++++++++ src/model/__init__.py | 0 .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 145 bytes src/model/config/__init__.py | 0 .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 152 bytes .../config_google_api.cpython-313.pyc | Bin 0 -> 1287 bytes .../config_subtitles.cpython-313.pyc | Bin 0 -> 1516 bytes .../config_whisperx.cpython-313.pyc | Bin 0 -> 1696 bytes src/model/config/config_google_api.py | 26 + src/model/config/config_subtitles.py | 30 + src/model/config/config_whisperx.py | 41 + src/model/transcription.py | 17 + src/utils/__init__.py | 0 .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 145 bytes .../__pycache__/audio_utils.cpython-313.pyc | Bin 0 -> 1354 bytes .../config_manager.cpython-313.pyc | Bin 0 -> 5513 bytes .../__pycache__/constants.cpython-313.pyc | Bin 0 -> 3012 bytes .../__pycache__/path_helper.cpython-313.pyc | Bin 0 -> 1058 bytes src/utils/audio_utils.py | 26 + src/utils/config_manager.py | 110 +++ src/utils/constants.py | 104 +++ src/utils/dict_utils.py | 5 + src/utils/enums.py | 40 + src/utils/i18n.py | 44 + src/utils/path_helper.py | 26 + src/view/__init__.py | 0 src/view/custom_widgets/__init__.py | 0 src/view/custom_widgets/ctk_input_dialog.py | 168 ++++ .../ctk_scrollable_dropdown/__init__.py | 12 + .../ctk_scrollable_dropdown.py | 453 ++++++++++ .../ctk_scrollable_dropdown_frame.py | 399 +++++++++ src/view/main_window.py | 774 ++++++++++++++++++ 52 files changed, 3274 insertions(+) create mode 100644 audiotext.spec create mode 100644 config.ini create mode 100644 requirements.txt create mode 100644 res/img/file-explorer.png create mode 100644 res/img/icon-dark.png create mode 100644 res/img/icon-light.png create mode 100644 res/img/icon.icns create mode 100644 res/img/icon.ico create mode 100644 res/locales/en/LC_MESSAGES/app.mo create mode 100644 res/locales/en/LC_MESSAGES/app.po create mode 100644 res/locales/en/LC_MESSAGES/main_controller.po create mode 100644 res/locales/en/LC_MESSAGES/main_window.po create mode 100644 res/locales/es/LC_MESSAGES/app.mo create mode 100644 res/locales/es/LC_MESSAGES/app.po create mode 100644 res/locales/es/LC_MESSAGES/main_controller.po create mode 100644 res/locales/es/LC_MESSAGES/main_window.po create mode 100644 src/app.py create mode 100644 src/controller/__init__.py create mode 100644 src/controller/__pycache__/__init__.cpython-313.pyc create mode 100644 src/controller/__pycache__/main_controller.cpython-313.pyc create mode 100644 src/controller/main_controller.py create mode 100644 src/model/__init__.py create mode 100644 src/model/__pycache__/__init__.cpython-313.pyc create mode 100644 src/model/config/__init__.py create mode 100644 src/model/config/__pycache__/__init__.cpython-313.pyc create mode 100644 src/model/config/__pycache__/config_google_api.cpython-313.pyc create mode 100644 src/model/config/__pycache__/config_subtitles.cpython-313.pyc create mode 100644 src/model/config/__pycache__/config_whisperx.cpython-313.pyc create mode 100644 src/model/config/config_google_api.py create mode 100644 src/model/config/config_subtitles.py create mode 100644 src/model/config/config_whisperx.py create mode 100644 src/model/transcription.py create mode 100644 src/utils/__init__.py create mode 100644 src/utils/__pycache__/__init__.cpython-313.pyc create mode 100644 src/utils/__pycache__/audio_utils.cpython-313.pyc create mode 100644 src/utils/__pycache__/config_manager.cpython-313.pyc create mode 100644 src/utils/__pycache__/constants.cpython-313.pyc create mode 100644 src/utils/__pycache__/path_helper.cpython-313.pyc create mode 100644 src/utils/audio_utils.py create mode 100644 src/utils/config_manager.py create mode 100644 src/utils/constants.py create mode 100644 src/utils/dict_utils.py create mode 100644 src/utils/enums.py create mode 100644 src/utils/i18n.py create mode 100644 src/utils/path_helper.py create mode 100644 src/view/__init__.py create mode 100644 src/view/custom_widgets/__init__.py create mode 100644 src/view/custom_widgets/ctk_input_dialog.py create mode 100644 src/view/custom_widgets/ctk_scrollable_dropdown/__init__.py create mode 100644 src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown.py create mode 100644 src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown_frame.py create mode 100644 src/view/main_window.py diff --git a/audiotext.spec b/audiotext.spec new file mode 100644 index 0000000..f27ab45 --- /dev/null +++ b/audiotext.spec @@ -0,0 +1,126 @@ +# -*- mode: python ; coding: utf-8 -*- +from os.path import join +from platform import system +from PyInstaller.utils.hooks import copy_metadata +from PyInstaller.utils.hooks import collect_data_files +from shutil import copyfile + +datas = [ + (r'venv/Lib/site-packages/customtkinter', 'customtkinter'), + (r'venv/Lib/site-packages/transformers', 'transformers'), + (r'venv/Lib/site-packages/lightning', 'lightning'), + (r'venv/Lib/site-packages/lightning_fabric', 'lightning_fabric'), + (r'venv/Lib/site-packages/speechbrain', 'speechbrain'), + (r'venv/Lib/site-packages/pyannote', 'pyannote'), + (r'venv/Lib/site-packages/asteroid_filterbanks', 'asteroid_filterbanks'), + (r'venv/Lib/site-packages/whisperx', 'whisperx'), + ('res', 'res') +] + +datas += copy_metadata('torch') +datas += copy_metadata('tqdm', recursive=True) +datas += copy_metadata('regex') +datas += copy_metadata('requests') +datas += copy_metadata('packaging') +datas += copy_metadata('filelock') +datas += copy_metadata('numpy') +datas += copy_metadata('tokenizers') +datas += copy_metadata('pillow') +datas += copy_metadata('huggingface_hub') +datas += copy_metadata('safetensors') +datas += copy_metadata('pyyaml') +datas += collect_data_files('librosa') + +block_cipher = None + +a = Analysis( + ['src/app.py'], + pathex=[], + binaries=[], + datas=datas, + hiddenimports=['huggingface_hub.repository', 'pytorch', 'sklearn.utils._cython_blas', 'sklearn.neighbors.typedefs', 'sklearn.neighbors.quad_tree', 'sklearn.tree', 'sklearn.tree._utils'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False, +) + +# Filter out unused and/or duplicate shared libs +torch_lib_paths = { + join('torch', 'lib', 'libtorch_cuda.so'), + join('torch', 'lib', 'libtorch_cpu.so'), +} +a.datas = [entry for entry in a.datas if not entry[0] in torch_lib_paths] + +os_path_separator = '\\' if system() == 'Windows' else '/' +a.datas = [entry for entry in a.datas if not f'torch{os_path_separator}_C.cp' in entry[0]] +a.datas = [entry for entry in a.datas if not f'torch{os_path_separator}_dl.cp' in entry[0]] + +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + +if system() == 'Darwin': # macOS + exe = EXE( + pyz, + a.scripts, + a.binaries, + a.zipfiles, + a.datas, + [], + name='Audiotext', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch='x86_64', + codesign_identity=None, + entitlements_file=None, + icon=['res/img/icon.icns'], + ) + + # BUNDLE statement is used to create a macOS application bundle (.app) for the program + app = BUNDLE( + exe, + name='Audiotext.app', + icon=['res/img/icon.icns'], + bundle_identifier=None, + ) +else: + exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='Audiotext', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch='x86_64', + codesign_identity=None, + entitlements_file=None, + icon=['res/img/icon.ico'], + ) + coll = COLLECT( + exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='audiotext', + ) + +copyfile('config.ini', '{0}/audiotext/config.ini'.format(DISTPATH)) \ No newline at end of file diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..650fd09 --- /dev/null +++ b/config.ini @@ -0,0 +1,15 @@ +[whisperx] +model_size = large-v2 +batch_size = 8 +compute_type = int8 +use_cpu = True +can_use_gpu = False + +[google_api] +api_key = + +[subtitles] +highlight_words = False +max_line_width = 2 +max_line_count = 42 + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..f502edf7e433e9a97f00d21d4e7ec5f581ef3605 GIT binary patch literal 752 zcmchVO-{o=429nsi92+UGHs}kpb`>iC?^QbD6I%dm8LCR9{B7DB#3=wIiAdW{u$d} zpBo)@P_I^Rd|$OwgN^F+h}!r*+)0 z7%vmla-{g?-#Z$I=!RL0g~xv;Z$viQYVEdFMZG(`EMwzdOZX4JKAAGGhMJ<@IUjjh ztr-z|WY61Inj literal 0 HcmV?d00001 diff --git a/res/img/file-explorer.png b/res/img/file-explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..f758f5c61280c96151b4f56c530ea7934039abe2 GIT binary patch literal 230 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

=Lwn!+Lo?!XeCC?o8$WB~XA@Czs^2CgBqRSWv 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 G7W_YvO@?Iv literal 0 HcmV?d00001 diff --git a/res/img/icon.icns b/res/img/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..64dbf57537d43301c1eac83ba8c5d2438f455b87 GIT binary patch literal 51395 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 literal 0 HcmV?d00001 diff --git a/res/locales/en/LC_MESSAGES/app.po b/res/locales/en/LC_MESSAGES/app.po new file mode 100644 index 0000000..ef28afd --- /dev/null +++ b/res/locales/en/LC_MESSAGES/app.po @@ -0,0 +1,117 @@ +# Copyright (C) 2023 HenestrosaConH +# This file is distributed under the same license as the PACKAGE package. +# José Carlos López Henestrosa , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.3.0\n" +"Report-Msgid-Bugs-To: José Carlos López Henestrosa \n" +"POT-Creation-Date: 2023-02-08 18:22+0100\n" +"PO-Revision-Date: 2023-02-08 18:22+0100\n" +"Last-Translator: José Carlos López Henestrosa \n" +"Language-Team: José Carlos López Henestrosa \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + + +#: src\controller\main_controller.py:35 +msgid "Select a file" +msgstr "Select a file" + +#: src\controller\main_controller.py:37 +msgid "Audio files" +msgstr "Audio files" + +#: src\controller\main_controller.py:38 +msgid "Video files" +msgstr "Video files" + +#: src\controller\main_controller.py:93 +msgid "Error: No audio file selected, please select one before generating text." +msgstr "Error: No audio file selected, please select one before generating text." + +#: src\controller\main_controller.py:116 +msgid "Error: The selected audio language is not valid." +msgstr "Error: The selected audio language is not valid." + +#: src\controller\main_controller.py:120 +#: src\controller\main_controller.py:224 +msgid "Error generating the file transcription. Please try again." +msgstr "Error generating the file transcription. Please try again." + +#: src\controller\main_controller.py:254 +msgid "Error: No microphone detected." +msgstr "Error: No microphone detected." + +#: src\controller\main_controller.py:257 +msgid "Error: Listening timed out while waiting for phrase to start." +msgstr "Error: Listening timed out while waiting for phrase to start." + +#: src\controller\main_controller.py:262 +msgid "Sorry, I cannot clarify what you are saying. Please try again." +msgstr "Sorry, I cannot clarify what you are saying. Please try again." + +#: src\controller\main_controller.py:267 +msgid "Unexpected error. Please try again." +msgstr "Unexpected error. Please try again." + +#: src\controller\main_controller.py:280 +msgid "Save as" +msgstr "Save as" + +#: src\controller\main_controller.py:282 +msgid "Text file" +msgstr "Text file" + +#: src\controller\main_controller.py:282 +msgid "All Files" +msgstr "All Files" + + +#: src\view\main_window.py:62 +#: src\view\main_window.py:204 +msgid "Select file" +msgstr "Select file" + +#: src\view\main_window.py:69 +#: src\view\main_window.py:205 +msgid "Transcribe from microphone" +msgstr "Transcribe from microphone" + +#: src\view\main_window.py:78 +msgid "Generate transcription" +msgstr "Generate transcription" + +#: src\view\main_window.py:86 +msgid "App language" +msgstr "App language" + +#: src\view\main_window.py:102 +msgid "Appearance mode" +msgstr "Appearance mode" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:210 +#: src\view\main_window.py:219 +msgid "System" +msgstr "System" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:218 +msgid "Light" +msgstr "Light" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:217 +msgid "Dark" +msgstr "Dark" + +#: src\view\main_window.py:133 +#: src\view\main_window.py:211 +msgid "Save transcription" +msgstr "Save transcription" diff --git a/res/locales/en/LC_MESSAGES/main_controller.po b/res/locales/en/LC_MESSAGES/main_controller.po new file mode 100644 index 0000000..4172350 --- /dev/null +++ b/res/locales/en/LC_MESSAGES/main_controller.po @@ -0,0 +1,69 @@ +# Copyright (C) 2023 HenestrosaConH +# This file is distributed under the same license as the PACKAGE package. +# José Carlos López Henestrosa , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.3.0\n" +"Report-Msgid-Bugs-To: José Carlos López Henestrosa \n" +"POT-Creation-Date: 2023-02-08 18:22+0100\n" +"PO-Revision-Date: 2023-02-08 18:22+0100\n" +"Last-Translator: José Carlos López Henestrosa \n" +"Language-Team: José Carlos López Henestrosa \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:35 +msgid "Select a file" +msgstr "Select a file" + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:37 +msgid "Audio files" +msgstr "Audio files" + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:38 +msgid "Video files" +msgstr "Video files" + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:93 +msgid "Error: No audio file selected, please select one before generating text." +msgstr "Error: No audio file selected, please select one before generating text." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:116 +msgid "Error: The selected audio language is not valid." +msgstr "Error: The selected audio language is not valid." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:120 +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:224 +msgid "Error generating the file transcription. Please try again." +msgstr "Error generating the file transcription. Please try again." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:254 +msgid "Error: No microphone detected." +msgstr "Error: No microphone detected." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:257 +msgid "Error: Listening timed out while waiting for phrase to start." +msgstr "Error: Listening timed out while waiting for phrase to start." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:262 +msgid "Sorry, I cannot clarify what you are saying. Please try again." +msgstr "Sorry, I cannot clarify what you are saying. Please try again." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:267 +msgid "Unexpected error. Please try again." +msgstr "Unexpected error. Please try again." + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:280 +msgid "Save as" +msgstr "Save as" + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:282 +msgid "Text file" +msgstr "Text file" + +#: D:\Mio\Proyectos\Python\audiotext\src\controller\main_controller.py:282 +msgid "All Files" +msgstr "All Files" diff --git a/res/locales/en/LC_MESSAGES/main_window.po b/res/locales/en/LC_MESSAGES/main_window.po new file mode 100644 index 0000000..3168691 --- /dev/null +++ b/res/locales/en/LC_MESSAGES/main_window.po @@ -0,0 +1,62 @@ +# Copyright (C) 2023 HenestrosaConH +# This file is distributed under the same license as the PACKAGE package. +# José Carlos López Henestrosa , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.3.0\n" +"Report-Msgid-Bugs-To: José Carlos López Henestrosa \n" +"POT-Creation-Date: 2023-02-08 18:22+0100\n" +"PO-Revision-Date: 2023-02-08 18:22+0100\n" +"Last-Translator: José Carlos López Henestrosa \n" +"Language-Team: José Carlos López Henestrosa \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +#: src\view\main_window.py:62 +#: src\view\main_window.py:204 +msgid "Select file" +msgstr "Select file" + +#: src\view\main_window.py:69 +#: src\view\main_window.py:205 +msgid "Transcribe from microphone" +msgstr "Transcribe from microphone" + +#: src\view\main_window.py:78 +msgid "Generate transcription" +msgstr "Generate transcription" + +#: src\view\main_window.py:86 +msgid "App language" +msgstr "App language" + +#: src\view\main_window.py:102 +msgid "Appearance mode" +msgstr "Appearance mode" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:210 +#: src\view\main_window.py:219 +msgid "System" +msgstr "System" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:218 +msgid "Light" +msgstr "Light" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:217 +msgid "Dark" +msgstr "Dark" + +#: src\view\main_window.py:133 +#: src\view\main_window.py:211 +msgid "Save transcription" +msgstr "Save transcription" diff --git a/res/locales/es/LC_MESSAGES/app.mo b/res/locales/es/LC_MESSAGES/app.mo new file mode 100644 index 0000000000000000000000000000000000000000..1db1a0cc1fcdf1f06430b627a6833fd214f601bf GIT binary patch literal 2134 zcmbuA&x;&I6vs=AzeXh{qJpSA5f9?_I6FZZ#$<7`S(DWnvt-8HYr1Q?D|T14Rn?QU z|9}YQrg$|VLJpo*#G^0@<}P>;JqTVrcnY38_^s}lo*fM;WZ2!$R_&`--}hd@qYYz73&AVkHMqhr{DwN7vK@_Yp@S~3!Vbmos69Ww!o*s z_rMPL8Tc6Z19&(1J9sa66Fd(72|ffKy{q>B6u5=;^WZ&T0(w0fd;%=NXTc9aujec9 zJ81X@^!~2ml1IT$K)?PHJO81AHs$t9xtJ2@P)p^>?hTD56E72FE! zmc(N&Rl7dgr-8IisOqT9L`1r9bUDEdbeYS_JvgRn0q0xEbjU(YIN6kHBgthd(xN(^zl9rTqG~=m^+U#td z3m@vC1h9dO6URn;CWzab>jtArJMk)eY_am0W+QD(xj}mra^)`yQ*Pw6M3%UtQWwM# zm*pjLc&j{*N+dXAV?@v6 z!9`&#D&42e_K9|j_@M-)SF1xTE0ruqU=*%#=?1L?Yu<2UTU$ij!+R_ z6>h>r&a`C%;fKH_-wY|`M#qL{oDE@!9pX72p-`dZY@fPHb^Qrzm90r%D*baOgHU^HplQt_@Xg6oYid~Ntcy< z>|{QQbfLew#Y@65+%cP9!ytj*x@P8YIb%C$f6dMo+(g_Enq#$SCQ6mvdWcl4MBx4gtq^z+sIFKJeS4W@QJIk#hT$G gO_c^eeCn(%o{PjZ$noFg|J-u;<;~`wV=l430AZ|>g#Z8m literal 0 HcmV?d00001 diff --git a/res/locales/es/LC_MESSAGES/app.po b/res/locales/es/LC_MESSAGES/app.po new file mode 100644 index 0000000..19a0aec --- /dev/null +++ b/res/locales/es/LC_MESSAGES/app.po @@ -0,0 +1,116 @@ +# Copyright (C) 2023 HenestrosaConH +# This file is distributed under the same license as the PACKAGE package. +# José Carlos López Henestrosa , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.3.0\n" +"Report-Msgid-Bugs-To: José Carlos López Henestrosa \n" +"POT-Creation-Date: 2023-02-08 18:22+0100\n" +"PO-Revision-Date: 2023-02-08 18:22+0100\n" +"Last-Translator: José Carlos López Henestrosa \n" +"Language-Team: José Carlos López Henestrosa \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +#: src\view\main_window.py:62 +#: src\view\main_window.py:204 +msgid "Select file" +msgstr "Selecciona archivo" + +#: src\view\main_window.py:69 +#: src\view\main_window.py:205 +msgid "Transcribe from microphone" +msgstr "Transcribir del micrófono" + +#: src\view\main_window.py:78 +msgid "Generate transcription" +msgstr "Generar transcripción" + +#: src\view\main_window.py:86 +msgid "App language" +msgstr "Lenguaje del programa" + +#: src\view\main_window.py:102 +msgid "Appearance mode" +msgstr "Modo de apariencia" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:210 +#: src\view\main_window.py:219 +msgid "System" +msgstr "Sistema" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:218 +msgid "Light" +msgstr "Claro" + +#: src\view\main_window.py:108 +#: src\view\main_window.py:209 +#: src\view\main_window.py:217 +msgid "Dark" +msgstr "Oscuro" + +#: src\view\main_window.py:133 +#: src\view\main_window.py:211 +msgid "Save transcription" +msgstr "Guardar transcripción" + + +#: src\controller\main_controller.py:35 +msgid "Select a file" +msgstr "Seleccionar archivo" + +#: src\controller\main_controller.py:37 +msgid "Audio files" +msgstr "Archivos de audio" + +#: src\controller\main_controller.py:38 +msgid "Video files" +msgstr "Archivos de vídeo" + +#: src\controller\main_controller.py:93 +msgid "Error: No audio file selected, please select one before generating text." +msgstr "Error: No se ha seleccionado un archivo de audio. Por favor, seleccione uno antes de generar el texto." + +#: src\controller\main_controller.py:116 +msgid "Error: The selected audio language is not valid." +msgstr "Error: El idioma del audio seleccionado no es válido." + +#: src\controller\main_controller.py:120 +#: src\controller\main_controller.py:224 +msgid "Error generating the file transcription. Please try again." +msgstr "Error generando la transcripción. Por favor, inténtelo de nuevo." + +#: src\controller\main_controller.py:254 +msgid "Error: No microphone detected." +msgstr "Error: Micrófono no disponible." + +#: src\controller\main_controller.py:257 +msgid "Error: Listening timed out while waiting for phrase to start." +msgstr "Error: No se ha detectado audio disponible para transcribir." + +#: src\controller\main_controller.py:262 +msgid "Sorry, I cannot clarify what you are saying. Please try again." +msgstr "Lo siento, no puedo entender lo que está diciendo. Por favor, inténtelo de nuevo." + +#: src\controller\main_controller.py:267 +msgid "Unexpected error. Please try again." +msgstr "Error inesperado. Por favor, inténtelo de nuevo." + +#: src\controller\main_controller.py:280 +msgid "Save as" +msgstr "Guardar como" + +#: src\controller\main_controller.py:282 +msgid "Text file" +msgstr "Archivo de texto" + +#: src\controller\main_controller.py:282 +msgid "All Files" +msgstr "Todos los archivos" diff --git a/res/locales/es/LC_MESSAGES/main_controller.po b/res/locales/es/LC_MESSAGES/main_controller.po new file mode 100644 index 0000000..69b7baa --- /dev/null +++ b/res/locales/es/LC_MESSAGES/main_controller.po @@ -0,0 +1,69 @@ +# Copyright (C) 2023 HenestrosaConH +# This file is distributed under the same license as the PACKAGE package. +# José Carlos López Henestrosa , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.3.0\n" +"Report-Msgid-Bugs-To: José Carlos López Henestrosa \n" +"POT-Creation-Date: 2023-02-08 18:22+0100\n" +"PO-Revision-Date: 2023-02-08 18:22+0100\n" +"Last-Translator: José Carlos López Henestrosa \n" +"Language-Team: José Carlos López Henestrosa \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +#: src\controller\main_controller.py:35 +msgid "Select a file" +msgstr "Seleccionar archivo" + +#: src\controller\main_controller.py:37 +msgid "Audio files" +msgstr "Archivos de audio" + +#: src\controller\main_controller.py:38 +msgid "Video files" +msgstr "Archivos de vídeo" + +#: src\controller\main_controller.py:93 +msgid "Error: No audio file selected, please select one before generating text." +msgstr "Error: No se ha seleccionado un archivo de audio. Por favor, seleccione uno antes de generar el texto." + +#: src\controller\main_controller.py:116 +msgid "Error: The selected audio language is not valid." +msgstr "Error: El idioma del audio seleccionado no es válido." + +#: src\controller\main_controller.py:120 +#: src\controller\main_controller.py:224 +msgid "Error generating the file transcription. Please try again." +msgstr "Error generando la transcripción. Por favor, inténtelo de nuevo." + +#: src\controller\main_controller.py:254 +msgid "Error: No microphone detected." +msgstr "Error: Micrófono no disponible." + +#: src\controller\main_controller.py:257 +msgid "Error: Listening timed out while waiting for phrase to start." +msgstr "Error: No se ha detectado audio disponible para transcribir." + +#: src\controller\main_controller.py:262 +msgid "Sorry, I cannot clarify what you are saying. Please try again." +msgstr "Lo siento, no puedo entender lo que está diciendo. Por favor, inténtelo de nuevo." + +#: src\controller\main_controller.py:267 +msgid "Unexpected error. Please try again." +msgstr "Error inesperado. Por favor, inténtelo de nuevo." + +#: src\controller\main_controller.py:280 +msgid "Save as" +msgstr "Guardar como" + +#: src\controller\main_controller.py:282 +msgid "Text file" +msgstr "Archivo de texto" + +#: src\controller\main_controller.py:282 +msgid "All Files" +msgstr "Todos los archivos" diff --git a/res/locales/es/LC_MESSAGES/main_window.po b/res/locales/es/LC_MESSAGES/main_window.po new file mode 100644 index 0000000000000000000000000000000000000000..bb1ab0017c3b4f6d595fff743a4b9ebc98779c5f GIT binary patch literal 3550 zcmds(TW`}q5QXO%iT_}=FCcK}g|?ww1eB^=615_TCnOXcCm0&Xa?_UZk9qDp@SWYb zPFnY&Nkk zn9s2|vbM8KnYnGZOrAbqoiGzvm;Xan2jlmS`6U+fqkv2~a|#%G7;oaZ6dvXJM# zdpcxw#8b+cX4=kovF^ZLfZ!eXJ=?cXr2CiUB-L$9jf>D)<;QW#d( zd!9$GOU125e{g@mh*(cp^O*67Zd7MWC5HCY=}VXW>QjAj*>jP>E_ONVck!n_mRgBP z?O8{!61+~!qY(f9Pg}wg%dftJ<1vO!)DtsXdPH6fvV}jqQ{t zuPdp2=1o{SpgJ9U+O|z9e|Bs2)WZq=DKx3Y-qLJoPO0G4N>#3nz^9D0u~80`i-br9 zV?CN3=cYZHGs=yMD9gT$K&#V8Crg)S>36`TGe>V3ktnkG3bnrMDZwrvSK_hsbcT2N znV*p@s3r=DUS{>eP+lxVk1<@K>z(KX|O_ z^afG-FZ5~_c3cNZyB1OTH(g0v6-uFR!<=vY>iGAmfr!(8F$}EpZ9QKtuU16RB7zgA U7uQ#5ec9z`jP6w`KdsV#0T5wQ6951J literal 0 HcmV?d00001 diff --git a/src/app.py b/src/app.py new file mode 100644 index 0000000..78522cf --- /dev/null +++ b/src/app.py @@ -0,0 +1,71 @@ +import customtkinter as ctk +import torch +import utils.config_manager as cm +import utils.constants as c +import utils.path_helper as ph +from controller.main_controller import MainController +from model.config.config_whisperx import ConfigWhisperX +from model.transcription import Transcription +from utils.enums import ComputeType +from view.main_window import MainWindow + + +class App(ctk.CTk): + def __init__(self): + super().__init__() + + # Modes: "System" (standard), "Dark", "Light" + ctk.set_appearance_mode("System") + # Themes: "blue" (standard), "green", "dark-blue" + ctk.set_default_color_theme("blue") + + self.title(c.APP_NAME) + self.wm_iconbitmap(ph.ROOT_PATH / ph.IMG_RELATIVE_PATH / "icon.ico") + + # Initial size of the window + width = 1000 + height = 760 + self.geometry(f"{width}x{height}") + + # Min size of the window + min_width = 500 + min_height = 250 + self.minsize(min_width, min_height) + + # Check GPU + cm.ConfigManager.modify_value( + section=ConfigWhisperX.Key.SECTION, + key=ConfigWhisperX.Key.CAN_USE_GPU, + new_value=str(torch.cuda.is_available()), + ) + + if not torch.cuda.is_available(): + cm.ConfigManager.modify_value( + section=ConfigWhisperX.Key.SECTION, + key=ConfigWhisperX.Key.COMPUTE_TYPE, + new_value=ComputeType.INT8.value, + ) + + # Initialize configs + config_whisperx = cm.ConfigManager.get_config_whisperx() + config_google_api = cm.ConfigManager.get_config_google_api() + config_subtitles = cm.ConfigManager.get_config_subtitles() + + # Create the view and place it on the root window + view = MainWindow(self, config_whisperx, config_google_api, config_subtitles) + view.pack(fill="both", expand=True) + + # Create the model for the controller + transcription = Transcription() + + # Create the controller + controller = MainController(transcription, view) + + # Set the controller to view + view.set_controller(controller) + + +if __name__ == "__main__": + app = App() + app.eval("tk::PlaceWindow . center") + app.mainloop() diff --git a/src/controller/__init__.py b/src/controller/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/__pycache__/__init__.cpython-313.pyc b/src/controller/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c016ce6b3b3d7f54f2914a2f69642c880a6471f GIT binary patch literal 150 zcmey&%ge<81Qsy`86f&Gh=2h`DC08=kTI1Zok5e)ZzV$!6Oi{ABz4Qw*D5AAIW?y| zF*7eFq$n}3IJqb@DOES1C_kpSC^;rMKd+=HKPM-(C?-BWGcU6wK3=b&@)n0pZhlH> ZPO4oIE6@~>EyWj0{{Gugg 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 T3UYRRVLoQkb>8L3XD$A3?(z>z literal 0 HcmV?d00001 diff --git a/src/controller/main_controller.py b/src/controller/main_controller.py new file mode 100644 index 0000000..934ebd6 --- /dev/null +++ b/src/controller/main_controller.py @@ -0,0 +1,354 @@ +import asyncio +import os +import shutil +import threading +import traceback +from pathlib import Path +from tkinter import filedialog + +import speech_recognition as sr +import utils.audio_utils as au +import utils.config_manager as cm +import whisperx +from model.transcription import Transcription +from moviepy.video.io.VideoFileClip import VideoFileClip +from pydub import AudioSegment +from pydub.silence import split_on_silence +from pytube import YouTube +from pytube.exceptions import RegexMatchError +from utils import constants as c +from utils.enums import AudioSource, TranscriptionMethod +from utils.i18n import _ +from utils.path_helper import ROOT_PATH + + +class MainController: + def __init__(self, transcription: Transcription, view): + self.view = view + self.transcription = transcription + self._is_mic_recording = False + self._whisperx_result = None + + # PUBLIC METHODS + + def select_file(self): + """ + Prompts a file explorer to determine the audio/video file path to transcribe. + Stores the filepath in the class variable filepath_to_transcribe. + """ + filepath = filedialog.askopenfilename( + initialdir="/", + title=_("Select a file"), + filetypes=[ + ( + _("All supported files"), + c.AUDIO_FILE_EXTENSIONS + c.VIDEO_FILE_EXTENSIONS, + ), + (_("Audio files"), c.AUDIO_FILE_EXTENSIONS), + (_("Video files"), c.VIDEO_FILE_EXTENSIONS), + ], + ) + + if filepath: + self.view.on_select_file_success(filepath) + + def prepare_for_transcription(self, transcription: Transcription): + """ + Prepares the transcription process based on provided parameters. + + :raises: IndexError if the selected language code is not valid. + """ + self.transcription = transcription + + try: + self.view.on_processing_transcription() + + if transcription.source == AudioSource.FILE: + self._prepare_for_file_transcription(transcription.source_file_path) + elif transcription.source == AudioSource.MIC: + self._prepare_for_mic_transcription() + elif transcription.source == AudioSource.YOUTUBE: + self._prepare_for_yt_transcription() + + except Exception as e: + self._handle_exception(e) + + async def handle_transcription_process(self): + try: + # Get transcription + if self.transcription.method == TranscriptionMethod.WHISPERX.value: + await self._transcribe_using_whisperx() + elif self.transcription.method == TranscriptionMethod.GOOGLE_API.value: + await self._transcribe_using_google_api() + + if self.transcription.source in (AudioSource.MIC, AudioSource.YOUTUBE): + self.transcription.source_file_path.unlink() # Remove tmp file + + except Exception as e: + self._handle_exception(e) + + finally: + is_transcription_empty = not self.transcription.text + self.view.on_processed_transcription(success=is_transcription_empty) + + def stop_recording_from_mic(self): + self._is_mic_recording = False + + def save_transcription(self): + """ + Prompts a file explorer to determine the file to save the + generated transcription. + """ + file_path = Path(self.transcription.source_file_path) + + file = filedialog.asksaveasfile( + mode="w", + initialdir=file_path.parent, + initialfile=f"{file_path.stem}.txt", + title=_("Save as"), + defaultextension=".txt", + filetypes=[(_("Text file"), "*.txt"), (_("All Files"), "*.*")], + ) + + if file: + file.write(self.transcription.text) + file.close() + + if self.transcription.should_subtitle: + self._generate_subtitles(Path(file.name)) + + # PRIVATE METHODS + + def _prepare_for_file_transcription(self, source_file_path: str): + if self._is_file_valid(source_file_path): + self.transcription.source_file_path = Path(source_file_path) + + threading.Thread( + target=lambda loop: loop.run_until_complete( + self.handle_transcription_process() + ), + args=(asyncio.new_event_loop(),), + ).start() + else: + raise ValueError("Error: No valid file selected.") + + def _prepare_for_mic_transcription(self): + threading.Thread(target=self._record_from_mic).start() + + def _prepare_for_yt_transcription(self): + threading.Thread(target=self._download_audio_from_yt_video).start() + + def _handle_exception(self, e: Exception): + print(traceback.format_exc()) + self.view.on_processed_transcription(success=False) + self.view.display_text(repr(e)) + + @staticmethod + def _is_file_valid(source_file_path: str): + filepath = Path(source_file_path) + is_audio = filepath.suffix in c.AUDIO_FILE_EXTENSIONS + is_video = filepath.suffix in c.VIDEO_FILE_EXTENSIONS + + return filepath.is_file() and (is_audio or is_video) + + async def _transcribe_using_whisperx(self): + config_whisperx = cm.ConfigManager.get_config_whisperx() + + device = "cpu" if config_whisperx.use_cpu else "cuda" + task = "translate" if self.transcription.should_translate else "transcribe" + + try: + model = whisperx.load_model( + config_whisperx.model_size, + device, + compute_type=config_whisperx.compute_type, + task=task, + language=self.transcription.language_code, + ) + + audio_path = str(self.transcription.source_file_path) + audio = whisperx.load_audio(audio_path) + self._whisperx_result = model.transcribe( + audio, batch_size=config_whisperx.batch_size + ) + + text_combined = " ".join( + segment["text"].strip() for segment in self._whisperx_result["segments"] + ) + + # Align output if should subtitle + if self.transcription.should_subtitle: + model_aligned, metadata = whisperx.load_align_model( + language_code=self.transcription.language_code, device=device + ) + self._whisperx_result = whisperx.align( + self._whisperx_result["segments"], + model_aligned, + metadata, + audio, + device, + return_char_alignments=False, + ) + + self.transcription.text = text_combined + self.view.display_text(self.transcription.text) + + except Exception as e: + self._handle_exception(e) + + async def _transcribe_using_google_api(self): + """ + Splits a large audio file into chunks + and applies speech recognition on each one. + """ + file_path = self.transcription.source_file_path + + # Can be the transcription or an error text + transcription_text = "" + + # Create a directory to store the audio chunks + chunks_directory = ROOT_PATH / "audio-chunks" + chunks_directory.mkdir(exist_ok=True) + + try: + # Get file extension + content_type = Path(file_path).suffix + + sound = None + # Open the audio file using pydub + if content_type in c.AUDIO_FILE_EXTENSIONS: + sound = AudioSegment.from_file(file_path) + + elif content_type in c.VIDEO_FILE_EXTENSIONS: + clip = VideoFileClip(str(file_path)) + video_audio_path = chunks_directory / f"{Path(file_path).stem}.wav" + clip.audio.write_audiofile(video_audio_path) + sound = AudioSegment.from_wav(video_audio_path) + + audio_chunks = split_on_silence( + sound, + # Minimum duration of silence required to consider a segment as a split point + min_silence_len=500, + # Audio with a level -X decibels below the original audio level will be considered as silence + silence_thresh=sound.dBFS - 40, + # Adds a buffer of silence before and after each split point + keep_silence=100, + ) + + # Create a speech recognition object + r = sr.Recognizer() + + # Get Google API key (if any) + config_google_api = cm.ConfigManager.get_config_google_api() + api_key = config_google_api.api_key or None + + # Process each chunk + for idx, audio_chunk in enumerate(audio_chunks): + # Export audio chunk and save it in the `chunks_directory` directory. + chunk_filename = os.path.join(chunks_directory, f"chunk{idx}.wav") + audio_chunk.export(chunk_filename, bitrate="192k", format="wav") + + # Recognize the chunk + with sr.AudioFile(chunk_filename) as source: + r.adjust_for_ambient_noise(source) + audio_listened = r.record(source) + + try: + # Try converting it to text + chunk_text = r.recognize_google( + audio_listened, + language=self.transcription.language_code, + key=api_key, + ) + + chunk_text = f"{chunk_text.capitalize()}. " + transcription_text += chunk_text + print(f"chunk text: {chunk_text}") + + except Exception: + continue + + self.transcription.text = transcription_text + + except Exception: + self.view.display_text(traceback.format_exc()) + + finally: + # Delete temporal directory and files + shutil.rmtree(chunks_directory) + + if self.transcription.text: + self.view.display_text(self.transcription.text) + + def _record_from_mic(self): + self._is_mic_recording = True + audio_data = [] + + try: + r = sr.Recognizer() + + with sr.Microphone() as mic: + while self._is_mic_recording: + audio_chunk = r.listen(mic, timeout=5) + audio_data.append(audio_chunk) + + if audio_data: + filename = "mic-output.wav" + au.save_audio_data(audio_data, filename=filename) + self.transcription.source_file_path = Path(filename) + + threading.Thread( + target=lambda loop: loop.run_until_complete( + self.handle_transcription_process() + ), + args=(asyncio.new_event_loop(),), + ).start() + else: + e = ValueError("No audio detected") + self._handle_exception(e) + + except Exception as e: + self.view.stop_recording_from_mic() + self._handle_exception(e) + + def _generate_subtitles(self, file_path): + config_subtitles = cm.ConfigManager.get_config_subtitles() + + output_formats = ["srt", "vtt"] + output_dir = file_path.parent + + for output_format in output_formats: + writer = whisperx.transcribe.get_writer(output_format, output_dir) + writer_args = { + "highlight_words": config_subtitles.highlight_words, + "max_line_count": config_subtitles.max_line_count, + "max_line_width": config_subtitles.max_line_width, + } + + # https://github.com/m-bain/whisperX/issues/455#issuecomment-1707547704 + self._whisperx_result["language"] = "en" + + writer(self._whisperx_result, file_path, writer_args) + + def _download_audio_from_yt_video(self): + try: + yt = YouTube(self.transcription.youtube_url) + stream = yt.streams.filter(only_audio=True).first() + output_file = stream.download(output_path=".", filename="yt-audio.mp3") + + if output_file: + self.transcription.source_file_path = Path(output_file) + + threading.Thread( + target=lambda loop: loop.run_until_complete( + self.handle_transcription_process() + ), + args=(asyncio.new_event_loop(),), + ).start() + + except RegexMatchError: + e = ValueError("The URL is not correct.") + self._handle_exception(e) + + except Exception as e: + self._handle_exception(e) diff --git a/src/model/__init__.py b/src/model/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/model/__pycache__/__init__.cpython-313.pyc b/src/model/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c7ae754a1f10c751a1525f8f20e8405db5201e3 GIT binary patch literal 145 zcmey&%ge<81Qsy`86f&Gh=2h`DC08=kTI1Zok5e)ZzV$!6Oi{ABz4Qc*D5AAIW?y| zF*7eFq$n}3IJqb@DOES1C_kpSC^;rKKP5FMCO$qhFS8^*Uaz3?7KaT`tTZRpu80+A T0LX%35aS~=BO_xGGmr%Uw8SCV literal 0 HcmV?d00001 diff --git a/src/model/config/__init__.py b/src/model/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/model/config/__pycache__/__init__.cpython-313.pyc b/src/model/config/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a3b630e8851fa1a6cd951dcbabe1ff565ae75f3 GIT binary patch literal 152 zcmey&%ge<81Qsy`86f&Gh=2h`DC08=kTI1Zok5e)ZzV$!6Oi{ABz4Q&*D5AAIW?y| zF*7eFq$n}3IJqb@DOES1C_kpSC^;rKKP5FMCOJPZEi*kPK0Y%qvm`!Vub}c4hYe7w aG$+-rh!toK$ev;l<0CU8BV!RWkOctb@g%YU literal 0 HcmV?d00001 diff --git a/src/model/config/__pycache__/config_google_api.cpython-313.pyc b/src/model/config/__pycache__/config_google_api.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2fc28840c8bbab457ee19c20cd9325dc9a3388a GIT binary patch literal 1287 zcmZux&2Q6K5P$x5+;k~~B4}aPP(G9cZ6)X)RtPPWf@n%Wm>!TUJsIaE7#ur{9Z)$T zAwjQusCJKVga3xr9zaj3w9=k>3(88pGGiw|fp_@LjOV?X-^`om;pC*la9v)w*j`f^ z`;UzAGDgbqDk@vdW1iArs|qMC>1sn=)j%tBt)Z_PV7Saz4zm-?(`T4xEMYuaOQm37 zcFel9Lsngpl~#}kVH{)`8v07o@1nGC_VOrAf;b$VDa2(#il}c?Q^&SMFO*lXld(mZqIpTh;rQhpKgp+TC^v zE~d|1Y(yGHK`vVElPJIM=J$nLa&<4=y6%Pr`91{HpLs_*ouUqo^r1q9m>}{#B%y-F zcBHJ)U3?ddt^n#c=okAt``+FoCGT+;fPC<}UaQX8O?qdFn{{ZI9>Il!+ zz+wBR|E&H|{Ywlq_2^HVYXh4dbl=zJ{;tivy7K1aKedH-)rBGT=q+p3C#21J5_ARU z(%~Fw^<&bjoImOZ@yN4}^L7MT9!H5tQgmCKx6+UlZ)N$;^_xxDj{$*338n}RA;@XY zvm7rxLrHagJzie6`4$N*^1KqAH zzOvucUQg~aRLk?nadQ!_S+Bqh8M6dO362pE7m4hHBuR-$nh*gRD=5yor0wMc7JVb2 z_m$NUUb25Dr=G9dbHOl}1 literal 0 HcmV?d00001 diff --git a/src/model/config/__pycache__/config_subtitles.cpython-313.pyc b/src/model/config/__pycache__/config_subtitles.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9b9515858a685a749384870527214937d215096 GIT binary patch literal 1516 zcmZuxOHUj}5bk;GljRXFgn$z=HYCv~@tR0MiXtnK1H`<%STx8vjMN%thuukLXErsx zA^4P2!XMyHZqC06;s9z1DN;_{)>=zkQ#HGgC3Z{u^;ccf)n8RtZ+CdO$Z&k=v>FwI zv46<89+^Jreuw0UamKZEwx)q*5!cuCH3N*48|&s;1~L|NwD;J3#?5KQGYfie|3W_u zWb0WwcS)A5sY1<_t{1vVf`+*qwVOESH(N4@BRBN=d(!Df#~PYP%weE$20GWk_=q{C zli~U&=y9^hj2mVWOVwmhP1eaRV16_p&vQ_y=k0pw8R7GLWI4TxQX)MjJuB z5#mpZ{TOPA8fm(}h%ktJ;l=Gp4%quaO*U?c?H|Irk1*72v0Mj}8<629WO)X1JWEoX zf>WdnztDMpn*CtH5HCQfUbKf)`G4{%>;A!I3BP^uZILQwrS-G+Vz7Sn4-yND8GC^% z{hGBO$c7~wzLi|(W_f9@ZE&f?m7*%#xS)VBff@mZ5L6a?*@no|(6}B{8Op5-2uEy( zZC!f?X0G9S|JnzZu~~5499-#fuFo5hwxez3-t_G-Zd|v}9J9?ApFiPfbf9RutyU1#6H3yu)HhGRa+;nW?z=(cY=avm9t6AogJ%#s z33yI3uKA(Ut9*YFH)XH14pcEsMo?@u^Oozb{O5lck4zpT{K`66_RhrF*xbq3-0|M| z*!bDl?8(^d@y-D4<#B3&A=U5k4ftBDhCzpWqIH!i?M~ib+!(k(4sI zs6inO@G-I5@_<@21$qgIh44H3dt&O;oH`$$JT)hK_}aXanLn&uF`RmeXkXRNsiB)c zJU;WP~pSK`t`-`lk*(9YpEzxU?r_ujmjekP+3Xpa_F zYJW?F{E5b}#RjDRF_2@T6J6LK>jD!rU|J2+_rZ|MZo3J6a;p_Mo@+L&!J4qU((xsj$HX8^&)eHY0Gpe8ueED zMks^hNPi7>y%~xwGFg`x2xoCU#u9p*CG`XdOEN`I8EHesJbWPP$^`jJW*I%rM(S!Y z!^dt4p5L$!FGgVM(W-)J)xsoeHIHdu+lRge8TTy54D3DazzO!XVBgk;!D?0*dz+bf z4f6_59z<#Qj-_BnhPA@d2r5DbfXA5~w3%xOU<@11!%+Lb0vwYnc|IJu*6RZJ2Q_ld z4V49c`MM|K;e5P}TTPc>e)5(ROkG-xxk6QVj)HHsD%9w(K4(cWcJxGfYzJX3zBL3uLmbNyxt2<@7^Z9m}C#rgxmbR-rU0SVBG#-N?)$O1ta@n^VHLl`0v}v|lj$8LJ zcbdjmHkXa2Wj78?$2E4C>G~FPcJ24KnP>RSGQ!d|qMIFbba<`vtwXMa5l0n#|G%{~ z|L^bw9O!=n@IC3}$Y|lG?91#)p_?1OB4@d&)7;d_68hAa>d!SGXF2UOr=2|LrQ>gp zbe_S=aqTQWbDEzyS$j46I=}F{y3oh_`HfVHS)QcSHJdi2T%i=Sw;RY+O228FjloEk z(wf8kpy9Z->%nk>(ml^YqL)iMPq!-UE^Nr|A-siv(%B>ez9Ke`paJj#rG5bAZc#G` zAaC%PeM;F3PMAh`2WLre;VcUbAC~_izz^h&D5lh2lH~7q65Ya7M~UF>Tu1GWO@i;v zOefuwv#G_C;WeM~l;A`=V06&sHa`_iq-4MnKujN8FGx}n)JBsu#c`~-x*}EjrMfz}U zrI_I9t54eY89rz(+wi4?$MZN8Ba~s3(D2BcGI;W%==xUJA}q!K!G8$QlLSFHCsXI7 aa84$BaU!NK#c5%&M*#W~m~YSwmHY!ZRF-=H literal 0 HcmV?d00001 diff --git a/src/model/config/config_google_api.py b/src/model/config/config_google_api.py new file mode 100644 index 0000000..326a30a --- /dev/null +++ b/src/model/config/config_google_api.py @@ -0,0 +1,26 @@ +from dataclasses import dataclass +from enum import Enum +from typing import Optional + + +@dataclass +class ConfigGoogleApi: + api_key: str + + class Key(Enum): + """ + Enum class for keys associated with the Google API configuration. + """ + + SECTION = "google_api" + API_KEY = "api_key" + + def value_type(self) -> Optional[str]: + """ + Get the value type associated with the ConfigKey. + """ + type_mapping = { + self.API_KEY: "str", + } + + return type_mapping.get(self, None) diff --git a/src/model/config/config_subtitles.py b/src/model/config/config_subtitles.py new file mode 100644 index 0000000..88af1c9 --- /dev/null +++ b/src/model/config/config_subtitles.py @@ -0,0 +1,30 @@ +from dataclasses import dataclass +from enum import Enum +from typing import Optional + + +@dataclass +class ConfigSubtitles: + highlight_words: bool + max_line_count: int + max_line_width: int + + class Key(Enum): + """ + Enum class for keys associated with the subtitles configuration. + """ + + SECTION = "subtitles" + HIGHLIGHT_WORDS = "highlight_words" + MAX_LINE_COUNT = "max_line_count" + MAX_LINE_WIDTH = "max_line_width" + + def value_type(self) -> Optional[str]: + """Get the value type associated with the ConfigKey.""" + type_mapping = { + self.HIGHLIGHT_WORDS: "bool", + self.MAX_LINE_COUNT: "int", + self.MAX_LINE_WIDTH: "int", + } + + return type_mapping.get(self, None) diff --git a/src/model/config/config_whisperx.py b/src/model/config/config_whisperx.py new file mode 100644 index 0000000..5cf1261 --- /dev/null +++ b/src/model/config/config_whisperx.py @@ -0,0 +1,41 @@ +from dataclasses import dataclass +from enum import Enum +from typing import Optional + + +@dataclass +class ConfigWhisperX: + model_size: str + batch_size: int + compute_type: str + use_cpu: bool + can_use_gpu: bool + + class Key(Enum): + """ + Enum class for keys associated with the WhisperX configuration. + """ + + SECTION = "whisperx" + MODEL_SIZE = "model_size" + BATCH_SIZE = "batch_size" + COMPUTE_TYPE = "compute_type" + USE_CPU = "use_cpu" + CAN_USE_GPU = "can_use_gpu" + + def value_type(self) -> Optional[str]: + """ + Get the value type associated with the ConfigKey. + + :return + :rtype: str + """ + type_mapping = { + self.MODEL_SIZE: "str", + self.BATCH_SIZE: "int", + self.COMPUTE_TYPE: "str", + self.USE_CPU: "bool", + self.CAN_USE_GPU: "bool", + } + + return type_mapping.get(self, None) diff --git a/src/model/transcription.py b/src/model/transcription.py new file mode 100644 index 0000000..16eb493 --- /dev/null +++ b/src/model/transcription.py @@ -0,0 +1,17 @@ +from dataclasses import dataclass +from pathlib import Path +from typing import Optional + +from utils.enums import AudioSource + + +@dataclass +class Transcription: + text: Optional[str] = None + language_code: Optional[str] = None + source: Optional[AudioSource] = None + source_file_path: Optional[Path | str] = Path("/") + method: Optional[int] = None + should_translate: bool = False + should_subtitle: bool = False + youtube_url: str = None diff --git a/src/utils/__init__.py b/src/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/__pycache__/__init__.cpython-313.pyc b/src/utils/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2cc43134466b5af469eb0e84ce08b8d2edf4f9ee GIT binary patch literal 145 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 CIb0Y3 literal 0 HcmV?d00001 diff --git a/src/utils/__pycache__/constants.cpython-313.pyc b/src/utils/__pycache__/constants.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b85a42b60ae19eb17f6d834db2a3c8bda305575 GIT binary patch literal 3012 zcmZ9NX>$`t8poxvb%J9PVh9j|Ljsm;V=gBlgb-v~KJW>T4TLyR+R{iGYYx#fV}Ww9 zN3!gFW@|sf?!Mcq{Ra60CF&jtqa3H+{X zwVVIUCKCTq^1~0Vf6xAvOeDTZP=Y5YNfz}@T0D6nLH(4fBq>c9FiSZwPY1w*GyuLp zgWwPy0$-%V;7c?N9-*V)%XADpPA9-u=p^_modQSbHSjdO4!%KWDr%myl!T2^0W8uO zI8GDbIhq8|(*^J%T>>xD6!<2+1-?yJz<1~>_%2-o-=pi``*Z^=(KI+ivtXI#D#@~% zX`U9~i*yrQqGfP}R>3t|2XE1BkZ1$kq&whUx(9wh_rVWo3;c*a1}pRl$Y>j^QVq1J z4mPOSo5`Uac#B-nBOeT?4L%?ah7^G@?SdV82tJ}N_$hq`eokM2U(#dnNAzRxC-hVB zEBYGz89f1iPQOqy(J$#&^lSPJ{g!@5zn@H(liWI=pg-J7@;*HOh-ZJ}PsMLUt`ygt zAhI7uB2)Got`jz6b^hhB&A$Cd;1(@m**^Y4VX-=z*SXVT%vb7(Ov!69?o=UMq)VJ_ zt8(*^$duCB0bH*2eB=zZCm80ZI|&l)NQwYk(svr26G(* z8zMIyyA4dB`c;|8%&>^LO1jPN;7rr;?a&@6r~)gBRJU1KSn3{rUcV6djgck5#5V4B zhn~kanA2f?5sT#_JHrDOnMp#Cn(5lrrm$*Eq-U9rgb2%bMQS#Vs!iUH++Yup$d zFgvU>k(y&XbVOg>aYc5{ah znk~}vHutd4RL!o;EOd_=9Vt-93BwVJm|tVOhSl3x*gUuG7KV&5NW8;1wjwO2Bhm}@ zHn%(2q9alZj$cD{GZwjp7zs8xbwZI_tl|I=#KAc=kze#{0n(~h;^0y&BI8O@PNbGH zV3zPht+j)t-(+p3PC{5ayUKQZ*1~BnG2drMrPXSQ^b+f`7IxqAL~5z&*&M|H)d9EF zp}K+STV_a`yDKuwEZWtJa3hglcA{pCvrw%(9MKAH!6Ou1k<&$}2gP!skzR_&l^_|| zz2*66h>H;Dtyn%XylS`gEyFS8Rs-I#P4a!ed+522tUmGs9wNDISESd`TU~~B6svFN zdcdQ&5r6x4yb5jH&Gp#d!TlE&4@CBMfaBB4<*~@zjzg2s5Q`$b3Oa)Ok|D=$V)4Sl zBx!PkU53d*Y)h5(3&d0E#$^a8*0YB=L5gwyCgWiTu?}nE%Aq6jMjgAR8%DU58_dIn zv?A# z!H%Z~3+t=J6uwsL>y_2gN?8o3(sF5aezP=RCNWsroLyY|pNe5qF}Ju}u9WX>lvinS zZI#6EoyFPmTIK($|CV@$vrCAJD_6HXyk#9^dTWE@<5}g-wta4$2U{VpZpD$~hFjIZ z5AkA0;ba@%&ud;#i(UIV{|iRIzu`of#ivL1C6md$14kZb_l}PIHUHhv<;Mduy_7s` z?e%A$jLSY%{5Oh4nNmfWPNZ^A3NoW5t7J^(wB(gc$OBpqnq~u9UNDhCEkjC*@{pDn zm5j^7T3#}dVJ$}>PxB|_QEe|LQU{+7oR-J59oKeBp3wG+>NX}%YI#-3s63@*L`gxu zrscGbeE+(ZHH;*wTvZF`6pN9xRwdi=bV;FB?Wn2%LOyQMJ<<% zT-GvWn!TyzExqis@@;KbRA^MbqvfjU^sbg`rqg>`uA64>Yq^nBHZDs^tVt zV!v#3PHR!l8(n}Nd{U8%MsMoqm|QZt+|w1KtG&K!M%T3#@P^MrV6kHae$uRL&b+&|3I@(dbPpap2Hi{_tLYcrQP+ jmp=mTZ|d0N!TtMI{+RVNF}!~~cg*@OG0gvrFT#HT{ROQ& literal 0 HcmV?d00001 diff --git a/src/utils/__pycache__/path_helper.cpython-313.pyc b/src/utils/__pycache__/path_helper.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bfed99a549d00214023e8db15a53b10d78a8de5 GIT binary patch literal 1058 zcma)5&ubGw6n>Lzer+3Vaa*d?c9dG#L(@Vl4WSBAL#_Q4vO$F|giSh0wrqBn*^L@c z>Z#&Ikb;8HYyB_uKWOk!SQQk#c#A|qJUO%Js`cc9eKYgsz3=bQ=ELmkzG7|%#$e<3 z?gkUwvjWfh#{y~--5Qwc1DJp_un`TC=1>f@SpfVuUOdDBjd5(`!)%YLkjy)yXCY#9 zTFouxvx?#+a(64l=7(Ux66YwDyeR7gFp?aB2<*B7Qw4yd$-EdUi=2D#)HlZoI<;82n^-<_?hQg7Zo6OyZjwD3VpQVu( zCw51lkG_#6w-cQ>^bfWBCiaDiAKzk-9Nu2&0*a*Hv8<7&YX_3tmgECzrY+4JNb_xJ z{!!vXpVTYp#8~1_hm$-!IS#w&?CJ39QN;Yc7$wfM-l)m!pJCf_jPe)g#kf*KF9#iR zsV~tRTv}Z$6>=-t;?j*=DW5G~^Ad&i^`bw030+nT^cY8oFEp&pra>;zVYcKyj5Ez# uCyWq!3*vhi`5GNS=bl~Z02}tC?|kS?!qC`041VmFo)jLhJV?+XR`Uybj|1`m literal 0 HcmV?d00001 diff --git a/src/utils/audio_utils.py b/src/utils/audio_utils.py new file mode 100644 index 0000000..1c43107 --- /dev/null +++ b/src/utils/audio_utils.py @@ -0,0 +1,26 @@ +import speech_recognition as sr +from pydub import AudioSegment + + +def save_audio_data(audio_data, filename): + if audio_data: + raw_audio_data = b"".join( + [ + chunk.get_raw_data(convert_rate=None, convert_width=None) + for chunk in audio_data + ] + ) + audio = AudioSegment( + raw_audio_data, + sample_width=audio_data[0].sample_width, + frame_rate=audio_data[0].sample_rate, + channels=1, + ) + + try: + audio.export(filename, format="wav") + print(f"Audio data saved to {filename}") + except sr.UnknownValueError: + print("Could not save audio data. Unknown value error.") + except sr.RequestError as e: + print(f"Could not request results; {e}") diff --git a/src/utils/config_manager.py b/src/utils/config_manager.py new file mode 100644 index 0000000..01ee401 --- /dev/null +++ b/src/utils/config_manager.py @@ -0,0 +1,110 @@ +from configparser import ConfigParser +from pathlib import Path +from typing import Optional, Union + +from model.config.config_google_api import ConfigGoogleApi +from model.config.config_subtitles import ConfigSubtitles +from model.config.config_whisperx import ConfigWhisperX +from utils.path_helper import ROOT_PATH + + +class ConfigManager: + _FILE_PATH = ROOT_PATH / "config.ini" + KeyType = Union[ConfigWhisperX.Key, ConfigGoogleApi.Key, ConfigSubtitles.Key] + + @staticmethod + def read_config(file_path: Path = _FILE_PATH) -> Optional[ConfigParser]: + config = ConfigParser() + config.read(file_path) + return config + + @staticmethod + def get_config_whisperx() -> ConfigWhisperX: + section = ConfigWhisperX.Key.SECTION + + return ConfigWhisperX( + model_size=ConfigManager.get_value(section, ConfigWhisperX.Key.MODEL_SIZE), + batch_size=ConfigManager.get_value(section, ConfigWhisperX.Key.BATCH_SIZE), + compute_type=ConfigManager.get_value( + section, ConfigWhisperX.Key.COMPUTE_TYPE + ), + use_cpu=ConfigManager.get_value(section, ConfigWhisperX.Key.USE_CPU), + can_use_gpu=ConfigManager.get_value( + section, ConfigWhisperX.Key.CAN_USE_GPU + ), + ) + + @staticmethod + def get_config_google_api() -> ConfigGoogleApi: + section = ConfigGoogleApi.Key.SECTION + + return ConfigGoogleApi( + api_key=ConfigManager.get_value(section, ConfigGoogleApi.Key.API_KEY), + ) + + @staticmethod + def get_config_subtitles() -> ConfigSubtitles: + section = ConfigSubtitles.Key.SECTION + + return ConfigSubtitles( + highlight_words=ConfigManager.get_value( + section, ConfigSubtitles.Key.HIGHLIGHT_WORDS + ), + max_line_count=ConfigManager.get_value( + section, ConfigSubtitles.Key.MAX_LINE_COUNT + ), + max_line_width=ConfigManager.get_value( + section, ConfigSubtitles.Key.MAX_LINE_WIDTH + ), + ) + + @staticmethod + def get_value( + section: KeyType, + key: KeyType, + file_path: Path = _FILE_PATH, + ) -> Optional[Union[str, bool, int, float]]: + config = ConfigManager.read_config(file_path) + + section_name = section.value + key_name = key.value + key_value_type = key.value_type() + + # Check if the section and key exist before getting the value + if section_name in config and key_name in config[section_name]: + if key_value_type == "str": + return config.get(section_name, key_name) + elif key_value_type == "bool": + return config.getboolean(section_name, key_name) + elif key_value_type == "int": + return config.getint(section_name, key_name) + elif key_value_type == "float": + return config.getfloat(section_name, key_name) + else: + print( + f"Section [{section_name}] or Key [{key_name}] not found in the config" + ) + return None + + @staticmethod + def modify_value( + section: KeyType, + key: KeyType, + new_value: str, + file_path: Path = _FILE_PATH, + ): + config = ConfigManager.read_config(file_path) + + section_name = section.value + key_name = key.value + + # Check if the section and option exist before modifying + if section_name in config and key_name in config[section_name]: + config.set(section_name, key_name, new_value) + + with open(file_path, "w") as config_file: + config.write(config_file) + + print(f"Value for [{section}][{key_name}] modified to {new_value}") + else: + print(f"Section [{section}] or Key [{key_name}] not found in the config") diff --git a/src/utils/constants.py b/src/utils/constants.py new file mode 100644 index 0000000..2d286c0 --- /dev/null +++ b/src/utils/constants.py @@ -0,0 +1,104 @@ +APP_NAME = "Audiotext" +APP_LANGUAGES = {"en": "English", "es": "Español"} + +# Code languages convention: ISO 639-1 +AUDIO_LANGUAGES = { + "af": "Afrikaans", + "am": "Amharic", + "ar": "Arabic", + "hy": "Armenian", + "az": "Azerbaijan", + "eu": "Basque", + "be": "Belarusian", + "bn": "Bengali", + "bg": "Bulgarian", + "ca": "Catalan", + "zh": "Chinese (China)", + "zh_HK": "Chinese (Hong Kong)", + "zh_TW": "Chinese (Taiwan)", + "hr": "Croatian", + "cs": "Czech", + "da": "Danish", + "nl": "Dutch", + "en": "English", + "et": "Estonian", + "fa": "Farsi", + "fil": "Filipino", + "fi": "Finnish", + "fr": "French", + "gl": "Galician", + "ka": "Georgian", + "de": "German", + "de_CH": "German (Swiss Standard)", + "el": "Greek", + "gu": "Gujarati", + "iw": "Hebrew", + "hi": "Hindi", + "hu": "Hungarian", + "is": "Icelandic", + "id": "Indonesian", + "it": "Italian", + "it_CH": "Swiss Italian", + "ja": "Japanese", + "jv": "Javanese", + "kn": "Kannada", + "kk": "Kazakh", + "km": "Khmer", + "ko": "Korean", + "lo": "Lao", + "lv": "Latvian", + "lt": "Lithuanian", + "ms": "Malay", + "ml": "Malayalam", + "mt": "Maltese", + "mr": "Marathi", + "mn": "Mongolian", + "ne": "Nepali", + "no": "Norwegian", + "nn": "Norwegian Nynorsk", + "pl": "Polish", + "pt": "Português", + "pa": "Punjabi", + "ro": "Romanian", + "ru": "Russian", + "sr": "Serbian", + "si": "Sinhala", + "sk": "Slovak", + "sl": "Slovenian", + "es": "Spanish", + "su": "Sundanese", + "sw": "Swahili", + "sv": "Swedish", + "ta": "Tamil", + "te": "Telugu", + "th": "Thai", + "tr": "Turkish", + "uk": "Ukrainian", + "ur": "Urdu", + "vi": "Vietnamese", + "zu": "Zulu", +} + +AUDIO_FILE_EXTENSIONS = [ + ".mp3", + ".mpeg", + ".wav", + ".wma", + ".aac", + ".flac", + ".ogg", + ".oga", + ".opus", +] + +# fmt: off +VIDEO_FILE_EXTENSIONS = [ + ".mp4", ".m4a", ".m4v", ".f4v", ".f4a", ".m4b", ".m4r", ".f4b", ".mov", # MP4 + ".avi", # AVI + ".webm", # WebM + ".flv", # FLV + ".mkv", # MKV + ".3gp", ".3gp2", ".3g2", ".3gpp", ".3gpp2", # 3GP + ".ogv", ".ogx", # OGG + ".wmv", ".asf" # AIFF / ASF +] diff --git a/src/utils/dict_utils.py b/src/utils/dict_utils.py new file mode 100644 index 0000000..e975902 --- /dev/null +++ b/src/utils/dict_utils.py @@ -0,0 +1,5 @@ +def find_key_by_value(dictionary, target_value): + for key, value in dictionary.items(): + if value == target_value: + return key + return None diff --git a/src/utils/enums.py b/src/utils/enums.py new file mode 100644 index 0000000..259c0fc --- /dev/null +++ b/src/utils/enums.py @@ -0,0 +1,40 @@ +from enum import Enum + + +class AudioSource(Enum): + FILE = "File" + MIC = "Microphone" + YOUTUBE = "YouTube" + + +class TranscriptionMethod(Enum): + WHISPERX = 0 + GOOGLE_API = 1 + + +class Color(Enum): + LIGHT_RED = "#D30000" + DARK_RED = "#8b0000" + HOVER_LIGHT_RED = "#BF0000" + HOVER_DARK_RED = "#610000" + + LIGHT_BLUE = "#3B8ED0" + DARK_BLUE = "#1F6AA5" + HOVER_LIGHT_BLUE = "#36719F" + HOVER_DARK_BLUE = "#144870" + + +class ComputeType(Enum): + INT8 = "int8" + FLOAT16 = "float16" + FLOAT32 = "float32" + + +class ModelSize(Enum): + TINY = "tiny" + BASE = "base" + SMALL = "small" + MEDIUM = "medium" + LARGE_V1 = "large-v1" + LARGE_V2 = "large-v2" + LARGE_V3 = "large-v3" diff --git a/src/utils/i18n.py b/src/utils/i18n.py new file mode 100644 index 0000000..28f1de3 --- /dev/null +++ b/src/utils/i18n.py @@ -0,0 +1,44 @@ +import gettext +import locale + +import utils.constants as c +import utils.path_helper as ph + +_ = None + + +def load_translation(language_code: str): + """ + Loads the translation for the provided language code. + + This function uses the gettext library to load the translation file + for the provided language code from the localedir. If the translation + file is not found, the fallback is set to True so that a default language + will be used if available. The function then installs the loaded translation + and sets the global _ variable to the gettext function for later use. + + :param language_code: The code for the language to be used for translation. + :type language_code: str + """ + try: + lang_code_without_territory = language_code.split("_")[0] + if lang_code_without_territory not in c.APP_LANGUAGES: + lang_code_without_territory = "en" + except Exception: + lang_code_without_territory = "en" + locale.setlocale(locale.LC_ALL, "en_US") + + translation = gettext.translation( + "app", + localedir=ph.ROOT_PATH / "res/locales", + languages=[lang_code_without_territory], + fallback=True, + ) + translation.install() + + global _ + _ = translation.gettext + + +load_translation("en") +# load_translation(locale.getdefaultlocale()[0][:2]) diff --git a/src/utils/path_helper.py b/src/utils/path_helper.py new file mode 100644 index 0000000..cadeeca --- /dev/null +++ b/src/utils/path_helper.py @@ -0,0 +1,26 @@ +import sys +from pathlib import Path + + +def get_path(relative_path: str = "") -> Path: + """ + Gets absolute path of the project. + + :param relative_path: The relative path to the application's base path. + Default is an empty string. + :type relative_path: str + :return: The absolute path to the file or directory specified by the relative path. + :rtype: Path + """ + try: + # PyInstaller creates a temp folder and stores path in _MEIPASS + base_path = Path(sys._MEIPASS) + except (Exception,): + base_path = Path(__file__).parent.parent.parent + + return base_path / relative_path + + +IMG_RELATIVE_PATH = "res/img" + +ROOT_PATH = get_path("") diff --git a/src/view/__init__.py b/src/view/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/view/custom_widgets/__init__.py b/src/view/custom_widgets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/view/custom_widgets/ctk_input_dialog.py b/src/view/custom_widgets/ctk_input_dialog.py new file mode 100644 index 0000000..132ed4e --- /dev/null +++ b/src/view/custom_widgets/ctk_input_dialog.py @@ -0,0 +1,168 @@ +from typing import Optional, Tuple, Union + +import customtkinter as ctk +from utils.enums import Color + + +class CTkInputDialog(ctk.CTkToplevel): + """ + Dialog with extra window, message, entry widget, cancel and ok button. + For detailed information check out the documentation. + """ + + def __init__( + self, + fg_color: Optional[Union[str, Tuple[str, str]]] = None, + text_color: Optional[Union[str, Tuple[str, str]]] = None, + button_fg_color: Optional[Union[str, Tuple[str, str]]] = None, + button_hover_color: Optional[Union[str, Tuple[str, str]]] = None, + button_text_color: Optional[Union[str, Tuple[str, str]]] = None, + entry_fg_color: Optional[Union[str, Tuple[str, str]]] = None, + entry_border_color: Optional[Union[str, Tuple[str, str]]] = None, + entry_text_color: Optional[Union[str, Tuple[str, str]]] = None, + title: str = "CTkDialog", + font: Optional[Union[tuple, ctk.CTkFont]] = None, + label_text: str = "CTkDialog", + entry_text: Optional[str] = None, + ): + super().__init__(fg_color=fg_color) + + self._fg_color = ( + ctk.ThemeManager.theme["CTkToplevel"]["fg_color"] + if fg_color is None + else self._check_color_type(fg_color) + ) + self._text_color = ( + ctk.ThemeManager.theme["CTkLabel"]["text_color"] + if text_color is None + else self._check_color_type(button_hover_color) + ) + self._button_fg_color = ( + ctk.ThemeManager.theme["CTkButton"]["fg_color"] + if button_fg_color is None + else self._check_color_type(button_fg_color) + ) + self._button_hover_color = ( + ctk.ThemeManager.theme["CTkButton"]["hover_color"] + if button_hover_color is None + else self._check_color_type(button_hover_color) + ) + self._button_text_color = ( + ctk.ThemeManager.theme["CTkButton"]["text_color"] + if button_text_color is None + else self._check_color_type(button_text_color) + ) + self._entry_fg_color = ( + ctk.ThemeManager.theme["CTkEntry"]["fg_color"] + if entry_fg_color is None + else self._check_color_type(entry_fg_color) + ) + self._entry_border_color = ( + ctk.ThemeManager.theme["CTkEntry"]["border_color"] + if entry_border_color is None + else self._check_color_type(entry_border_color) + ) + self._entry_text_color = ( + ctk.ThemeManager.theme["CTkEntry"]["text_color"] + if entry_text_color is None + else self._check_color_type(entry_text_color) + ) + + self._user_input: Union[str, None] = None + self._running: bool = False + self._title = title + self._label_text = label_text + self._entry_text = entry_text + self._font = font + + self.title(self._title) + self.lift() # lift window on top + self.attributes("-topmost", True) # stay on top + self.protocol("WM_DELETE_WINDOW", self._on_closing) + self.after( + 10, self._create_widgets + ) # create widgets with slight delay, to avoid white flickering of background + self.resizable(False, False) + self.grab_set() # make other windows not clickable + + def _create_widgets(self): + self.grid_columnconfigure((0, 1), weight=1) + self.rowconfigure(0, weight=1) + + self._label = ctk.CTkLabel( + master=self, + width=300, + wraplength=300, + fg_color="transparent", + text_color=self._text_color, + text=self._label_text, + font=self._font, + ) + self._label.grid(row=0, column=0, columnspan=2, padx=20, pady=20, sticky="ew") + + self._entry = ctk.CTkEntry( + master=self, + width=230, + fg_color=self._entry_fg_color, + border_color=self._entry_border_color, + text_color=self._entry_text_color, + font=self._font, + textvariable=ctk.StringVar(self, self._entry_text), + ) + self._entry.grid( + row=1, column=0, columnspan=2, padx=20, pady=(0, 20), sticky="ew" + ) + + self._ok_button = ctk.CTkButton( + master=self, + width=100, + border_width=0, + fg_color=self._button_fg_color, + hover_color=self._button_hover_color, + text_color=self._button_text_color, + text="Ok", + font=self._font, + command=self._ok_event, + ) + self._ok_button.grid( + row=2, column=0, columnspan=1, padx=(20, 10), pady=(0, 20), sticky="ew" + ) + + self._cancel_button = ctk.CTkButton( + master=self, + width=100, + border_width=0, + fg_color=(Color.LIGHT_RED.value, Color.DARK_RED.value), + hover_color=( + Color.HOVER_LIGHT_RED.value, + Color.HOVER_DARK_RED.value, + ), + text_color=self._button_text_color, + text="Cancel", + font=self._font, + command=self._cancel_event, + ) + self._cancel_button.grid( + row=2, column=1, columnspan=1, padx=(10, 20), pady=(0, 20), sticky="ew" + ) + + # set focus to entry with slight delay, otherwise it won't work + self.after(150, lambda: self._entry.focus()) + self._entry.bind("", self._ok_event) + + def _ok_event(self): + self._user_input = self._entry.get() + self.grab_release() + self.destroy() + + def _on_closing(self): + self.grab_release() + self.destroy() + + def _cancel_event(self): + self.grab_release() + self.destroy() + + def get_input(self): + self.master.wait_window(self) + return self._user_input diff --git a/src/view/custom_widgets/ctk_scrollable_dropdown/__init__.py b/src/view/custom_widgets/ctk_scrollable_dropdown/__init__.py new file mode 100644 index 0000000..eb90a08 --- /dev/null +++ b/src/view/custom_widgets/ctk_scrollable_dropdown/__init__.py @@ -0,0 +1,12 @@ +""" +CustomTkinter Scrollable Dropdown Menu +Author: Akash Bora +License: MIT +This is a custom dropdown menu for customtkinter. +Homepage: https://github.com/Akascape/CTkScrollableDropdown +""" + +__version__ = "1.0" + +from .ctk_scrollable_dropdown import CTkScrollableDropdown +from .ctk_scrollable_dropdown_frame import CTkScrollableDropdownFrame diff --git a/src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown.py b/src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown.py new file mode 100644 index 0000000..c5acf97 --- /dev/null +++ b/src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown.py @@ -0,0 +1,453 @@ +""" +Advanced Scrollable Dropdown class for customtkinter widgets +Author: Akash Bora +""" + +import difflib +import sys +import time + +import customtkinter + + +class CTkScrollableDropdown(customtkinter.CTkToplevel): + def __init__( + self, + attach, + x=None, + y=None, + button_color=None, + height: int = 200, + width: int = None, + fg_color=None, + button_height: int = 20, + justify="center", + scrollbar_button_color=None, + scrollbar=True, + scrollbar_button_hover_color=None, + frame_border_width=2, + values=[], + command=None, + image_values=[], + alpha: float = 0.97, + frame_corner_radius=20, + double_click=False, + resize=True, + frame_border_color=None, + text_color=None, + autocomplete=False, + hover_color=None, + **button_kwargs + ): + super().__init__(takefocus=1) + + self.focus() + self.lift() + self.alpha = alpha + self.attach = attach + self.corner = frame_corner_radius + self.padding = 0 + self.focus_something = False + self.disable = True + self.update() + + if sys.platform.startswith("win"): + self.after(100, lambda: self.overrideredirect(True)) + self.transparent_color = self._apply_appearance_mode(self._fg_color) + self.attributes("-transparentcolor", self.transparent_color) + elif sys.platform.startswith("darwin"): + self.overrideredirect(True) + self.transparent_color = "systemTransparent" + self.attributes("-transparent", True) + self.focus_something = True + else: + self.overrideredirect(True) + self.transparent_color = "#000001" + self.corner = 0 + self.padding = 18 + self.withdraw() + + self.hide = True + self.attach.bind( + "", + lambda e: self._withdraw() if not self.disable else None, + add="+", + ) + self.attach.winfo_toplevel().bind( + "", + lambda e: self._withdraw() if not self.disable else None, + add="+", + ) + self.attach.winfo_toplevel().bind( + "", + lambda e: self._withdraw() if not self.disable else None, + add="+", + ) + + self.attributes("-alpha", 0) + self.disable = False + self.fg_color = ( + customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] + if fg_color is None + else fg_color + ) + self.scroll_button_color = ( + customtkinter.ThemeManager.theme["CTkScrollbar"]["button_color"] + if scrollbar_button_color is None + else scrollbar_button_color + ) + self.scroll_hover_color = ( + customtkinter.ThemeManager.theme["CTkScrollbar"]["button_hover_color"] + if scrollbar_button_hover_color is None + else scrollbar_button_hover_color + ) + self.frame_border_color = ( + customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] + if frame_border_color is None + else frame_border_color + ) + self.button_color = ( + customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] + if button_color is None + else button_color + ) + self.text_color = ( + customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] + if text_color is None + else text_color + ) + self.hover_color = ( + customtkinter.ThemeManager.theme["CTkButton"]["hover_color"] + if hover_color is None + else hover_color + ) + + if scrollbar is False: + self.scroll_button_color = self.fg_color + self.scroll_hover_color = self.fg_color + + self.frame = customtkinter.CTkScrollableFrame( + self, + bg_color=self.transparent_color, + fg_color=self.fg_color, + scrollbar_button_hover_color=self.scroll_hover_color, + corner_radius=self.corner, + border_width=frame_border_width, + scrollbar_button_color=self.scroll_button_color, + border_color=self.frame_border_color, + ) + self.frame._scrollbar.grid_configure(padx=3) + self.frame.pack(expand=True, fill="both") + self.dummy_entry = customtkinter.CTkEntry( + self.frame, fg_color="transparent", border_width=0, height=1, width=1 + ) + self.no_match = customtkinter.CTkLabel(self.frame, text="No Match") + self.height = height + self.height_new = height + self.width = width + self.command = command + self.fade = False + self.resize = resize + self.autocomplete = autocomplete + self.var_update = customtkinter.StringVar() + self.appear = False + + if justify.lower() == "left": + self.justify = "w" + elif justify.lower() == "right": + self.justify = "e" + else: + self.justify = "c" + + self.button_height = button_height + self.values = values + self.button_num = len(self.values) + self.image_values = ( + None if len(image_values) != len(self.values) else image_values + ) + + self.resizable(width=False, height=False) + self.transient(self.master) + self._init_buttons(**button_kwargs) + + # Add binding for different ctk widgets + if ( + double_click + or self.attach.winfo_name().startswith("!ctkentry") + or self.attach.winfo_name().startswith("!ctkcombobox") + ): + self.attach.bind("", lambda e: self._iconify(), add="+") + else: + self.attach.bind("", lambda e: self._iconify(), add="+") + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._canvas.tag_bind( + "right_parts", "", lambda e: self._iconify() + ) + self.attach._canvas.tag_bind( + "dropdown_arrow", "", lambda e: self._iconify() + ) + if self.command is None: + self.command = self.attach.set + + if self.attach.winfo_name().startswith("!ctkoptionmenu"): + self.attach._canvas.bind("", lambda e: self._iconify()) + self.attach._text_label.bind("", lambda e: self._iconify()) + if self.command is None: + self.command = self.attach.set + + self.attach.bind("", lambda _: self._destroy(), add="+") + + self.update_idletasks() + self.x = x + self.y = y + + if self.autocomplete: + self.bind_autocomplete() + + self.deiconify() + self.withdraw() + + self.attributes("-alpha", self.alpha) + + def _destroy(self): + self.after(500, self.destroy_popup) + + def _withdraw(self): + if self.winfo_viewable() and self.hide: + self.withdraw() + + self.event_generate("<>") + self.hide = True + + def _update(self, a, b, c): + self.live_update(self.attach._entry.get()) + + def bind_autocomplete( + self, + ): + def appear(x): + self.appear = True + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._entry.configure(textvariable=self.var_update) + self.attach._entry.bind("", appear) + self.attach.set(self.values[0]) + self.var_update.trace_add("write", self._update) + + if self.attach.winfo_name().startswith("!ctkentry"): + self.attach.configure(textvariable=self.var_update) + self.attach.bind("", appear) + self.var_update.trace_add("write", self._update) + + def fade_out(self): + for i in range(100, 0, -10): + if not self.winfo_exists(): + break + self.attributes("-alpha", i / 100) + self.update() + time.sleep(1 / 100) + + def fade_in(self): + for i in range(0, 100, 10): + if not self.winfo_exists(): + break + self.attributes("-alpha", i / 100) + self.update() + time.sleep(1 / 100) + + def _init_buttons(self, **button_kwargs): + self.i = 0 + self.widgets = {} + for row in self.values: + self.widgets[self.i] = customtkinter.CTkButton( + self.frame, + text=row, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + image=self.image_values[self.i] + if self.image_values is not None + else None, + anchor=self.justify, + command=lambda k=row: self._attach_key_press(k), + **button_kwargs + ) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i += 1 + + self.hide = False + + def destroy_popup(self): + self.destroy() + self.disable = True + + def place_dropdown(self): + self.x_pos = ( + self.attach.winfo_rootx() + if self.x is None + else self.x + self.attach.winfo_rootx() + ) + self.y_pos = ( + self.attach.winfo_rooty() + self.attach.winfo_reqheight() + 5 + if self.y is None + else self.y + self.attach.winfo_rooty() + ) + self.width_new = self.attach.winfo_width() if self.width is None else self.width + + if self.resize: + if self.button_num <= 5: + self.height_new = self.button_height * self.button_num + 55 + else: + self.height_new = self.button_height * self.button_num + 35 + if self.height_new > self.height: + self.height_new = self.height + + self.geometry( + "{}x{}+{}+{}".format( + self.width_new, self.height_new, self.x_pos, self.y_pos + ) + ) + self.fade_in() + self.attributes("-alpha", self.alpha) + self.attach.focus() + + def _iconify(self): + if self.attach.cget("state") == "disabled": + return + if self.disable: + return + if self.hide: + self.event_generate("<>") + self._deiconify() + self.focus() + self.hide = False + self.place_dropdown() + if self.focus_something: + self.dummy_entry.pack() + self.dummy_entry.focus_set() + self.after(100, self.dummy_entry.pack_forget) + else: + self.withdraw() + self.hide = True + + def _attach_key_press(self, k): + self.event_generate("<>") + self.fade = True + if self.command: + self.command(k) + self.fade = False + self.fade_out() + self.withdraw() + self.hide = True + + def live_update(self, string=None): + if not self.appear: + return + if self.disable: + return + if self.fade: + return + if string: + string = string.lower() + self._deiconify() + i = 1 + for key in self.widgets.keys(): + s = self.widgets[key].cget("text").lower() + text_similarity = difflib.SequenceMatcher( + None, s[0 : len(string)], string + ).ratio() + similar = s.startswith(string) or text_similarity > 0.75 + if not similar: + self.widgets[key].pack_forget() + else: + self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0)) + i += 1 + + if i == 1: + self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0)) + else: + self.no_match.pack_forget() + self.button_num = i + self.place_dropdown() + + else: + self.no_match.pack_forget() + self.button_num = len(self.values) + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + self.place_dropdown() + + self.frame._parent_canvas.yview_moveto(0.0) + self.appear = False + + def insert(self, value, **kwargs): + self.widgets[self.i] = customtkinter.CTkButton( + self.frame, + text=value, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + anchor=self.justify, + command=lambda k=value: self._attach_key_press(k), + **kwargs + ) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i += 1 + self.values.append(value) + + def _deiconify(self): + if len(self.values) > 0: + self.deiconify() + + def popup(self, x=None, y=None): + self.x = x + self.y = y + self.hide = True + self._iconify() + + def configure(self, **kwargs): + if "height" in kwargs: + self.height = kwargs.pop("height") + self.height_new = self.height + + if "alpha" in kwargs: + self.alpha = kwargs.pop("alpha") + + if "width" in kwargs: + self.width = kwargs.pop("width") + + if "fg_color" in kwargs: + self.frame.configure(fg_color=kwargs.pop("fg_color")) + + if "values" in kwargs: + self.values = kwargs.pop("values") + self.image_values = None + self.button_num = len(self.values) + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + + if "image_values" in kwargs: + self.image_values = kwargs.pop("image_values") + self.image_values = ( + None + if len(self.image_values) != len(self.values) + else self.image_values + ) + if self.image_values is not None: + i = 0 + for key in self.widgets.keys(): + self.widgets[key].configure(image=self.image_values[i]) + i += 1 + + if "button_color" in kwargs: + for key in self.widgets.keys(): + self.widgets[key].configure(fg_color=kwargs.pop("button_color")) + + if "hover_color" not in kwargs: + kwargs["hover_color"] = self.hover_color + + for key in self.widgets.keys(): + self.widgets[key].configure(**kwargs) diff --git a/src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown_frame.py b/src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown_frame.py new file mode 100644 index 0000000..0dcaff5 --- /dev/null +++ b/src/view/custom_widgets/ctk_scrollable_dropdown/ctk_scrollable_dropdown_frame.py @@ -0,0 +1,399 @@ +""" +Advanced Scrollable Dropdown Frame class for customtkinter widgets +Author: Akash Bora +""" + +import difflib +import sys + +import customtkinter + + +class CTkScrollableDropdownFrame(customtkinter.CTkFrame): + def __init__( + self, + attach, + x=None, + y=None, + button_color=None, + height: int = 200, + width: int = None, + fg_color=None, + button_height: int = 20, + justify="center", + scrollbar_button_color=None, + scrollbar=True, + scrollbar_button_hover_color=None, + frame_border_width=2, + values=[], + command=None, + image_values=[], + double_click=False, + frame_corner_radius=True, + resize=True, + frame_border_color=None, + text_color=None, + autocomplete=False, + **button_kwargs + ): + super().__init__( + master=attach.winfo_toplevel(), bg_color=attach.cget("bg_color") + ) + + self.attach = attach + self.corner = 11 if frame_corner_radius else 0 + self.padding = 0 + self.disable = True + + self.hide = True + self.attach.bind( + "", + lambda e: self._withdraw() if not self.disable else None, + add="+", + ) + self.attach.winfo_toplevel().bind( + "", + lambda e: self._withdraw() if not self.disable else None, + add="+", + ) + + self.disable = False + self.fg_color = ( + customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] + if fg_color is None + else fg_color + ) + self.scroll_button_color = ( + customtkinter.ThemeManager.theme["CTkScrollbar"]["button_color"] + if scrollbar_button_color is None + else scrollbar_button_color + ) + self.scroll_hover_color = ( + customtkinter.ThemeManager.theme["CTkScrollbar"]["button_hover_color"] + if scrollbar_button_hover_color is None + else scrollbar_button_hover_color + ) + self.frame_border_color = ( + customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] + if frame_border_color is None + else frame_border_color + ) + self.button_color = ( + customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] + if button_color is None + else button_color + ) + self.text_color = ( + customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] + if text_color is None + else text_color + ) + + if scrollbar is False: + self.scroll_button_color = self.fg_color + self.scroll_hover_color = self.fg_color + + self.frame = customtkinter.CTkScrollableFrame( + self, + fg_color=self.fg_color, + bg_color=attach.cget("bg_color"), + scrollbar_button_hover_color=self.scroll_hover_color, + corner_radius=self.corner, + border_width=frame_border_width, + scrollbar_button_color=self.scroll_button_color, + border_color=self.frame_border_color, + ) + self.frame._scrollbar.grid_configure(padx=3) + self.frame.pack(expand=True, fill="both") + + if self.corner == 0: + self.corner = 21 + + self.dummy_entry = customtkinter.CTkEntry( + self.frame, fg_color="transparent", border_width=0, height=1, width=1 + ) + self.no_match = customtkinter.CTkLabel(self.frame, text="No Match") + self.height = height + self.height_new = height + self.width = width + self.command = command + self.fade = False + self.resize = resize + self.autocomplete = autocomplete + self.var_update = customtkinter.StringVar() + self.appear = False + + if justify.lower() == "left": + self.justify = "w" + elif justify.lower() == "right": + self.justify = "e" + else: + self.justify = "c" + + self.button_height = button_height + self.values = values + self.button_num = len(self.values) + self.image_values = ( + None if len(image_values) != len(self.values) else image_values + ) + + self._init_buttons(**button_kwargs) + + # Add binding for different ctk widgets + if ( + double_click + or self.attach.winfo_name().startswith("!ctkentry") + or self.attach.winfo_name().startswith("!ctkcombobox") + ): + self.attach.bind("", lambda e: self._iconify(), add="+") + self.attach._entry.bind( + "", + lambda e: self._withdraw() if not self.disable else None, + add="+", + ) + else: + self.attach.bind("", lambda e: self._iconify(), add="+") + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._canvas.tag_bind( + "right_parts", "", lambda e: self._iconify() + ) + self.attach._canvas.tag_bind( + "dropdown_arrow", "", lambda e: self._iconify() + ) + + if self.command is None: + self.command = self.attach.set + + if self.attach.winfo_name().startswith("!ctkoptionmenu"): + self.attach._canvas.bind("", lambda e: self._iconify()) + self.attach._text_label.bind("", lambda e: self._iconify()) + if self.command is None: + self.command = self.attach.set + + self.x = x + self.y = y + + self.attach.bind("", lambda _: self._destroy(), add="+") + + if self.autocomplete: + self.bind_autocomplete() + + def _destroy(self): + self.after(500, self.destroy_popup) + + def _withdraw(self): + if self.winfo_viewable() and self.hide: + self.place_forget() + + self.event_generate("<>") + self.hide = True + + def _update(self, a, b, c): + self.live_update(self.attach._entry.get()) + + def bind_autocomplete(self): + def appear(x): + self.appear = True + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._entry.configure(textvariable=self.var_update) + self.attach.set(self.values[0]) + self.attach._entry.bind("", appear) + self.var_update.trace_add("write", self._update) + + if self.attach.winfo_name().startswith("!ctkentry"): + self.attach.configure(textvariable=self.var_update) + self.attach.bind("", appear) + self.var_update.trace_add("write", self._update) + + def _init_buttons(self, **button_kwargs): + self.i = 0 + self.widgets = {} + for row in self.values: + self.widgets[self.i] = customtkinter.CTkButton( + self.frame, + text=row, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + image=self.image_values[self.i] + if self.image_values is not None + else None, + anchor=self.justify, + command=lambda k=row: self._attach_key_press(k), + **button_kwargs + ) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i += 1 + + self.hide = False + + def destroy_popup(self): + self.destroy() + self.disable = True + + def place_dropdown(self): + self.x_pos = ( + self.attach.winfo_x() + if self.x is None + else self.x + self.attach.winfo_rootx() + ) + self.y_pos = ( + self.attach.winfo_y() + self.attach.winfo_reqheight() + 5 + if self.y is None + else self.y + self.attach.winfo_rooty() + ) + self.width_new = ( + self.attach.winfo_width() - 45 + self.corner + if self.width is None + else self.width + ) + + if self.resize: + if self.button_num <= 5: + self.height_new = self.button_height * self.button_num + 55 + else: + self.height_new = self.button_height * self.button_num + 35 + if self.height_new > self.height: + self.height_new = self.height + + self.frame.configure(width=self.width_new, height=self.height_new) + self.place(x=self.x_pos, y=self.y_pos) + + if sys.platform.startswith("darwin"): + self.dummy_entry.pack() + self.after(100, self.dummy_entry.pack_forget()) + + self.lift() + self.attach.focus() + + def _iconify(self): + if self.attach.cget("state") == "disabled": + return + if self.disable: + return + if self.hide: + self.event_generate("<>") + self.hide = False + self.place_dropdown() + else: + self.place_forget() + self.hide = True + + def _attach_key_press(self, k): + self.event_generate("<>") + self.fade = True + if self.command: + self.command(k) + self.fade = False + self.place_forget() + self.hide = True + + def live_update(self, string=None): + if not self.appear: + return + if self.disable: + return + if self.fade: + return + if string: + string = string.lower() + self._deiconify() + i = 1 + for key in self.widgets.keys(): + s = self.widgets[key].cget("text").lower() + text_similarity = difflib.SequenceMatcher( + None, s[0 : len(string)], string + ).ratio() + similar = s.startswith(string) or text_similarity > 0.75 + if not similar: + self.widgets[key].pack_forget() + else: + self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0)) + i += 1 + + if i == 1: + self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0)) + else: + self.no_match.pack_forget() + self.button_num = i + self.place_dropdown() + + else: + self.no_match.pack_forget() + self.button_num = len(self.values) + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + self.place_dropdown() + + self.frame._parent_canvas.yview_moveto(0.0) + self.appear = False + + def insert(self, value, **kwargs): + self.widgets[self.i] = customtkinter.CTkButton( + self.frame, + text=value, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + anchor=self.justify, + command=lambda k=value: self._attach_key_press(k), + **kwargs + ) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i += 1 + self.values.append(value) + + def _deiconify(self): + if len(self.values) > 0: + self.pack_forget() + + def popup(self, x=None, y=None): + self.x = x + self.y = y + self.hide = True + self._iconify() + + def configure(self, **kwargs): + if "height" in kwargs: + self.height = kwargs.pop("height") + self.height_new = self.height + + if "alpha" in kwargs: + self.alpha = kwargs.pop("alpha") + + if "width" in kwargs: + self.width = kwargs.pop("width") + + if "fg_color" in kwargs: + self.frame.configure(fg_color=kwargs.pop("fg_color")) + + if "values" in kwargs: + self.values = kwargs.pop("values") + self.image_values = None + self.button_num = len(self.values) + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + + if "image_values" in kwargs: + self.image_values = kwargs.pop("image_values") + self.image_values = ( + None + if len(self.image_values) != len(self.values) + else self.image_values + ) + if self.image_values is not None: + i = 0 + for key in self.widgets.keys(): + self.widgets[key].configure(image=self.image_values[i]) + i += 1 + + if "button_color" in kwargs: + for key in self.widgets.keys(): + self.widgets[key].configure(fg_color=kwargs.pop("button_color")) + + for key in self.widgets.keys(): + self.widgets[key].configure(**kwargs) diff --git a/src/view/main_window.py b/src/view/main_window.py new file mode 100644 index 0000000..8d2c115 --- /dev/null +++ b/src/view/main_window.py @@ -0,0 +1,774 @@ +import locale +import tkinter + +import customtkinter as ctk +import utils.config_manager as cm +import utils.constants as c +import utils.dict_utils as du +import utils.path_helper as ph +from controller.main_controller import MainController +from model.config.config_google_api import ConfigGoogleApi +from model.config.config_subtitles import ConfigSubtitles +from model.config.config_whisperx import ConfigWhisperX +from model.transcription import Transcription +from PIL import Image +from utils.enums import AudioSource, Color, ComputeType, ModelSize, TranscriptionMethod +from utils.i18n import _ + +from .custom_widgets.ctk_input_dialog import CTkInputDialog +from .custom_widgets.ctk_scrollable_dropdown import CTkScrollableDropdown + + +class MainWindow(ctk.CTkFrame): + def __init__( + self, + parent, + config_whisperx: ConfigWhisperX, + config_google_api: ConfigGoogleApi, + config_subtitles: ConfigSubtitles, + ): + super().__init__(parent) + + # Configure grid of the window + self.grid_columnconfigure(1, weight=1) + self.grid_rowconfigure(2, weight=1) + + # Init the configs + self._config_whisperx = config_whisperx + self._config_google_api = config_google_api + self._config_subtitles = config_subtitles + + # Init the controller + self._controller = None + + # Init the components of the window + self._init_sidebar() + self._init_main_content() + + # State + self._transcribe_from_source = AudioSource.FILE + self._is_transcribing_from_mic = False + + # To handle debouncing + self._after_id = None # To store the `after()` method ID + + # GETTERS AND SETTERS + + def set_controller(self, controller: MainController): + """ + Set the controller of the window. + + :param controller: View controller + :type controller: MainController + """ + self._controller = controller + + def _get_language_code(self): + return du.find_key_by_value( + dictionary=c.AUDIO_LANGUAGES, target_value=self.omn_audio_language.get() + ) + + def _get_whisperx_args(self): + whisperx_args = {} + if self.radio_var.get() == TranscriptionMethod.WHISPERX.value: + whisperx_args["should_translate"] = ( + self.chk_whisper_options_translate.get() == 1 + ) + whisperx_args["should_subtitle"] = ( + self.chk_whisper_options_subtitles.get() == 1 + ) + + return whisperx_args + + # WIDGETS INITIALIZATION + + def _init_sidebar(self): + # Sidebar frame + self.frm_sidebar = ctk.CTkScrollableFrame( + master=self, width=230, corner_radius=0 + ) + self.frm_sidebar.grid(row=0, column=0, rowspan=4, sticky=ctk.NSEW) + self.frm_sidebar.grid_rowconfigure(10, weight=1) + + # Logo label + self.logo_image = ctk.CTkImage( + light_image=Image.open( + ph.ROOT_PATH / ph.IMG_RELATIVE_PATH / "icon-light.png" + ), + dark_image=Image.open( + ph.ROOT_PATH / ph.IMG_RELATIVE_PATH / "icon-dark.png" + ), + size=(32, 32), + ) + + self.lbl_logo = ctk.CTkLabel( + master=self.frm_sidebar, + text=f" {c.APP_NAME}", + image=self.logo_image, + compound=ctk.LEFT, + font=ctk.CTkFont(size=22, weight="bold"), + ) + self.lbl_logo.grid(row=0, column=0, padx=20, pady=(19, 0)) + + # ------------------ + + # Shared options frame + self.frm_shared_options = ctk.CTkFrame(master=self.frm_sidebar, border_width=2) + self.frm_shared_options.grid(row=1, column=0, padx=20, pady=(20, 0)) + + ## 'Audio language' option menu + self.lbl_audio_language = ctk.CTkLabel( + master=self.frm_shared_options, + text=_("Audio language"), + font=ctk.CTkFont(size=14, weight="bold"), + ) + self.lbl_audio_language.grid(row=0, column=0, padx=0, pady=(10, 0)) + + self.omn_audio_language = ctk.CTkOptionMenu(master=self.frm_shared_options) + CTkScrollableDropdown( + attach=self.omn_audio_language, + values=list(c.AUDIO_LANGUAGES.values()), + alpha=1, + ) + self.omn_audio_language.grid(row=1, column=0, padx=20, pady=0, sticky=ctk.EW) + try: + self.omn_audio_language.set( + c.AUDIO_LANGUAGES[locale.getdefaultlocale()[0][:2]] + ) + except Exception: + self.omn_audio_language.set("English") + + ## 'Transcribe from' option menu + self.lbl_transcribe_from = ctk.CTkLabel( + master=self.frm_shared_options, + text="Transcribe from", + font=ctk.CTkFont(size=14, weight="bold"), + ) + self.lbl_transcribe_from.grid(row=2, column=0, padx=0, pady=(15, 0)) + + self.omn_transcribe_from = ctk.CTkOptionMenu( + master=self.frm_shared_options, + values=[e.value for e in AudioSource], + command=self._on_change_transcribe_from_event, + ) + self.omn_transcribe_from.grid(row=3, column=0, padx=20, pady=0, sticky=ctk.EW) + self.omn_transcribe_from.set(AudioSource.FILE.value) + + ## 'Generate transcription' button + self.btn_generate_transcription = ctk.CTkButton( + master=self.frm_shared_options, + fg_color="green", + hover_color="darkgreen", + text=_("Generate transcription"), + command=lambda: self._on_generate_transcription(), + ) + self.btn_generate_transcription.grid( + row=4, column=0, padx=20, pady=(25, 20), sticky=ctk.EW + ) + + # ------------------ + + # 'Transcribe using' frame + self.frm_transcribe_using = ctk.CTkFrame( + master=self.frm_sidebar, border_width=2 + ) + self.frm_transcribe_using.grid(row=2, column=0, padx=0, pady=(20, 0)) + + # 'Transcribe using' label + self.lbl_transcribe_using = ctk.CTkLabel( + master=self.frm_transcribe_using, + text=_("Transcribe using"), + font=ctk.CTkFont(size=14, weight="bold"), # 14 is the default size + ) + self.lbl_transcribe_using.grid(row=0, column=0, padx=0, pady=(10, 12.5)) + + self.radio_var = tkinter.IntVar(value=TranscriptionMethod.WHISPERX.value) + + self.rbt_transcribe_using_whisper = ctk.CTkRadioButton( + master=self.frm_transcribe_using, + variable=self.radio_var, + value=TranscriptionMethod.WHISPERX.value, + text="WhisperX (local)", + command=self._on_transcribe_using_change, + ) + self.rbt_transcribe_using_whisper.grid( + row=1, column=0, padx=20, pady=0, sticky=ctk.W + ) + + self.rbt_transcribe_using_google = ctk.CTkRadioButton( + master=self.frm_transcribe_using, + variable=self.radio_var, + value=TranscriptionMethod.GOOGLE_API.value, + text="Google API (remote)", + command=self._on_transcribe_using_change, + ) + self.rbt_transcribe_using_google.grid( + row=2, column=0, padx=20, pady=(7.5, 16), sticky=ctk.W + ) + + # ------------------ + + # Whisper options frame + self.frm_whisper_options = ctk.CTkFrame(master=self.frm_sidebar, border_width=2) + self.frm_whisper_options.grid(row=3, column=0, padx=20, pady=(20, 0)) + + ## Title label + self.lbl_whisper_options = ctk.CTkLabel( + master=self.frm_whisper_options, + text="WhisperX options", + font=ctk.CTkFont(size=14, weight="bold"), # 14 is the default size + ) + self.lbl_whisper_options.grid(row=0, column=0, padx=10, pady=(10, 12.5)) + + ## 'Translate to English' checkbox + self.chk_whisper_options_translate = ctk.CTkCheckBox( + master=self.frm_whisper_options, + text="Translate to English", + command=self._on_chk_whisper_options_translate_change, + ) + self.chk_whisper_options_translate.grid( + row=1, column=0, padx=20, pady=0, sticky=ctk.W + ) + + ## 'Subtitles' checkbox + self.chk_whisper_options_subtitles = ctk.CTkCheckBox( + master=self.frm_whisper_options, + text="Generate subtitles", + command=self._on_whisper_options_subtitles_change, + ) + self.chk_whisper_options_subtitles.grid( + row=2, column=0, padx=20, pady=(10, 0), sticky=ctk.W + ) + + ## 'Show advanced options' button + self.btn_whisperx_show_advanced_options = ctk.CTkButton( + master=self.frm_whisper_options, + text=_("Show advanced options"), + command=self._on_show_advanced_options, + ) + self.btn_whisperx_show_advanced_options.grid( + row=3, column=0, padx=20, pady=16, sticky=ctk.EW + ) + + # ------------------ + + # 'Google API options' frame + self.frm_google_api_options = ctk.CTkFrame( + master=self.frm_sidebar, border_width=2 + ) + self.frm_google_api_options.grid( + row=3, column=0, padx=20, pady=(20, 0), sticky=ctk.EW + ) + # Hidden at first because WhisperX is the default transcription method + self.frm_google_api_options.grid_remove() + + ## Title label + self.lbl_google_api_options = ctk.CTkLabel( + master=self.frm_google_api_options, + text="Google API options", + font=ctk.CTkFont(size=14, weight="bold"), # 14 is the default size + ) + self.lbl_google_api_options.grid(row=0, column=0, padx=10, pady=(10, 12.5)) + + ## 'Set API key' button + self.btn_set_google_api_key = ctk.CTkButton( + master=self.frm_google_api_options, + text=_("Set API key"), + command=self._on_set_google_api_key, + ) + self.btn_set_google_api_key.grid( + row=1, column=0, padx=20, pady=(0, 20), sticky=ctk.EW + ) + + # ------------------ + + # Subtitle options frame + self.frm_subtitle_options = ctk.CTkFrame( + master=self.frm_sidebar, border_width=2 + ) + self.frm_subtitle_options.grid( + row=4, column=0, padx=20, pady=(20, 0), sticky=ctk.EW + ) + self.frm_subtitle_options.grid_remove() # Hidden by default + + ## Title label + self.lbl_subtitle_options = ctk.CTkLabel( + master=self.frm_subtitle_options, + text="Subtitle options", + font=ctk.CTkFont(size=14, weight="bold"), # 14 is the default size + ) + self.lbl_subtitle_options.grid( + row=0, column=0, padx=40, pady=(10, 0), sticky=ctk.EW + ) + + ## 'Highlight words' check box + self.chk_highlight_words = ctk.CTkCheckBox( + master=self.frm_subtitle_options, + text="Highlight words", + command=lambda: self._on_config_change( + section=ConfigSubtitles.Key.SECTION, + key=ConfigSubtitles.Key.HIGHLIGHT_WORDS, + new_value="True" if self.chk_highlight_words.get() else "False", + ), + ) + self.chk_highlight_words.grid(row=1, column=0, padx=20, pady=10, sticky=ctk.W) + + ## 'Max. line count' entry + self.lbl_max_line_count = ctk.CTkLabel( + master=self.frm_subtitle_options, + text=_("Max. line count"), + ) + self.lbl_max_line_count.grid( + row=2, column=0, padx=(52, 0), pady=0, sticky=ctk.W + ) + + self.max_line_count = ctk.StringVar( + self, str(self._config_subtitles.max_line_count) + ) + self._setup_debounced_change( + section=ConfigSubtitles.Key.SECTION, + key=ConfigSubtitles.Key.MAX_LINE_COUNT, + variable=self.max_line_count, + callback=self._on_config_change, + ) + + self.ent_max_line_count = ctk.CTkEntry( + master=self.frm_subtitle_options, + width=28, + textvariable=self.max_line_count, + ) + self.ent_max_line_count.grid( + row=2, column=0, padx=(18, 20), pady=0, sticky=ctk.W + ) + + ## 'Max. line width' entry + self.lbl_max_line_width = ctk.CTkLabel( + master=self.frm_subtitle_options, + text=_("Max. line width"), + ) + self.lbl_max_line_width.grid( + row=3, column=0, padx=(52, 0), pady=(10, 14), sticky=ctk.W + ) + + self.max_line_width = ctk.StringVar( + self, str(self._config_subtitles.max_line_width) + ) + self._setup_debounced_change( + section=ConfigSubtitles.Key.SECTION, + key=ConfigSubtitles.Key.MAX_LINE_WIDTH, + variable=self.max_line_width, + callback=self._on_config_change, + ) + + self.ent_max_line_width = ctk.CTkEntry( + master=self.frm_subtitle_options, + width=28, + textvariable=self.max_line_width, + ) + self.ent_max_line_width.grid( + row=3, column=0, padx=(18, 20), pady=(10, 14), sticky=ctk.W + ) + + # ------------------ + + # WhisperX advanced options frame + self.frm_whisperx_advanced_options = ctk.CTkFrame( + master=self.frm_sidebar, border_width=2 + ) + self.frm_whisperx_advanced_options.grid( + row=5, column=0, padx=20, pady=(20, 0), sticky=ctk.EW + ) + self.frm_whisperx_advanced_options.grid_remove() # Hidden by default + + ## Title label + self.lbl_advanced_options = ctk.CTkLabel( + master=self.frm_whisperx_advanced_options, + text="Advanced options", + font=ctk.CTkFont(size=14, weight="bold"), # 14 is the default size + ) + self.lbl_advanced_options.grid( + row=0, column=0, padx=10, pady=(10, 5), sticky=ctk.EW + ) + + ## 'Model size' option menu + self.lbl_model_size = ctk.CTkLabel( + master=self.frm_whisperx_advanced_options, + text="Model size", + ) + self.lbl_model_size.grid(row=1, column=0, padx=20, pady=0, sticky=ctk.W) + + self.omn_model_size = ctk.CTkOptionMenu( + master=self.frm_whisperx_advanced_options, + values=[model_size.value for model_size in ModelSize.__members__.values()], + command=lambda *args: self._on_config_change( + section=ConfigWhisperX.Key.SECTION, + key=ConfigWhisperX.Key.MODEL_SIZE, + new_value=self.omn_model_size.get(), + ), + ) + self.omn_model_size.grid(row=2, column=0, padx=20, pady=(3, 10), sticky=ctk.EW) + self.omn_model_size.set(self._config_whisperx.model_size) + + ## 'Compute type' option menu + self.lbl_compute_type = ctk.CTkLabel( + master=self.frm_whisperx_advanced_options, + text="Compute type", + ) + self.lbl_compute_type.grid(row=3, column=0, padx=20, pady=0, sticky=ctk.W) + + self.omn_compute_type = ctk.CTkOptionMenu( + master=self.frm_whisperx_advanced_options, + values=[ + compute_type.value for compute_type in ComputeType.__members__.values() + ], + command=lambda *args: self._on_config_change( + section=ConfigWhisperX.Key.SECTION, + key=ConfigWhisperX.Key.COMPUTE_TYPE, + new_value=self.omn_compute_type.get(), + ), + ) + self.omn_compute_type.grid( + row=4, column=0, padx=20, pady=(3, 17), sticky=ctk.EW + ) + self.omn_compute_type.set(self._config_whisperx.compute_type) + + ## 'Batch size' entry + self.lbl_batch_size = ctk.CTkLabel( + master=self.frm_whisperx_advanced_options, + text="Batch size", + ) + self.lbl_batch_size.grid(row=5, column=0, padx=(50, 0), pady=0, sticky=ctk.W) + + self.batch_size = ctk.StringVar(self, str(self._config_whisperx.batch_size)) + self._setup_debounced_change( + section=ConfigWhisperX.Key.SECTION, + key=ConfigWhisperX.Key.BATCH_SIZE, + variable=self.batch_size, + callback=self._on_config_change, + ) + + self.ent_batch_size = ctk.CTkEntry( + master=self.frm_whisperx_advanced_options, + width=28, + textvariable=self.batch_size, + ) + self.ent_batch_size.grid(row=5, column=0, padx=(18, 20), pady=0, sticky=ctk.W) + + ## 'Use CPU' checkbox + self.chk_use_cpu = ctk.CTkCheckBox( + master=self.frm_whisperx_advanced_options, + text="Use CPU", + command=lambda: self._on_config_change( + section=ConfigWhisperX.Key.SECTION, + key=ConfigWhisperX.Key.USE_CPU, + new_value="True" if self.chk_use_cpu.get() else "False", + ), + ) + self.chk_use_cpu.grid(row=6, column=0, padx=20, pady=(10, 16), sticky=ctk.W) + + if self._config_whisperx.use_cpu: + self.chk_use_cpu.select() + + if not self._config_whisperx.can_use_gpu: + self.chk_use_cpu.select() + self.chk_use_cpu.configure(state=ctk.DISABLED) + + # ------------------ + + ## 'Appearance mode' option menu + self.lbl_appearance_mode = ctk.CTkLabel( + master=self.frm_sidebar, + text=_("Appearance mode"), + anchor=ctk.W, + font=ctk.CTkFont(size=14, weight="bold"), + ) + self.lbl_appearance_mode.grid(row=12, column=0, padx=20, pady=(50, 0)) + + self.omn_appearance_mode = ctk.CTkOptionMenu( + master=self.frm_sidebar, + values=[_("System"), _("Light"), _("Dark")], + command=self._change_appearance_mode_event, + ) + self.omn_appearance_mode.grid(row=13, column=0, padx=20, pady=0, sticky=ctk.EW) + + ## Info label + self.lbl_info = ctk.CTkLabel( + master=self.frm_sidebar, + text="v2.2.0 | Made by HenestrosaDev", + font=ctk.CTkFont(size=12), + ) + self.lbl_info.grid(row=14, column=0, padx=20, pady=(5, 10)) + + def _init_main_content(self): + # Main entry frame + self.frm_main_entry = ctk.CTkFrame(master=self, fg_color="transparent") + self.frm_main_entry.grid(row=0, column=1, padx=20, pady=(20, 0), sticky=ctk.EW) + self.frm_main_entry.grid_columnconfigure(1, weight=1) + + ## 'Path' entry + self.lbl_path = ctk.CTkLabel( + master=self.frm_main_entry, + text="File path", + font=ctk.CTkFont(size=14, weight="bold"), + ) + self.lbl_path.grid(row=0, column=0, padx=(0, 15), sticky=ctk.W) + + self.ent_path = ctk.CTkEntry(master=self.frm_main_entry) + self.ent_path.grid(row=0, column=1, padx=0, sticky=ctk.EW) + + ## File explorer image button + self.img_file_explorer = ctk.CTkImage( + Image.open(ph.ROOT_PATH / ph.IMG_RELATIVE_PATH / "file-explorer.png"), + size=(24, 24), + ) + self.btn_file_explorer = ctk.CTkButton( + self.frm_main_entry, + image=self.img_file_explorer, + text="", + width=32, + command=self._on_select_file, + ) + self.btn_file_explorer.grid(row=0, column=2, padx=(15, 0), sticky=ctk.E) + + ## Textbox + self.tbx_transcription = ctk.CTkTextbox(master=self, wrap=ctk.WORD) + self.tbx_transcription.grid(row=2, column=1, padx=20, pady=20, sticky=ctk.NSEW) + + ## Progress bar + self.progress_bar = ctk.CTkProgressBar(master=self) + self.progress_bar.configure(mode="indeterminate") + + ## 'Save transcription' button + self.btn_save = ctk.CTkButton( + master=self, + fg_color="green", + hover_color="darkgreen", + text=_("Save transcription"), + command=self._on_save_transcription, + ) + self.btn_save.grid(row=3, column=1, padx=20, pady=(0, 20), sticky=ctk.EW) + + # PUBLIC METHODS + + def on_select_file_success(self, filepath): + self.ent_path.configure(textvariable=ctk.StringVar(self, filepath)) + + def on_processing_transcription(self): + # Disable action buttons to avoid multiple requests at the same time + self.ent_path.configure(state=ctk.DISABLED) + self.omn_transcribe_from.configure(state=ctk.DISABLED) + self.omn_audio_language.configure(state=ctk.DISABLED) + + if not self._is_transcribing_from_mic: + self.btn_generate_transcription.configure(state=ctk.DISABLED) + + # Show progress bar + self._toggle_progress_bar_visibility(should_show=True) + + # Remove previous text + self.display_text("") + + def on_processed_transcription(self, success: bool): + # Re-enable disabled widgets + self.ent_path.configure(state=ctk.NORMAL) + self.omn_transcribe_from.configure(state=ctk.NORMAL) + self.omn_audio_language.configure(state=ctk.NORMAL) + self.btn_generate_transcription.configure(state=ctk.NORMAL) + + self._toggle_progress_bar_visibility(should_show=False) + + # HELPER METHODS + + def display_text(self, text): + self.tbx_transcription.delete("1.0", ctk.END) + self.tbx_transcription.insert("0.0", text) + + # PRIVATE METHODS + + def _setup_debounced_change(self, section, key, variable, callback, *unused): + variable.trace_add( + mode="write", + callback=lambda *args: self._on_change_debounced( + section, key, variable, callback + ), + ) + + def _on_change_debounced(self, section, key, variable, callback, delay=600): + # Cancel the previously scheduled after call + if self._after_id is not None: + self.after_cancel(self._after_id) + + # Schedule a new after call with the specified delay + self._after_id = self.after( + delay, lambda: callback(section, key, variable.get()) + ) + + def _on_change_app_language(self, language_name: str): + self._controller.change_app_language(language_name) + + def _on_change_transcribe_from_event(self, option: str): + self._transcribe_from_source = AudioSource(option) + self.ent_path.configure(textvariable=ctk.StringVar(self, "")) + + if self._transcribe_from_source == AudioSource.FILE: + self.btn_generate_transcription.configure(text="Generate transcription") + self.lbl_path.configure(text="File path") + self.btn_file_explorer.grid() + self.frm_main_entry.grid() + + elif self._transcribe_from_source == AudioSource.MIC: + self.btn_generate_transcription.configure(text="Start recording") + self.frm_main_entry.grid_remove() + + elif self._transcribe_from_source == AudioSource.YOUTUBE: + self.btn_generate_transcription.configure(text="Generate transcription") + self.lbl_path.configure(text="YouTube video URL") + self.btn_file_explorer.grid_remove() + self.frm_main_entry.grid() + + def _on_select_file(self): + self._controller.select_file() + + def _on_transcribe_from_mic(self): + if self._is_transcribing_from_mic: + self.stop_recording_from_mic() + else: + self._start_recording_from_mic() + + def _start_recording_from_mic(self): + self._is_transcribing_from_mic = True + + self.btn_generate_transcription.configure( + fg_color=(Color.LIGHT_RED.value, Color.DARK_RED.value), + hover_color=( + Color.HOVER_LIGHT_RED.value, + Color.HOVER_DARK_RED.value, + ), + text=_("Stop recording"), + ) + + transcription = Transcription( + source=AudioSource.MIC, + language_code=self._get_language_code(), + method=self.radio_var.get(), + **self._get_whisperx_args(), + ) + self._controller.prepare_for_transcription(transcription) + + def stop_recording_from_mic(self): + self._is_transcribing_from_mic = False + + self.btn_generate_transcription.configure( + fg_color="green", + hover_color="darkgreen", + text="Start recording", + state=ctk.DISABLED, + ) + + self._controller.stop_recording_from_mic() + + def _on_generate_transcription(self): + self.ent_path.configure(state=ctk.DISABLED) + self.omn_transcribe_from.configure(state=ctk.DISABLED) + self.omn_audio_language.configure(state=ctk.DISABLED) + + transcription = Transcription( + language_code=self._get_language_code(), + method=self.radio_var.get(), + **self._get_whisperx_args(), + ) + + if self._transcribe_from_source == AudioSource.FILE: + transcription.source = AudioSource.FILE + transcription.source_file_path = self.ent_path.get() + + self._controller.prepare_for_transcription(transcription) + + elif self._transcribe_from_source == AudioSource.MIC: + self._on_transcribe_from_mic() + + elif self._transcribe_from_source == AudioSource.YOUTUBE: + transcription.source = AudioSource.YOUTUBE + transcription.youtube_url = self.ent_path.get() + + self._controller.prepare_for_transcription(transcription) + + def _on_save_transcription(self): + self._controller.save_transcription() + + def _on_transcribe_using_change(self): + if self.radio_var.get() == TranscriptionMethod.WHISPERX.value: + self.frm_whisper_options.grid() + self.frm_google_api_options.grid_remove() + elif self.radio_var.get() == TranscriptionMethod.GOOGLE_API.value: + self.frm_whisper_options.grid_remove() + self.frm_whisperx_advanced_options.grid_remove() + self.btn_whisperx_show_advanced_options.configure( + text=_("Show advanced options") + ) + self.frm_google_api_options.grid() + + def _on_set_google_api_key(self): + old_api_key = self._config_google_api.api_key + + dialog = CTkInputDialog( + title="Google API key", + label_text="Type in the API key:", + entry_text=old_api_key, + ) + + new_api_key = dialog.get_input() + + if new_api_key is not None and old_api_key != new_api_key: + self._on_config_change( + section=ConfigGoogleApi.Key.SECTION, + key=ConfigGoogleApi.Key.API_KEY, + new_value=new_api_key.strip(), + ) + + def _on_chk_whisper_options_translate_change(self): + if self.chk_whisper_options_translate.get(): + self.chk_whisper_options_subtitles.deselect() + self.chk_whisper_options_subtitles.configure(state=ctk.DISABLED) + self.frm_subtitle_options.grid_remove() + else: + self.chk_whisper_options_subtitles.configure(state=ctk.NORMAL) + + def _on_whisper_options_subtitles_change(self): + if self.chk_whisper_options_subtitles.get(): + self.frm_subtitle_options.grid() + else: + self.frm_subtitle_options.grid_remove() + + def _on_show_advanced_options(self): + if self.frm_whisperx_advanced_options.winfo_ismapped(): + self.frm_whisperx_advanced_options.grid_remove() + self.btn_whisperx_show_advanced_options.configure( + text=_("Show advanced options") + ) + else: + self.frm_whisperx_advanced_options.grid() + self.btn_whisperx_show_advanced_options.configure( + text=_("Hide advanced options") + ) + + def _toggle_progress_bar_visibility(self, should_show): + if should_show: + self.progress_bar.grid(row=2, column=1, padx=40, pady=0, sticky=ctk.EW) + self.progress_bar.start() + else: + self.progress_bar.grid_forget() + + @staticmethod + def _on_config_change(section, key, new_value): + cm.ConfigManager.modify_value(section, key, new_value) + + @staticmethod + def _change_appearance_mode_event(new_appearance_mode: str): + appearance_mode_map = { + _("Dark"): "Dark", + _("Light"): "Light", + _("System"): "System", + } + appearance_mode = appearance_mode_map.get(new_appearance_mode, "System") + ctk.set_appearance_mode(appearance_mode)