diff --git a/README.md b/README.md index c53ee4a6..173d25e4 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,11 @@ Install with [brew utility](https://brew.sh/) brew install --cask buzz ``` -Or download the `.dmg` from the [releases page](https://github.com/chidiwilliams/buzz/releases/latest). +Or download the `.dmg` from the [SourceForge](https://sourceforge.net/projects/buzz-captions/files/). ### Windows -Download and run the `.exe` from the [releases page](https://github.com/chidiwilliams/buzz/releases/latest). +Get the installation files from the [SourceForge](https://sourceforge.net/projects/buzz-captions/files/). App is not signed, you will get a warning when you install it. Select `More info` -> `Run anyway`. diff --git a/buzz/db/migrator.py b/buzz/db/migrator.py index 0fa6b043..d36f9b34 100644 --- a/buzz/db/migrator.py +++ b/buzz/db/migrator.py @@ -69,7 +69,8 @@ class DBMigrator: msg_argv += (args,) else: args = [] - logging.info(msg_tmpl, *msg_argv) + # Uncomment this to get debugging information + # logging.info(msg_tmpl, *msg_argv) self.db.execute(sql, args) self.n_changes += 1 diff --git a/buzz/file_transcriber_queue_worker.py b/buzz/file_transcriber_queue_worker.py index 24fe8013..f6cf91fb 100644 --- a/buzz/file_transcriber_queue_worker.py +++ b/buzz/file_transcriber_queue_worker.py @@ -139,7 +139,7 @@ class FileTranscriberQueueWorker(QObject): self.current_transcriber.stop() if self.current_transcriber_thread is not None: - if not self.current_transcriber_thread.wait(3000): + if not self.current_transcriber_thread.wait(5000): logging.warning("Transcriber thread did not terminate gracefully") self.current_transcriber_thread.terminate() diff --git a/buzz/transcriber/recording_transcriber.py b/buzz/transcriber/recording_transcriber.py index 5c71b8ba..8e5cc3d1 100644 --- a/buzz/transcriber/recording_transcriber.py +++ b/buzz/transcriber/recording_transcriber.py @@ -326,7 +326,7 @@ class RecordingTranscriber(QObject): self.is_running = False if self.process and self.process.poll() is None: self.process.terminate() - self.process.wait() + self.process.wait(5000) def start_local_whisper_server(self): self.transcription.emit(_("Starting Whisper.cpp...")) @@ -416,4 +416,4 @@ class RecordingTranscriber(QObject): def __del__(self): if self.process and self.process.poll() is None: self.process.terminate() - self.process.wait() \ No newline at end of file + self.process.wait(5000) \ No newline at end of file diff --git a/buzz/transcriber/whisper_file_transcriber.py b/buzz/transcriber/whisper_file_transcriber.py index 1b2ea99e..c5533397 100644 --- a/buzz/transcriber/whisper_file_transcriber.py +++ b/buzz/transcriber/whisper_file_transcriber.py @@ -274,11 +274,11 @@ class WhisperFileTranscriber(FileTranscriber): if self.started_process: self.current_process.terminate() # Use timeout to avoid hanging indefinitely - self.current_process.join(timeout=5) + self.current_process.join(timeout=10) if self.current_process.is_alive(): logging.warning("Process didn't terminate gracefully, force killing") self.current_process.kill() - self.current_process.join(timeout=2) + self.current_process.join(timeout=5) # Close pipes to unblock the read_line thread try: @@ -291,7 +291,7 @@ class WhisperFileTranscriber(FileTranscriber): # Join read_line_thread with timeout to prevent hanging if self.read_line_thread and self.read_line_thread.is_alive(): - self.read_line_thread.join(timeout=3) + self.read_line_thread.join(timeout=5) if self.read_line_thread.is_alive(): logging.warning("Read line thread didn't terminate gracefully") diff --git a/buzz/translator.py b/buzz/translator.py index 0243aacf..56a816ea 100644 --- a/buzz/translator.py +++ b/buzz/translator.py @@ -68,7 +68,8 @@ class Translator(QObject): messages=[ {"role": "system", "content": self.transcription_options.llm_prompt}, {"role": "user", "content": transcript} - ] + ], + timeout=30.0 ) except Exception as e: completion = None diff --git a/buzz/widgets/main_window.py b/buzz/widgets/main_window.py index ed471ec6..0ca97cd0 100644 --- a/buzz/widgets/main_window.py +++ b/buzz/widgets/main_window.py @@ -425,7 +425,7 @@ class MainWindow(QMainWindow): self.transcriber_worker.stop() self.transcriber_thread.quit() - self.transcriber_thread.wait() + self.transcriber_thread.wait(5000) # Wait up to 5 seconds if self.transcription_viewer_widget is not None: self.transcription_viewer_widget.close() diff --git a/buzz/widgets/recording_transcriber_widget.py b/buzz/widgets/recording_transcriber_widget.py index b336121b..80ae166d 100644 --- a/buzz/widgets/recording_transcriber_widget.py +++ b/buzz/widgets/recording_transcriber_widget.py @@ -624,6 +624,10 @@ class RecordingTranscriberWidget(QWidget): if self.translator is not None: self.translator.stop() + if self.translation_thread is not None: + self.translation_thread.quit() + self.translation_thread.wait(35_000) # Wait up to 35 seconds + self.settings.set_value( Settings.Key.RECORDING_TRANSCRIBER_LANGUAGE, self.transcription_options.language, diff --git a/buzz/widgets/transcription_viewer/transcription_viewer_widget.py b/buzz/widgets/transcription_viewer/transcription_viewer_widget.py index 5b9abeab..ba53226a 100644 --- a/buzz/widgets/transcription_viewer/transcription_viewer_widget.py +++ b/buzz/widgets/transcription_viewer/transcription_viewer_widget.py @@ -1348,7 +1348,7 @@ class TranscriptionViewerWidget(QWidget): self.translator.stop() self.translation_thread.quit() - self.translation_thread.wait() + self.translation_thread.wait(35_000) # Wait up to 35 seconds, translation thread also has timeouts, wait longer super().closeEvent(event) diff --git a/pytest.ini b/pytest.ini index ad52348a..b1ef248a 100644 --- a/pytest.ini +++ b/pytest.ini @@ -5,5 +5,7 @@ qt_api=pyqt6 log_format = %(asctime)s %(levelname)s %(module)s::%(funcName)s %(message)s log_date_format = %Y-%m-%d %H:%M:%S addopts = -x +timeout = 600 +timeout_method = thread markers = timeout: set a timeout on a test function. \ No newline at end of file diff --git a/tests/cli_test.py b/tests/cli_test.py index 9bd077d1..7887acf3 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -20,7 +20,7 @@ class TestCLI: "--task", "transcribe", "--model-size", - "small", + "tiny", "--output-directory", mkdtemp(), "--txt", diff --git a/tests/translator_test.py b/tests/translator_test.py index 56db2fc3..6c0f87d6 100644 --- a/tests/translator_test.py +++ b/tests/translator_test.py @@ -13,7 +13,7 @@ from buzz.widgets.transcriber.advanced_settings_dialog import AdvancedSettingsDi class TestTranslator: @patch('buzz.translator.OpenAI', autospec=True) @patch('buzz.translator.queue.Queue', autospec=True) - def test_start(self, mock_queue, mock_openai): + def test_start(self, mock_queue, mock_openai, qtbot): def side_effect(*args, **kwargs): side_effect.call_count += 1 @@ -106,11 +106,11 @@ class TestTranslator: if self.translator is not None: self.translator.stop() - self.translator.deleteLater() if self.translation_thread is not None: self.translation_thread.quit() - self.translation_thread.deleteLater() + # Wait for the thread to actually finish before cleanup + self.translation_thread.wait() - # Wait to clean-up threads - time.sleep(3) + # Note: translator and translation_thread will be automatically deleted + # via the deleteLater() connections set up earlier diff --git a/tests/widgets/export_transcription_menu_test.py b/tests/widgets/export_transcription_menu_test.py index 7c15f1c4..30a735be 100644 --- a/tests/widgets/export_transcription_menu_test.py +++ b/tests/widgets/export_transcription_menu_test.py @@ -32,7 +32,7 @@ class TestExportTranscriptionMenu: file=test_audio_path, task=Task.TRANSCRIBE.value, model_type=ModelType.WHISPER.value, - whisper_model_size=WhisperModelSize.SMALL.value, + whisper_model_size=WhisperModelSize.TINY.value, ) ) transcription_segment_dao.insert(TranscriptionSegment(40, 299, "Bien", "", str(id))) diff --git a/tests/widgets/transcription_viewer/transcription_segments_editor_widget_test.py b/tests/widgets/transcription_viewer/transcription_segments_editor_widget_test.py index 5e4fab68..ac8036a9 100644 --- a/tests/widgets/transcription_viewer/transcription_segments_editor_widget_test.py +++ b/tests/widgets/transcription_viewer/transcription_segments_editor_widget_test.py @@ -289,7 +289,7 @@ class TestTranscriptionSegmentsEditorWidget: file=test_audio_path, task=Task.TRANSCRIBE.value, model_type=ModelType.WHISPER.value, - whisper_model_size=WhisperModelSize.SMALL.value, + whisper_model_size=WhisperModelSize.TINY.value, ) ) transcription_segment_dao.insert( diff --git a/tests/widgets/transcription_viewer/transcription_viewer_widget_additional_test.py b/tests/widgets/transcription_viewer/transcription_viewer_widget_additional_test.py index cb1ceb66..8d34460c 100644 --- a/tests/widgets/transcription_viewer/transcription_viewer_widget_additional_test.py +++ b/tests/widgets/transcription_viewer/transcription_viewer_widget_additional_test.py @@ -32,7 +32,7 @@ class TestTranscriptionViewerWidgetAdditional: file=test_audio_path, task=Task.TRANSCRIBE.value, model_type=ModelType.WHISPER.value, - whisper_model_size=WhisperModelSize.SMALL.value, + whisper_model_size=WhisperModelSize.TINY.value, ) ) transcription_segment_dao.insert( diff --git a/tests/widgets/transcription_viewer_test.py b/tests/widgets/transcription_viewer_test.py index ebc5ac01..13d87bc8 100644 --- a/tests/widgets/transcription_viewer_test.py +++ b/tests/widgets/transcription_viewer_test.py @@ -42,7 +42,7 @@ class TestTranscriptionViewerWidget: file=test_audio_path, task=Task.TRANSCRIBE.value, model_type=ModelType.WHISPER.value, - whisper_model_size=WhisperModelSize.SMALL.value, + whisper_model_size=WhisperModelSize.TINY.value, ) ) transcription_segment_dao.insert(TranscriptionSegment(40, 299, "Bien", "", str(id)))