GarreTTS is a TTS synthesizer which uses plugin-provided synthesizers. You can make plugins for it, so it can use your preferred synthesizer.
This project is my first attempt to use Qt5 and plugins.
Plugins have a very simple interface. You provide a function which accepts a string of text to be synthesized. You should return the binary contents of an audio file in whatever format you like (though MP3 is likely to be the most compatible).
def my_synthesizer(user_text: str) -> BinaryIO: ...
Plugins are registered with a decorator you can import from this
...register(name=...) allows you to provide a custom name, if you
from garretts import Plugin @Plugin.register(name="My very fancy Mario voice") def my_synthesizer(user_text: str) -> BinaryIO: ...
The only method for asking a user for input is via files.
The package provides a way to store and access any file/data you may
garretts.plugin_file(file: str) accepts the name of your
file and hands you a
pathlib.Path to its expected location. I do
not ensure that it exists or that its contents are appropriate.
from garretts import plugin_file PEACH = "another_castle.txt" @Plugin.register(name="My very fancy Mario voice") def my_synthesizer(user_text: str) -> BinaryIO: peach_file = plugin_file(PEACH) ...
This package provides a
garretts.PluginFileMissing exception which
can be raised when you need to be given some data. Its arguments
include the name of the file, a prompt to be shown to the user, and a
caption for the file picker window. The user will be shown your prompt
before being asked to pick their file.
from garretts import PluginFileMissing ... if not peach_file.exists(): user_prompt = "You must tell me which castle peach is in!" picker_caption = "Which castle?" raise PluginFileMissing(PEACH, user_prompt, picker_caption) ...
When you raise this error, it will cancel the current synthesizer attempt. After selecting a file, the user will try synthesizing again.
If you need to
refresh a file, or have data which is no longer
valid, you should use
PluginFileMissing to prompt the user for a
new version. The currently existing file will be overwritten.
This package provides a
garretts.PluginError. If your plugin has an
error, you should catch it and raise a PluginError for the user to
read. Uncaught errors will be presented to the user and then crash
from garretts import PluginError ... try: scary_operation() except ScaryOperationFailure as e: raise PluginError(e.message) ...