Downloads · 30 days
84
49% of all-time downloads
square-zero-labs/Supertonic-TTS-ONNX
Supertonic-TTS-ONNX is a text-to-speech model from square-zero-labs. Use it when you need text read aloud. It is set up for transformers.js. The card lists the license as openrail.
If you haven't already, you can install the Transformers.js JavaScript library from NPM using:
Downloads · 30 days
84
49% of all-time downloads
All-time downloads
171
Public
Repo size
263 MB
Likes
0
Public
Click a slice to open those files.
.onnx_data262 MB · 99%
From the Hugging Face model README
If you haven't already, you can install the Transformers.js JavaScript library from NPM using:
npm i @huggingface/transformers
You can then generate audio as follows:
import { pipeline } from '@huggingface/transformers';
const tts = await pipeline('text-to-speech', 'onnx-community/Supertonic-TTS-ONNX');
const input_text = 'This is really cool!';
const audio = await tts(input_text, {
speaker_embeddings: 'https://huggingface.co/onnx-community/Supertonic-TTS-ONNX/resolve/main/voices/F1.bin',
num_inference_steps: 5, // Higher = better quality (typically 1-50)
speed: 1.05, // Higher = faster speech (typically 0.8-1.2)
});
await audio.save('output.wav'); // or `audio.toBlob()`;
First, let's create a helper class, SupertonicTTS:
import os
import numpy as np
import onnxruntime as ort
from transformers import AutoTokenizer
class SupertonicTTS:
SAMPLE_RATE = 44100
CHUNK_COMPRESS_FACTOR = 6
BASE_CHUNK_SIZE = 512
LATENT_DIM = 24
STYLE_DIM = 128
LATENT_SIZE = BASE_CHUNK_SIZE * CHUNK_COMPRESS_FACTOR
def __init__(self, model_path):
self.model_path = model_path
self.tokenizer = AutoTokenizer.from_pretrained(self.model_path)
# Load ONNX sessions
self.text_encoder = ort.InferenceSession(os.path.join(self.model_path, "onnx", "text_encoder.onnx"))
self.latent_denoiser = ort.InferenceSession(os.path.join(self.model_path, "onnx", "latent_denoiser.onnx"))
self.voice_decoder = ort.InferenceSession(os.path.join(self.model_path, "onnx", "voice_decoder.onnx"))
def _load_style(self, voice: str) -> np.ndarray:
voice_path = os.path.join(self.model_path, "voices", f"{voice}.bin")
if not os.path.exists(voice_path):
raise ValueError(f"Voice '{voice}' not found.")
style_vec = np.fromfile(voice_path, dtype=np.float32)
return style_vec.reshape(1, -1, self.STYLE_DIM)
def generate(self, text: list[str], *, voice: str = "M1", speed: float = 1.0, steps: int = 5) -> list[np.ndarray]:
# 1. Prepare Text Inputs
inputs = self.tokenizer(text, return_tensors="np", padding=True, truncation=True)
input_ids = inputs["input_ids"]
attn_mask = inputs["attention_mask"]
batch_size = input_ids.shape[0]
# 2. Prepare Style
style = self._load_style(voice).repeat(batch_size, axis=0)
# 3. Text Encoding
last_hidden_state, raw_durations = self.text_encoder.run(
None,
{"input_ids": input_ids, "attention_mask": attn_mask, "style": style}
)
durations = (raw_durations / speed * self.SAMPLE_RATE).astype(np.int64)
# 4. Latent Preparation
latent_lengths = (durations + self.LATENT_SIZE - 1) // self.LATENT_SIZE
max_len = latent_lengths.max()
latent_mask = (np.arange(max_len) < latent_lengths[:, None]).astype(np.int64)
latents = np.random.randn(batch_size, self.LATENT_DIM * self.CHUNK_COMPRESS_FACTOR, max_len).astype(np.float32)
latents *= latent_mask[:, None, :]
# 5. Denoising Loop
num_inference_steps = np.full(batch_size, steps, dtype=np.float32)
for step in range(steps):
timestep = np.full(batch_size, step, dtype=np.float32)
latents = self.latent_denoiser.run(
None,
{
"noisy_latents": latents,
"latent_mask": latent_mask,
"style": style,
"encoder_outputs": last_hidden_state,
"attention_mask": attn_mask,
"timestep": timestep,
"num_inference_steps": num_inference_steps,
},
)[0]
# 6. Decode Latents to Audio
waveforms = self.voice_decoder.run(None, {"latents": latents})[0]
# 7. Post-process: Trim padding and return list of arrays
results = []
for i, length in enumerate(latent_mask.sum(axis=1) * self.LATENT_SIZE):
results.append(waveforms[i, :length])
return results
Next, we clone this repository (using whichever way you want, git clone, huggingface_hub, etc.)
# (Optional) Download model files (or use existing local directory)
from huggingface_hub import snapshot_download
model_id = "onnx-community/Supertonic-TTS-ONNX"
local_dir = "supertonic"
snapshot_download(model_id, local_dir=local_dir)
We can then use the model as follows:
# Initialize TTS
tts = SupertonicTTS(local_dir)
# Generate audio
prompts = [
"Once upon a time, there was a brave knight.",
"Refactoring code makes it much easier to read!",
"I love this!"
]
audio_data = tts.generate(prompts, voice="M1", speed=1.0, steps=10)
# (Optional) Save to files
import soundfile as sf
for i, audio in enumerate(audio_data):
filename = f"output_{i}.wav"
sf.write(filename, audio, tts.SAMPLE_RATE)
print(f"Saved {filename}")