KittenTTS module. - #1107
Conversation
…issue when processing text over 400 char. Fix an issue when we get unmapped chars.
sthibaul
left a comment
There was a problem hiding this comment.
Thanks for the nice work!
In the future, we will probably want to integrate various onnx-based voices, so code will be useful to share between modules, but your writing seems already quite well structured so that it will be convenient to do.
There are just a few changes that need to happen before we can integrate this.
There was a problem hiding this comment.
I believe this is best to be handled by package managers instead?
As models update, we don't want to frequently update and recompile this as downstream packages might lag behind for years.
There was a problem hiding this comment.
Also all the download links are outside of this project's control. Which means that we won't be able to fix a broken download until a new release is packaged by distributions and shipped to the end user (which as commented, might be months/years after).
There was a problem hiding this comment.
I believe this is best to be handled by package managers
It already checks if the models/voices are in the path /usr/share/speech-dispatcher/models/kitten and uses that path first. If the package manger placed them there, then they will get used.
we won't be able to fix a broken download until a new release
I have added the ability to set the download configuration through the models dot conf file.
Here is an example dot conf on how to do that https://gist.github.com/jsett/6146eb2803f8780a1830ed816bdc94ef
There was a problem hiding this comment.
I believe this is best to be handled by package managers
It already checks if the models/voices are in the path
/usr/share/speech-dispatcher/models/kittenand uses that path first. If the package manger placed them there, then they will get used.
I'm afraid distribution would not organize their packages this way.
Like piper, kitten models are general purpose in the sense of the Text-to-Speech task. If we take example from piper, the AUR packages place the models into /usr/share/piper-voices/, because their use are not limited to speech-dispatcher, and the distributions would not want to package multiple copies of large model files just for different applications to use.
It is also likely that different distributions wouldn't come to agreement on where these models should be placed. So the distribution packagers would adjust the conf default to accommodate their packaging schemes.
I believe this is best to be handled by package managers instead?
Nevertheless, I personally wouldn't expect program like speech-dispatcher (as a daemon process) to make network requests (and I strongly believe that we should learn from the log4shell disaster where a logging library contains the code path to make network requests) . So adding this to me feels like a scope creep that I would like to push against, as indicated by the first time linking with libcurl.
There was a problem hiding this comment.
/usr/share/speech-dispatcher was recommended in the comments above, but I really don't have any real issue changing it if that what is decided.
code path to make network requests
I'm not opposed to removing the downloader. But there is a trade off here. If you remove it you increase the complexity for users to get things working, if there distro did not include the models with the install. I would be interested in hearing what other people think.
There was a problem hiding this comment.
Turning the downloader into a one-off script might not be a bad idea
That could be an idea yes. People installing speech-dispatcher by hand would use it, and distribution people would package the voices. People could still use the script to update the voices.
Again, if only upstream voices providers could manage these questions instead of just throwing .onnx files at people...
There could simply be a voice downloading manager, even independent from speech-dispatcher, that manages updates and whatnot, and speech-dispatcher would just happen to see the voice files show up, and use them.
There was a problem hiding this comment.
upstream of these models could simply document where these are supposed to be shipped
Unfortunately I don't think hugging face models have a way of doing this currently.
There was a problem hiding this comment.
Based off the above comments, I think this is what I am going to do.
With regards to the downloader.
-
Remove the downloader from the speechd module.
-
Create a separate script outside speechd code that has the downloader (this will likely be in python).
-
Add documentation on how to use the downloader.
With regards to the search path for the distro's.
-
Search if the models are in
~/.cache/speech-dispatcher/kitten(for user provided models). -
Check if a path is provided in the module's .conf file. Something like a line for
modelsPath "<path>"distro's then should be able to place the models where ever they desire and add a line in the conf file.
There was a problem hiding this comment.
upstream of these models could simply document where these are supposed to be shipped
Unfortunately I don't think hugging face models have a way of doing this currently.
It would really just be a matter of documenting it in README or website or whatever, nothing fancy...
There was a problem hiding this comment.
I made all those changes in the latest commit.
|
bleh, "ubuntu-latest" doesn't seem to really be "latest", the CI is taking 24.04 rather than 26.04... Let me see that |
Could you rebase? I have bumped to 26.04 so onnxruntime is available. |
|
You need to add |
- The downloaded has been moved to a seperate package, documentation has been added on how to use the downloader. - modules dot conf file can now set the models+voices search path.
| [kitten_libxml="yes"], | ||
| [AS_IF([test $with_kitten = "yes"], | ||
| [AC_MSG_FAILURE([libxml-2.0 is not available])])]) | ||
| AS_IF([test "x$kitten_libonnxruntime" = "xyes" -a "x$kitten_libxml" = "xyes" -a "x$kitten_libcurl" = "xyes"], |
There was a problem hiding this comment.
You need to drop the libcurl condition, and you can drop it from the github workflow
There was a problem hiding this comment.
I must have over looked that. Interesting that it did not cause my ./configure to fail.
There was a problem hiding this comment.
./configure is meant to avoid failing unless the user explicitly requested --enable-kitten
sthibaul
left a comment
There was a problem hiding this comment.
we're getting close :)
| @@ -0,0 +1,23 @@ | |||
| # Module conf file options. | |||
There was a problem hiding this comment.
Please rather put an example configuration file, otherwise it will be too hard for users to work out what it should look like. You can then stuff this information in the example configuration file.
There was a problem hiding this comment.
Really, rather put the information of README.kitten.md in the configuration file example. That's the best way that users will see it and know how to configure it. Otherwise distributions will at worse not install the readme file, at best put it in /usr/share/doc/speech-dispatcher, where users won't find it, and be at a loss when trying to configure /etc/speech-dispatcher/config/kitten.conf
| @@ -0,0 +1,23 @@ | |||
| # Module conf file options. | |||
|
|
|||
| The modules dot conf file can be used to configure the module using `AddVoiceFile` and `modelPath`. `AddVoiceFile` let you set models/voices in the case of updated models. `modelPath` let you set the modes/voices search path. | |||
There was a problem hiding this comment.
You can set the model in the example file to /usr/share/kitten, to give people an idea where the files should be put as a distribution (to be shared with other software using kitten models)
There was a problem hiding this comment.
I updated the readme with examples.
|
|
||
| static const configoption_t options[] = { | ||
| {"AddVoiceFile", ARG_LIST, cb_voicefiles, NULL, CTX_ALL}, | ||
| {"modelPath", ARG_STR, cb_modelPath, NULL, CTX_ALL}, |
There was a problem hiding this comment.
Better add a Debug option, like the other modules, and make use of MSG and DBG instead of always printing to stderr, so people don't have a log file growly a lot, but can still easily add debugging output when something goes wrong and you need information from the execution on the user machine to investigate.
There was a problem hiding this comment.
I'm confused on what we are talking about here. Are we talking about replacing the fprintf(stderr, functions(there in quite a few locations) with MSG/DBG. Or is this something that is added to the dot conf stuff?
There was a problem hiding this comment.
yes, and add a Debug dot conf option that sets the Debug variable, that the MSG/DBG calls will use to determine whether they should actually print their content or not. That is very convenient to get users to provide debugging information easily
|
The CI said: This indeed should rather be a |
|
The CI also said: The xml header mentions that one should rather use |
…to the logs - Fixed depr warning with libxml content and use - Fixed potental bug that could happen if the phonemizer failed to load
KittenTTS Module.
This is a speech dispatch model for running Kitten TTS. Kitten TTS is a deep learning model which provides high quality natural sounding TTS generation using models ranging from 15M to 80M parameters. Due to its small size it is able to run in real-time on CPU. The goal of this project is to integrate Kitten TTS with speech dispatch while maintaining its near real-time speech generation, with special attention being place on reading of long text's such as ebooks. To achieve this the original python code was rewrote into c and tightly integrated into a speech dispatch model.
There is a lot here so let me give a quick summary of what all is going on here.
kitten_server.c:
This file is for handling the protocol and follows some what closely to the example modules for async servers with speech dispatch handling the audio. By design I made sure very little work is done in any function in this thread. Any long running code should be handed to an async queue and ran on one of the threads in the kitten_worker.c file.
kitten_worker.c:
This is where the handling of long running tasks is done. We create two different threads here one to one to handle passing audio back to the server(since the module_tts_output_server function can block and we want the generation to continue while we are outputting audio to the server). The other thread is dedicated to the generation of audio by the model. We synchronize all this using two GasyncQueue, one for handling incoming speak requests, and the other to handle the outputted audio from our model. we also keep track of how much audio we have generated and played so that long speak commands don't run the cpu unnecessarily hard (For example I have seen that Okular will in some cases send an entire book's text in a single speak command). There is also code here for parsing ssml text using libxml.
kitten_model.c:
The handles everything we need to do to generated output from onnx using our model. The most important functions here are init_voice_style to handle loading voice styles. reload_models_and_voices: to handle changing the voice style. And kitten_speak for generating audio.
kitten_downloader.c:
This handles downloading the model+voice styles if its not already on our computer. If it download it does verify the file against a sha256, but that verification is not strongly enforce and is more of a warning.