Views
No views yet
npm i @huggingface/transformers1import { pipeline } from '@huggingface/transformers';
2
3const tts = await pipeline('text-to-speech', 'onnx-community/Supertonic-TTS-ONNX');
4
5const input_text = 'This is really cool!';
6const audio = await tts(input_text, {
7 speaker_embeddings: 'https://huggingface.co/onnx-community/Supertonic-TTS-ONNX/resolve/main/voices/F1.bin',
8 num_inference_steps: 5, // Higher = better quality (typically 1-50)
9 speed: 1.05, // Higher = faster speech (typically 0.8-1.2)
10});
11await audio.save('output.wav'); // or `audio.toBlob()`;SupertonicTTS:1import os
2import numpy as np
3import onnxruntime as ort
4from transformers import AutoTokenizer
5
6class SupertonicTTS:
7 SAMPLE_RATE = 44100
8 CHUNK_COMPRESS_FACTOR = 6
9 BASE_CHUNK_SIZE = 512
10 LATENT_DIM = 24
11 STYLE_DIM = 128
12 LATENT_SIZE = BASE_CHUNK_SIZE * CHUNK_COMPRESS_FACTOR
13
14 def __init__(self, model_path):
15 self.model_path = model_path
16 self.tokenizer = AutoTokenizer.from_pretrained(self.model_path)
17
18 # Load ONNX sessions
19 self.text_encoder = ort.InferenceSession(os.path.join(self.model_path, "onnx", "text_encoder.onnx"))
20 self.latent_denoiser = ort.InferenceSession(os.path.join(self.model_path, "onnx", "latent_denoiser.onnx"))
21 self.voice_decoder = ort.InferenceSession(os.path.join(self.model_path, "onnx", "voice_decoder.onnx"))
22
23 def _load_style(self, voice: str) -> np.ndarray:
24 voice_path = os.path.join(self.model_path, "voices", f"{voice}.bin")
25 if not os.path.exists(voice_path):
26 raise ValueError(f"Voice '{voice}' not found.")
27
28 style_vec = np.fromfile(voice_path, dtype=np.float32)
29 return style_vec.reshape(1, -1, self.STYLE_DIM)
30
31 def generate(self, text: list[str], *, voice: str = "M1", speed: float = 1.0, steps: int = 5) -> list[np.ndarray]:
32 # 1. Prepare Text Inputs
33 inputs = self.tokenizer(text, return_tensors="np", padding=True, truncation=True)
34 input_ids = inputs["input_ids"]
35 attn_mask = inputs["attention_mask"]
36 batch_size = input_ids.shape[0]
37
38 # 2. Prepare Style
39 style = self._load_style(voice).repeat(batch_size, axis=0)
40
41 # 3. Text Encoding
42 last_hidden_state, raw_durations = self.text_encoder.run(
43 None,
44 {"input_ids": input_ids, "attention_mask": attn_mask, "style": style}
45 )
46 durations = (raw_durations / speed * self.SAMPLE_RATE).astype(np.int64)
47
48 # 4. Latent Preparation
49 latent_lengths = (durations + self.LATENT_SIZE - 1) // self.LATENT_SIZE
50 max_len = latent_lengths.max()
51 latent_mask = (np.arange(max_len) < latent_lengths[:, None]).astype(np.int64)
52 latents = np.random.randn(batch_size, self.LATENT_DIM * self.CHUNK_COMPRESS_FACTOR, max_len).astype(np.float32)
53 latents *= latent_mask[:, None, :]
54
55 # 5. Denoising Loop
56 num_inference_steps = np.full(batch_size, steps, dtype=np.float32)
57 for step in range(steps):
58 timestep = np.full(batch_size, step, dtype=np.float32)
59 latents = self.latent_denoiser.run(
60 None,
61 {
62 "noisy_latents": latents,
63 "latent_mask": latent_mask,
64 "style": style,
65 "encoder_outputs": last_hidden_state,
66 "attention_mask": attn_mask,
67 "timestep": timestep,
68 "num_inference_steps": num_inference_steps,
69 },
70 )[0]
71
72 # 6. Decode Latents to Audio
73 waveforms = self.voice_decoder.run(None, {"latents": latents})[0]
74
75 # 7. Post-process: Trim padding and return list of arrays
76 results = []
77 for i, length in enumerate(latent_mask.sum(axis=1) * self.LATENT_SIZE):
78 results.append(waveforms[i, :length])
79
80 return resultsgit clone, huggingface_hub, etc.)1# (Optional) Download model files (or use existing local directory)
2from huggingface_hub import snapshot_download
3model_id = "onnx-community/Supertonic-TTS-ONNX"
4local_dir = "supertonic"
5snapshot_download(model_id, local_dir=local_dir)1# Initialize TTS
2tts = SupertonicTTS(local_dir)
3
4# Generate audio
5prompts = [
6 "Once upon a time, there was a brave knight.",
7 "Refactoring code makes it much easier to read!",
8 "I love this!"
9]
10audio_data = tts.generate(prompts, voice="M1", speed=1.0, steps=10)
11
12# (Optional) Save to files
13import soundfile as sf
14for i, audio in enumerate(audio_data):
15 filename = f"output_{i}.wav"
16 sf.write(filename, audio, tts.SAMPLE_RATE)
17 print(f"Saved {filename}")