From 6b6fcf6e5a266e891762bfa5d8c9ce6539cce54b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 27 Sep 2024 16:10:26 +0530 Subject: [PATCH] Support headless voice download --- src/calibre/gui2/tts/download.py | 18 ++++++++++++++++++ src/calibre/gui2/tts/piper.py | 17 ++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/calibre/gui2/tts/download.py b/src/calibre/gui2/tts/download.py index 1c8eaeaad4..0778351c0e 100644 --- a/src/calibre/gui2/tts/download.py +++ b/src/calibre/gui2/tts/download.py @@ -162,6 +162,24 @@ class DownloadResources(QDialog): super().reject() +def download_resources( + title: str, message: str, urls: dict[str, tuple[str, str]], parent: QWidget | None = None, headless: bool = False +) -> bool: + if not headless: + d = DownloadResources(title, message, urls, parent=parent) + return d.exec() == QDialog.DialogCode.Accepted + from calibre import browser + print(title) + print(message) + for url, (path, name) in urls.items(): + print(_('Downloading {}...').format(name)) + br = browser() + data = br.open_novisit(url).read() + with open(path, 'wb') as f: + f.write(data) + return True + + def develop(): from calibre.gui2 import Application app = Application([]) diff --git a/src/calibre/gui2/tts/piper.py b/src/calibre/gui2/tts/piper.py index c6144838c1..1b30308c6a 100644 --- a/src/calibre/gui2/tts/piper.py +++ b/src/calibre/gui2/tts/piper.py @@ -13,11 +13,11 @@ from itertools import count from time import monotonic from qt.core import ( + QApplication, QAudio, QAudioFormat, QAudioSink, QByteArray, - QDialog, QIODevice, QIODeviceBase, QMediaDevices, @@ -469,14 +469,13 @@ class Piper(TTSBackend): if not download_even_if_exists: return model_path, config_path os.makedirs(os.path.dirname(model_path), exist_ok=True) - from calibre.gui2.tts.download import DownloadResources - d = DownloadResources(_('Downloading voice for Read aloud'), _('Downloading neural network for the {} voice').format(voice.human_name), { - voice.engine_data['model_url']: (model_path, _('Neural network data')), - voice.engine_data['config_url']: (config_path, _('Neural network metadata')), - }, parent=widget_parent(self)) - if d.exec() == QDialog.DialogCode.Accepted: - return model_path, config_path - return '', '' + from calibre.gui2.tts.download import download_resources + ok = download_resources(_('Downloading voice for Read aloud'), _('Downloading neural network for the {} voice').format(voice.human_name), { + voice.engine_data['model_url']: (model_path, _('Neural network data')), + voice.engine_data['config_url']: (config_path, _('Neural network metadata')), + }, parent=widget_parent(self), headless=getattr(QApplication.instance(), 'headless', False) + ) + return (model_path, config_path) if ok else ('', '') def download_voice(self, v: Voice) -> None: if not v.name: