Use extra thread for transcription to not block UI

This commit is contained in:
mesonium
2024-06-11 19:16:46 +02:00
committed by hueso
parent 5579cd6bfd
commit 6667e01304

View File

@@ -20,7 +20,7 @@ from functools import partial
from pathlib import Path
import whisper
from gi.repository import Gtk
from gi.repository import Gio, GObject, Gtk
from stt_voice_messages.config_dialog import STTVoiceMessagesConfigDialog
from gajim.plugins import GajimPlugin
@@ -69,12 +69,12 @@ class STTBox(Gtk.Box):
audio_file: Path,
) -> None:
print('FOO')
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=12)
self._config = config
self._preview_audio = preview_audio_widget
self._audio_file = audio_file
self._text = ''
self._transcribe_button = Gtk.Button(label=_('Transcribe'))
@@ -89,20 +89,69 @@ class STTBox(Gtk.Box):
self.show_all()
def _on_transcribe_clicked(self, _button: Gtk.Button):
text = self._trascribe_by_whisper()
if text.strip() != '':
self._transcription_label.set_text(text.strip())
transcription_task = BackgroundTask(
self._trascribe_by_whisper,
self._show_result
)
transcription_task.start()
def _show_result(self):
if self._text.strip() != '':
self._transcription_label.set_text(self._text.strip())
else:
self._transcription_label.set_text(_('_Have not heard any word!_'))
def _trascribe_by_whisper(self) -> str:
model = whisper.load_model(self._config['model_size'])
result = model.transcribe(self._audio_file)
text = result["text"]
self._text = result["text"]
return text
'''
https://discourse.gnome.org/t/gtk-threading-problem-with-glib-idle-add/13597/5
https://github.com/gdm-settings/gdm-settings/blob/f245d3000200fa6be2a35c7f6ac45b131dadb5d6/src/utils.py#L116..L162
'''
class BackgroundTask (GObject.Object):
__gtype_name__ = 'BackgroundTask'
def __init__ (self, function, finish_callback, **kwargs):
super().__init__(**kwargs)
self.function = function
self.finish_callback = finish_callback
self._current = None
def start(self):
if self._current:
AlreadyRunningError('Task is already running')
finish_callback = lambda self, task, nothing: self.finish_callback()
task = Gio.Task.new(self, None, finish_callback, None)
task.run_in_thread(self._thread_cb)
self._current = task
@staticmethod
def _thread_cb (task, self, task_data, cancellable):
try:
retval = self.function()
task.return_value(retval)
except Exception as e:
task.return_value(e)
def finish (self):
task = self._current
self._current = None
if not Gio.Task.is_valid(task, self):
raise InvalidGioTaskError()
value = task.propagate_value().value
if isinstance(value, Exception):
raise value
return value