Speech Generation
Speech generation supports multiple model families, including SpeechT5, Kokoro, and Qwen3-TTS. The generated audio signal is a single-channel (mono) waveform, and the sampling rate depends on the model (for example, SpeechT5 outputs 16 kHz and Qwen3-TTS outputs 24 kHz).
Convert and Optimize Model
Download and convert model (for example, speecht5_tts) to OpenVINO format from Hugging Face.
The command below uses SpeechT5 as an example; SpeechT5 requires specifying a vocoder via --model-kwargs:
optimum-cli export openvino --model microsoft/speecht5_tts --weight-format int4 --model-kwargs '{"vocoder":"microsoft/speecht5_hifigan"}' speecht5_tts
See all supported Speech Generation Models.
Refer to the Model Preparation guide for detailed instructions on how to download, convert and optimize models for OpenVINO GenAI.
Run Model Using OpenVINO GenAI
The Text2SpeechPipeline is the main object for generating speech from text.
It automatically loads the TTS model and vocoder from the converted model directory.
The output sample rate is model-dependent and is returned in the generation result.
- Python
- C++
- C
- JavaScript
- CPU
- GPU
import openvino_genai
import numpy as np
import soundfile as sf
pipeline = openvino_genai.Text2SpeechPipeline(model_path, "CPU")
generation_config = pipeline.get_generation_config()
# Generate audio using the default speaker
result = pipeline.generate("Hello OpenVINO GenAI", generation_config=generation_config)
# speech tensor contains the waveform of the spoken phrase
speech_data = np.array(result.speeches[0].data).reshape(-1)
sf.write("output_audio.wav", speech_data, samplerate=result.output_sample_rate)
import openvino_genai
import numpy as np
import soundfile as sf
pipeline = openvino_genai.Text2SpeechPipeline(model_path, "GPU")
generation_config = pipeline.get_generation_config()
# Generate audio using the default speaker
result = pipeline.generate("Hello OpenVINO GenAI", generation_config=generation_config)
# speech tensor contains the waveform of the spoken phrase
speech_data = np.array(result.speeches[0].data).reshape(-1)
sf.write("output_audio.wav", speech_data, samplerate=result.output_sample_rate)
- CPU
- GPU
#include "audio_utils.hpp"
#include "openvino/genai/speech_generation/text2speech_pipeline.hpp"
int main(int argc, char* argv[]) {
std::string models_path = argv[1];
ov::genai::Text2SpeechPipeline pipeline(models_path, "CPU");
ov::genai::SpeechGenerationConfig generation_config = pipeline.get_generation_config();
auto result = pipeline.generate("Hello OpenVINO GenAI", ov::Tensor{}, generation_config);
auto waveform_size = result.speeches[0].get_size();
auto waveform_ptr = result.speeches[0].data<const float>();
auto bits_per_sample = result.speeches[0].get_element_type().bitwidth();
utils::audio::save_to_wav(waveform_ptr, waveform_size, "output_audio.wav", bits_per_sample);
return 0;
}
#include "audio_utils.hpp"
#include "openvino/genai/speech_generation/text2speech_pipeline.hpp"
int main(int argc, char* argv[]) {
std::string models_path = argv[1];
ov::genai::Text2SpeechPipeline pipeline(models_path, "GPU");
ov::genai::SpeechGenerationConfig generation_config = pipeline.get_generation_config();
auto result = pipeline.generate("Hello OpenVINO GenAI", ov::Tensor{}, generation_config);
auto waveform_size = result.speeches[0].get_size();
auto waveform_ptr = result.speeches[0].data<const float>();
auto bits_per_sample = result.speeches[0].get_element_type().bitwidth();
utils::audio::save_to_wav(waveform_ptr, waveform_size, "output_audio.wav", bits_per_sample);
return 0;
}
- CPU
- GPU
#include <stdint.h>
#include <stdio.h>
#include "openvino/genai/c/text2speech_pipeline.h"
int main(int argc, char** argv) {
if (argc != 2) return 1;
ov_genai_text2speech_pipeline* pipeline = NULL;
ov_genai_speech_generation_config* config = NULL;
ov_genai_text2speech_decoded_results* results = NULL;
ov_tensor_t* speech = NULL;
FILE* output = NULL;
int status = 1;
if (ov_genai_text2speech_pipeline_create(argv[1], "CPU", 0, &pipeline) != OK ||
ov_genai_text2speech_pipeline_get_generation_config(pipeline, &config) != OK ||
ov_genai_text2speech_pipeline_generate(pipeline, "Hello OpenVINO GenAI", NULL, config, &results) != OK ||
ov_genai_text2speech_decoded_results_get_speech_at(results, 0, &speech) != OK)
goto cleanup;
size_t sample_count = 0;
uint32_t sample_rate = 0;
void* samples = NULL;
if (ov_tensor_get_size(speech, &sample_count) != OK ||
ov_tensor_data(speech, &samples) != OK ||
ov_genai_text2speech_decoded_results_get_output_sample_rate(results, &sample_rate) != OK)
goto cleanup;
output = fopen("speech.f32", "wb");
if (!output || fwrite(samples, sizeof(float), sample_count, output) != sample_count)
goto cleanup;
printf("Saved %zu float32 samples at %u Hz\n", sample_count, sample_rate);
status = 0;
cleanup:
if (output) fclose(output);
ov_tensor_free(speech);
ov_genai_text2speech_decoded_results_free(results);
ov_genai_speech_generation_config_free(config);
ov_genai_text2speech_pipeline_free(pipeline);
return status;
}
#include <stdint.h>
#include <stdio.h>
#include "openvino/genai/c/text2speech_pipeline.h"
int main(int argc, char** argv) {
if (argc != 2) return 1;
ov_genai_text2speech_pipeline* pipeline = NULL;
ov_genai_speech_generation_config* config = NULL;
ov_genai_text2speech_decoded_results* results = NULL;
ov_tensor_t* speech = NULL;
FILE* output = NULL;
int status = 1;
if (ov_genai_text2speech_pipeline_create(argv[1], "GPU", 0, &pipeline) != OK ||
ov_genai_text2speech_pipeline_get_generation_config(pipeline, &config) != OK ||
ov_genai_text2speech_pipeline_generate(pipeline, "Hello OpenVINO GenAI", NULL, config, &results) != OK ||
ov_genai_text2speech_decoded_results_get_speech_at(results, 0, &speech) != OK)
goto cleanup;
size_t sample_count = 0;
uint32_t sample_rate = 0;
void* samples = NULL;
if (ov_tensor_get_size(speech, &sample_count) != OK ||
ov_tensor_data(speech, &samples) != OK ||
ov_genai_text2speech_decoded_results_get_output_sample_rate(results, &sample_rate) != OK)
goto cleanup;
output = fopen("speech.f32", "wb");
if (!output || fwrite(samples, sizeof(float), sample_count, output) != sample_count)
goto cleanup;
printf("Saved %zu float32 samples at %u Hz\n", sample_count, sample_rate);
status = 0;
cleanup:
if (output) fclose(output);
ov_tensor_free(speech);
ov_genai_text2speech_decoded_results_free(results);
ov_genai_speech_generation_config_free(config);
ov_genai_text2speech_pipeline_free(pipeline);
return status;
}
- CPU
- GPU
import { writeFile } from 'node:fs/promises';
import { Text2SpeechPipeline } from 'openvino-genai-node';
import { encode } from 'node-wav';
const pipeline = await Text2SpeechPipeline(modelPath, "CPU");
const result = await pipeline.generate("Hello OpenVINO GenAI");
const sampleRate = Number(result.outputSampleRate ?? result.output_sample_rate ?? 16000);
const wavData = encode([result.speeches[0].data], { sampleRate });
await writeFile("output_audio.wav", wavData);
import { writeFile } from 'node:fs/promises';
import { Text2SpeechPipeline } from 'openvino-genai-node';
import { encode } from 'node-wav';
const pipeline = await Text2SpeechPipeline(modelPath, "GPU");
const result = await pipeline.generate("Hello OpenVINO GenAI");
const sampleRate = Number(result.outputSampleRate ?? result.output_sample_rate ?? 16000);
const wavData = encode([result.speeches[0].data], { sampleRate });
await writeFile("output_audio.wav", wavData);
Use CPU or GPU as devices without any other code change.
Additional Usage Options
Use Speaker Embedding File
To generate speech using the SpeechT5 model, you can specify a target voice by providing a speaker embedding file.
This file must contain 512 32-bit floating-point values that represent the voice characteristics of the target speaker. The model will use these characteristics to synthesize the input text in the specified voice.
If no speaker embedding is provided, the model uses the default built-in speaker.
You can generate a speaker embedding using the create_speaker_embedding.py script. This script records 5 seconds of audio from your microphone and extracts a speaker embedding vector from the recording.
python create_speaker_embedding.py
- Python
- C++
- C
- JavaScript
import openvino_genai
import openvino as ov
import numpy as np
import soundfile as sf
pipeline = openvino_genai.Text2SpeechPipeline(model_path, "CPU")
speaker_embedding = np.fromfile(args.speaker_embedding_file_path, dtype=np.float32).reshape(1, 512)
speaker_embedding = ov.Tensor(speaker_embedding)
result = pipeline.generate("Hello OpenVINO GenAI", speaker_embedding)
speech = result.speeches[0]
sf.write("output_audio.wav", speech.data[0], samplerate=result.output_sample_rate)
#include "openvino/genai/speech_generation/text2speech_pipeline.hpp"
#include "audio_utils.hpp"
int main(int argc, char* argv[]) {
std::string model_path = argv[1];
ov::genai::Text2SpeechPipeline pipeline(model_path, "CPU");
auto speaker_embedding = utils::audio::read_speaker_embedding(speaker_embedding_path);
auto result = pipeline.generate("Hello OpenVINO GenAI", speaker_embedding);
auto waveform_size = result.speeches[0].get_size();
auto waveform_ptr = result.speeches[0].data<const float>();
auto bits_per_sample = result.speeches[0].get_element_type().bitwidth();
utils::audio::save_to_wav(waveform_ptr, waveform_size, "output_audio.wav", bits_per_sample);
return 0;
}
text2speech_c MODEL_DIR "Hello OpenVINO GenAI" SPEAKER_EMBEDDING.bin output_audio.wav --device CPU
import { writeFile } from 'node:fs/promises';
import { Text2SpeechPipeline } from 'openvino-genai-node';
import { encode } from 'node-wav';
import { readSpeakerEmbedding } from './embedding_utils.js';
const pipeline = await Text2SpeechPipeline(modelPath, "CPU");
const speakerEmbedding = await readSpeakerEmbedding(embeddingPath);
const result = await pipeline.generate(
"Hello OpenVINO GenAI",
{ speakerEmbedding },
);
const sampleRate = Number(result.outputSampleRate ?? result.output_sample_rate ?? 16000);
const wavData = encode([result.speeches[0].data], { sampleRate });
await writeFile("output_audio.wav", wavData);
Performance Metrics
Text2SpeechPipeline returns Text2SpeechDecodedResults with a perf_metrics field of type SpeechGenerationPerfMetrics, which extends PerfMetrics.
In addition to common metrics, SpeechGenerationPerfMetrics provides:
| Metric | Type | Description |
|---|---|---|
num_generated_samples | integer | Number of audio samples generated |