-
Notifications
You must be signed in to change notification settings - Fork 261
Kokoro usage improvements #4357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
michalkulakowski
wants to merge
10
commits into
main
Choose a base branch
from
mkulakow/kokoro_improvements
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
05aaa8e
Kokoro usage improvements
michalkulakowski 31d1840
adjust uts
michalkulakowski 2ba854d
update docs
michalkulakowski 26997dc
fix
michalkulakowski 9f72de1
fix
michalkulakowski 62a67a0
Docs fixes
michalkulakowski 01ea5b4
fixes
michalkulakowski 6a3dfe4
fix
michalkulakowski 683c50d
TMP
michalkulakowski 8ed0835
Use Kokoro int8 TTS artifacts in UT model prep
michalkulakowski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,116 +8,80 @@ Check supported [Speech Recognition Models](https://openvinotoolkit.github.io/op | |
|
|
||
| ## Prerequisites | ||
|
|
||
| **OVMS version 2025.4** This demo require version 2025.4 or nightly release. | ||
|
|
||
| **Model preparation**: Python 3.10 or higher with pip | ||
| **OVMS version 2026.3** This demo require version 2026.3 or nightly release. | ||
|
|
||
| **Model Server deployment**: Installed Docker Engine or OVMS binary package according to the [baremetal deployment guide](../../docs/deploying_server_baremetal.md) | ||
|
|
||
| **Client**: curl or Python for using OpenAI client package | ||
|
|
||
| ## Speech generation | ||
| ### Prepare speaker embeddings | ||
| When generating speech you can use default speaker voice or you can prepare your own speaker embedding file. Here you can see how to do it with downloaded file from online repository, but you can try with your own speech recording as well: | ||
| ```console | ||
| pip install -r https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/main/demos/audio/requirements.txt | ||
| mkdir audio_samples | ||
| curl --create-dirs "https://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0032_8k.wav" -o audio_samples/audio.wav | ||
| curl --create-dirs https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/main/demos/audio/create_speaker_embedding.py -o models/speakers/create_speaker_embedding.py | ||
| python models/speakers/create_speaker_embedding.py audio_samples/audio.wav models/speakers/voice1.bin | ||
| ``` | ||
|
|
||
| Kokoro is the primary example in this demo, but SpeechT5 remains supported for existing deployments. | ||
| ### Model preparation | ||
| Supported models should use the topology of [microsoft/speecht5_tts](https://huggingface.co/microsoft/speecht5_tts) which needs to be converted to IR format before using in OVMS. | ||
|
|
||
| Specific OVMS pull mode example for models requiring conversion is described in the [Ovms pull mode](../../docs/pull_hf_models.md#pulling-models-outside-openvino-organization) | ||
|
|
||
| Or you can use the python export_model.py script described below. | ||
|
|
||
| Here, the original Text to Speech model will be converted to IR format and optionally quantized. | ||
| That ensures faster initialization time, better performance and lower memory consumption. | ||
| Execution parameters will be defined inside the `graph.pbtxt` file. | ||
|
|
||
| Download export script, install it's dependencies and create directory for the models: | ||
| ```console | ||
| curl https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/main/demos/common/export_models/export_model.py -o export_model.py | ||
| pip install -r https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/main/demos/common/export_models/requirements.txt | ||
| mkdir models | ||
| ``` | ||
|
|
||
| Run `export_model.py` script to download and quantize the model: | ||
|
|
||
| > **Note:** The users in China need to set environment variable HF_ENDPOINT="https://hf-mirror.com" before running the export script to connect to the HF Hub. | ||
| > **Note:** Exporting `microsoft/speecht5_tts` model requires Python 3.10 | ||
|
|
||
| **CPU** | ||
| ```console | ||
| python export_model.py text2speech --source_model microsoft/speecht5_tts --weight-format fp16 --model_name microsoft/speecht5_tts --config_file_path models/config.json --model_repository_path models --overwrite_models --vocoder microsoft/speecht5_hifigan --speaker_name voice1 --speaker_path models/speakers/voice1.bin | ||
| ``` | ||
| This demo uses a pre-exported OpenVINO IR model [luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS](https://huggingface.co/luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS) available on HuggingFace. | ||
| The model can be pulled directly by OVMS without any conversion step. | ||
|
|
||
| > **Note:** Change the `--weight-format` to quantize the model to `int8` precision to reduce memory consumption and improve performance. | ||
| > **Note:** `speaker_name` and `speaker_path` may be omitted if the default model voice is sufficient | ||
| > **Note:** The users in China need to set environment variable HF_ENDPOINT="https://hf-mirror.com" before starting OVMS to connect to the HF Hub. | ||
| > **Note:** Kokoro voices are loaded from the `voices/` directory in the model repository and can be selected per request with the `voice` field. | ||
|
|
||
| The default configuration should work in most cases but the parameters can be tuned via `export_model.py` script arguments. Run the script with `--help` argument to check available parameters and see the [T2s calculator documentation](../../docs/speech_generation/reference.md) to learn more about configuration options and limitations. | ||
| See the [T2s calculator documentation](../../docs/speech_generation/reference.md) to learn more about configuration options and limitations. | ||
|
|
||
| ### Deployment | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there should be included option for deployment on GPU and NPU |
||
|
|
||
| :::{dropdown} **Deploying with Docker** | ||
|
|
||
| **CPU** | ||
|
|
||
| Running this command starts the container with CPU only target device: | ||
| Running this command starts the container with CPU target device: | ||
| ```bash | ||
| mkdir -p models | ||
| docker run -d -u $(id -u):$(id -g) --rm -p 8000:8000 -v $(pwd)/models:/models:rw openvino/model_server:latest --rest_port 8000 --model_path /models/microsoft/speecht5_tts --model_name microsoft/speecht5_tts | ||
| mkdir models | ||
| docker run -d -u $(id -u):$(id -g) --rm -p 8000:8000 -v $(pwd)/models:/models:rw openvino/model_server:latest --rest_port 8000 --source_model luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS --model_repository_path /models --model_name Kokoro-82M-OpenVINO-FP16-OVMS --target_device CPU --task text2speech | ||
| ``` | ||
|
|
||
| **Deploying on Bare Metal** | ||
| **GPU** | ||
|
|
||
| ```bat | ||
| In case you want to use GPU device, add extra docker parameters `--device /dev/dri --group-add=$(stat -c "%g" /dev/dri/render* | head -n 1)` and use the GPU image: | ||
| ```bash | ||
| mkdir models | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on windows it's better to use c:\models |
||
| ovms --rest_port 8000 --model_path models/microsoft/speecht5_tts --model_name microsoft/speecht5_tts | ||
| docker run -d -u $(id -u):$(id -g) --rm -p 8000:8000 --device /dev/dri --group-add=$(stat -c "%g" /dev/dri/render* | head -n 1) -v $(pwd)/models:/models:rw openvino/model_server:latest-gpu --rest_port 8000 --source_model luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS --model_repository_path /models --model_name Kokoro-82M-OpenVINO-FP16-OVMS --target_device GPU --task text2speech | ||
| ``` | ||
|
|
||
| ### Request Generation | ||
|
|
||
| :::{dropdown} **Unary call with curl with default voice** | ||
|
|
||
| **NPU** | ||
|
|
||
| In case you want to use NPU device, add extra docker parameters `--device /dev/accel --group-add=$(stat -c "%g" /dev/dri/render* | head -n 1)` and use the GPU image: | ||
| ```bash | ||
| curl http://localhost:8000/v3/audio/speech -H "Content-Type: application/json" -d "{\"model\": \"microsoft/speecht5_tts\", \"input\": \"The quick brown fox jumped over the lazy dog\"}" -o speech.wav | ||
| mkdir models | ||
| docker run -d -u $(id -u):$(id -g) --rm -p 8000:8000 --device /dev/accel --group-add=$(stat -c "%g" /dev/dri/render* | head -n 1) -v $(pwd)/models:/models:rw openvino/model_server:latest-gpu --rest_port 8000 --source_model luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS --model_repository_path /models --model_name Kokoro-82M-OpenVINO-FP16-OVMS --target_device NPU --task text2speech | ||
| ``` | ||
| ::: | ||
|
|
||
| :::{dropdown} **Unary call with OpenAI python library with default voice** | ||
|
|
||
| ```python | ||
| from pathlib import Path | ||
| from openai import OpenAI | ||
|
|
||
| prompt = "The quick brown fox jumped over the lazy dog" | ||
| filename = "speech.wav" | ||
| url="http://localhost:8000/v3" | ||
|
|
||
|
|
||
| speech_file_path = Path(__file__).parent / "speech.wav" | ||
| client = OpenAI(base_url=url, api_key="not_used") | ||
| :::{dropdown} **Deploying on Bare Metal** | ||
|
|
||
| with client.audio.speech.with_streaming_response.create( | ||
| model="microsoft/speecht5_tts", | ||
| voice=None, | ||
| input=prompt | ||
| ) as response: | ||
| response.stream_to_file(speech_file_path) | ||
| **CPU** | ||
| ```bat | ||
| mkdir c:\models | ||
| ovms --rest_port 8000 --source_model luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS --model_repository_path c:\models --model_name Kokoro-82M-OpenVINO-FP16-OVMS --target_device CPU | ||
| ``` | ||
|
|
||
| **GPU** | ||
| ```bat | ||
| mkdir c:\models | ||
| ovms --rest_port 8000 --source_model luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS --model_repository_path c:\models --model_name Kokoro-82M-OpenVINO-FP16-OVMS --target_device GPU | ||
| ``` | ||
|
|
||
| print("Generation finished") | ||
| **NPU** | ||
| ```bat | ||
| mkdir c:\models | ||
| ovms --rest_port 8000 --source_model luis-castillo/Kokoro-82M-OpenVINO-FP16-OVMS --model_repository_path c:\models --model_name Kokoro-82M-OpenVINO-FP16-OVMS --target_device NPU | ||
| ``` | ||
| ::: | ||
|
|
||
| ### Request Generation | ||
|
|
||
| :::{dropdown} **Unary call with curl** | ||
|
|
||
|
|
||
| ```bash | ||
| curl http://localhost:8000/v3/audio/speech -H "Content-Type: application/json" -d "{\"model\": \"microsoft/speecht5_tts\", \"voice\":\"voice1\", \"input\": \"The quick brown fox jumped over the lazy dog\"}" -o speech.wav | ||
| curl http://localhost:8000/v3/audio/speech -H "Content-Type: application/json" -d "{\"model\": \"Kokoro-82M-OpenVINO-FP16-OVMS\", \"voice\": \"af_alloy\", \"input\": \"The quick brown fox jumped over the lazy dog\"}" -o speech.wav | ||
| ``` | ||
| ::: | ||
|
|
||
|
|
@@ -136,8 +100,8 @@ speech_file_path = Path(__file__).parent / "speech.wav" | |
| client = OpenAI(base_url=url, api_key="not_used") | ||
|
|
||
| with client.audio.speech.with_streaming_response.create( | ||
| model="microsoft/speecht5_tts", | ||
| voice="voice1", | ||
| model="Kokoro-82M-OpenVINO-FP16-OVMS", | ||
| voice="af_alloy", | ||
| input=prompt | ||
| ) as response: | ||
| response.stream_to_file(speech_file_path) | ||
|
|
@@ -152,20 +116,25 @@ Play speech.wav file to check generated speech. | |
| ## Benchmarking speech generation | ||
| An asynchronous benchmarking client can be used to access the model server performance with various load conditions. Below are execution examples captured on Intel(R) Core(TM) Ultra 7 258V. | ||
|
|
||
| > **Note:** `RTFx` (Real-Time Factor, inverted) is calculated as `generated_audio_duration / generation_time`. | ||
| > Values greater than `1.0x` mean faster-than-real-time generation, while values below `1.0x` mean slower-than-real-time. | ||
|
|
||
| ```console | ||
| pip install -r https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/main/demos/benchmark/v3/requirements.txt | ||
| curl https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/main/demos/benchmark/v3/benchmark.py -o benchmark.py | ||
| python benchmark.py --api_url http://localhost:8000/v3/audio/speech --model microsoft/speecht5_tts --batch_size 1 --limit 100 --request_rate inf --backend text2speech --dataset edinburghcstr/ami --hf-subset ihm --tokenizer openai/whisper-large-v3-turbo --trust-remote-code True | ||
| Number of documents: 100 | ||
| 100%|████████████████████████████████████████████████████████████████████████████████| 100/100 [01:58<00:00, 1.19s/it] | ||
| Tokens: 1802 | ||
| Success rate: 100.0%. (100/100) | ||
| Throughput - Tokens per second: 15.2 | ||
| Mean latency: 63653.98 ms | ||
| Median latency: 66736.83 ms | ||
| Average document length: 18.02 tokens | ||
| pip install -r https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/mkulakow/kokoro_improvements/demos/benchmark/v3/requirements.txt | ||
| curl https://raw.githubusercontent.com/openvinotoolkit/model_server/refs/heads/mkulakow/kokoro_improvements/demos/benchmark/v3/benchmark.py -o benchmark.py | ||
| python benchmark.py --api_url http://localhost:8000/v3/audio/speech --model Kokoro-82M-OpenVINO-FP16-OVMS --batch_size 1 --limit 100 --request_rate inf --backend text2speech --dataset edinburghcstr/ami --hf-subset ihm --voice af_alloy | ||
| Number of documents: 1000 | ||
|
Comment on lines
+123
to
+126
|
||
| 100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [15:53<00:00, 1.05it/s] | ||
| Success rate: 100.0%. (1000/1000) | ||
| Mean latency: 742.48 ms | ||
| Median latency: 662.10 ms | ||
| Mean RTFx: 5.091x | ||
| Median RTFx: 5.173x | ||
| ``` | ||
|
|
||
| > **Note:** `RTFx` (Real-Time Factor, inverted) is calculated as `generated_audio_duration / generation_time`. | ||
| > Values greater than `1.0x` mean faster-than-real-time generation, while values below `1.0x` mean slower-than-real-time. | ||
|
|
||
| ## Transcription | ||
| ### Model preparation | ||
| Many variances of Whisper models can be deployed in a single command by using pre-configured models from [OpenVINO HuggingFace organization](https://huggingface.co/collections/OpenVINO/speech-to-text) and used both for translations and transcriptions endpoints. | ||
|
|
@@ -235,7 +204,7 @@ ovms --rest_port 8000 --model_path /models/openai/whisper-large-v3-turbo --model | |
| The default configuration should work in most cases but the parameters can be tuned via `export_model.py` script arguments. Run the script with `--help` argument to check available parameters and see the [s2t calculator documentation](../../docs/speech_recognition/reference.md) to learn more about configuration options and limitations. | ||
|
|
||
| ### Request Generation | ||
| Transcript file that was previously generated with audio/speech endpoint. | ||
| Transcribe the speech.wav file generated in the [Speech generation](#speech-generation) section. | ||
|
|
||
| > **Note:** Streaming responses are supported for `audio/transcriptions`. `audio/translations` does not support streaming. | ||
|
|
||
|
|
@@ -360,33 +329,13 @@ Average document length: 10.948 tokens | |
| ``` | ||
|
|
||
| ## Translation | ||
| To test translations endpoint we first need to prepare audio file with speech in language other than English, e.g. Spanish. To generate such sample we will use finetuned version of microsoft/speecht5_tts model. | ||
|
|
||
| **Deploying with Docker** | ||
| To test the translations endpoint we first need to prepare an audio file with speech in a language other than English, e.g. Spanish. To generate such a sample, follow the [Speech generation](#speech-generation) section to deploy Kokoro and then run: | ||
|
|
||
| ```bash | ||
| mkdir -p models | ||
|
|
||
| python export_model.py text2speech --source_model Sandiago21/speecht5_finetuned_facebook_voxpopuli_spanish --weight-format fp16 --model_name speecht5_tts_spanish --config_file_path models/config.json --model_repository_path models --overwrite_models --vocoder microsoft/speecht5_hifigan | ||
|
|
||
| docker run -d -u $(id -u):$(id -g) --rm -p 8000:8000 -v $(pwd)/models:/models:rw openvino/model_server:latest --rest_port 8000 --model_path /models/speecht5_tts_spanish --model_name speecht5_tts_spanish | ||
|
|
||
| curl http://localhost:8000/v3/audio/speech -H "Content-Type: application/json" -d "{\"model\": \"speecht5_tts_spanish\", \"input\": \"Madrid es la capital de España\"}" -o speech_spanish.wav | ||
| ``` | ||
|
|
||
| **Deploying on Bare Metal** | ||
|
|
||
| ```bat | ||
| mkdir models | ||
|
|
||
| python export_model.py text2speech --source_model Sandiago21/speecht5_finetuned_facebook_voxpopuli_spanish --weight-format fp16 --model_name speecht5_tts_spanish --config_file_path models/config.json --model_repository_path models --overwrite_models --vocoder microsoft/speecht5_hifigan | ||
|
|
||
| ovms --rest_port 8000 --model_path models/speecht5_tts_spanish --model_name speecht5_tts_spanish | ||
|
|
||
| curl http://localhost:8000/v3/audio/speech -H "Content-Type: application/json" -d "{\"model\": \"speecht5_tts_spanish\", \"input\": \"Madrid es la capital de España\"}" -o speech_spanish.wav | ||
| ```console | ||
| curl http://localhost:8000/v3/audio/speech -H "Content-Type: application/json" -d "{\"model\": \"Kokoro-82M-OpenVINO-FP16-OVMS\", \"voice\": \"em_alex\", \"input\": \"Madrid es la capital de España\"}" -o speech_spanish.wav | ||
| ``` | ||
|
|
||
| ### Model preparation | ||
| ### Deployment | ||
| Whisper models can be deployed in a single command by using pre-configured models from [OpenVINO HuggingFace organization](https://huggingface.co/collections/OpenVINO/speech-to-text) and used both for translations and transcriptions endpoints. | ||
| Here is an example of OpenVINO/whisper-large-v3-fp16-ov deployment: | ||
|
|
||
|
|
@@ -427,7 +376,7 @@ ovms --rest_port 8000 --source_model OpenVINO/whisper-large-v3-fp16-ov --model_r | |
| ::: | ||
|
|
||
| ### Request Generation | ||
| Transcript and translate file that was previously generated with audio/speech endpoint. | ||
| Translate the speech_spanish.wav file generated above. | ||
|
|
||
| :::{dropdown} **Unary call with cURL** | ||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add also a note in building from src doc with info that espeek is optional and can be delete from the package if not needed. explain the consequences - which language is supported without it