voidful commited on
Commit
63e7bc2
·
verified ·
1 Parent(s): aa8d376

Update BlueMagpie-TTS checkpoint step_0006000

Browse files

Upload inference-only BlueMagpie-TTS step_0006000 checkpoint.

Includes model weights, AudioVAE weights, tokenizer files, sanitized config, model card, usage guide, and release metadata.
Deletes remote speaker-centroid artifacts under checkpoints/ so no experimental speaker tables are shipped.

.gitattributes CHANGED
@@ -1,5 +1,2 @@
1
  *.bin filter=lfs diff=lfs merge=lfs -text
2
  *.pth filter=lfs diff=lfs merge=lfs -text
3
- checkpoints/hung_yi_lee_speaker_centroids.pt filter=lfs diff=lfs merge=lfs -text
4
- assets/icon.png filter=lfs diff=lfs merge=lfs -text
5
- assets/social-preview.png filter=lfs diff=lfs merge=lfs -text
 
1
  *.bin filter=lfs diff=lfs merge=lfs -text
2
  *.pth filter=lfs diff=lfs merge=lfs -text
 
 
 
README.md CHANGED
@@ -1,325 +1,130 @@
1
- # BlueMagpie-TTS
2
-
3
- <p align="center">
4
- <img src="assets/icon.png" alt="OpenFormosa Blue Magpie TTS" width="260">
5
- </p>
6
-
7
- BlueMagpie-TTS是一套文字轉語音(TTS)模型,能把文字合成為自然的語音。它支援三種使用情境:
8
-
9
- - **一般語音合成** —— 直接把文字唸出來。
10
- - **聲音複製** —— 提供一段參考音檔,讓輸出模仿該語者的音色。
11
- - **指定語者** —— 用事先準備好的語者向量來控制音色。
 
12
 
13
- 同時也提供**串流輸出**,適合需要邊合成邊播放的應用。
14
 
15
- 🔊 **線上試玩**:[BlueMagpie-TTS Demo(Hugging Face Space)](https://huggingface.co/spaces/voidful/BlueMagpie-TTS-Demo)
16
 
17
- ## 命名由來
 
 
 
18
 
19
- 專案全名是 **OpenFormosa Blue Magpie TTS**。「藍鵲」取自**台灣藍鵲**(Taiwan Blue Magpie,學名 *Urocissa caerulea*)。選牠作為 TTS 的識別有幾層用意:
20
- - **會發聲、辨識度高**:台灣藍鵲本來就是叫聲響亮、容易辨認的鳥,恰好呼應 TTS「把文字變成聲音」的核心。
21
- - **長尾的動態感**:標誌性的長尾巴帶來流動、延展的視覺意象,比一般的喇叭 icon 更有記憶點與品牌個性。
22
- - **立足台灣**:OpenFormosa(福爾摩沙)點出專案面向台灣華語、在地化語音的定位。
23
 
24
- ## 安裝
 
 
 
 
25
 
26
- 先把專案 clone 下來,再以可編輯模式安裝:
27
 
28
  ```bash
29
- git clone https://github.com/OpenFormosa/BlueMagpie-TTS
30
  cd BlueMagpie-TTS
31
- pip install -e .
32
- ```
33
-
34
- 安裝過程會自動從 GitHub 取得相依的 [`barbet`](https://github.com/OpenFormosa/Barbet) 套件(負責文字語意的語言模型)。語音合成所需的聲學模組已內含於專案中(位於 `bluemagpie/_vendor/`,原始碼取自 [VoxCPM](https://github.com/OpenBMB/VoxCPM),採 Apache-2.0 授權),不需另外安裝。
35
-
36
- 若要儲存合成出來的音檔,建議另外安裝 `soundfile`:
37
-
38
- ```bash
39
- pip install soundfile
40
  ```
41
 
42
- ## 載入模型
43
-
44
- ### 從 Hugging Face 下載
45
 
46
  ```python
47
- import os
48
  from huggingface_hub import snapshot_download
49
- from transformers import PreTrainedTokenizerFast
50
- from bluemagpie import BlueMagpieModel
51
-
52
- model_dir = snapshot_download("OpenFormosa/BlueMagpie-TTS", token=True)
53
- # 直接從 tokenizer.json 載入 tokenizer,相容較新版 transformers(5.x)
54
- tokenizer = PreTrainedTokenizerFast(tokenizer_file=os.path.join(model_dir, "tokenizer.json"))
55
- model = BlueMagpieModel.from_local(model_dir, tokenizer=tokenizer, training=False, device="cuda")
56
- ```
57
-
58
- ### 從本機目錄載入
59
-
60
- 如果你已經有一份模型檔案,直接指向該目錄即可:
61
 
62
- ```python
63
- import os
64
- from transformers import PreTrainedTokenizerFast
65
  from bluemagpie import BlueMagpieModel
66
 
67
- model_dir = "checkpoints/bluemagpie"
68
- tokenizer = PreTrainedTokenizerFast(tokenizer_file=os.path.join(model_dir, "tokenizer.json"))
69
- model = BlueMagpieModel.from_local(model_dir, tokenizer=tokenizer, training=False, device="cuda")
70
- ```
71
-
72
- - `device` 可填 `"cuda"` 或 `"cpu"`,不指定時會自動選擇。
73
- - 推論時請固定使用 `training=False`。
74
-
75
- ## 基本使用:文字轉語音
76
-
77
- `generate` 會回傳一段語音波形(`torch.Tensor`),搭配 `soundfile` 即可存成 `.wav`。輸出的取樣率可由 `model.sample_rate` 取得:
78
-
79
- ```python
80
- import soundfile as sf
81
 
82
  audio = model.generate(
83
- target_text="今天天氣真好。",
 
84
  cfg_value=2.0,
 
 
85
  )
86
 
87
- sf.write("output.wav", audio.squeeze().cpu().numpy(), model.sample_rate)
88
  ```
89
 
90
- ## 聲音複製:模仿參考語者的音色
91
-
92
- 有兩種做法。
93
-
94
- **A. 語者向量(`speaker_centroid`)** —— 從參考音檔抽出語者向量再合成(免逐字稿):
95
-
96
- ```bash
97
- pip install -e ".[clone]" # 抽取需要 speechbrain(ECAPA-TDNN)
98
- python scripts/extract_speaker_centroid.py --audio reference.wav --out my_voice.pt
99
- # 多段同一語者更穩定:--audio a.wav b.wav c.wav
100
- ```
101
-
102
- ```python
103
- import torch
104
-
105
- centroid = torch.load("my_voice.pt", weights_only=True) # [192] 語者向量
106
- audio = model.generate(
107
- target_text="今天天氣真好。",
108
- speaker_centroid=centroid,
109
- cfg_value=2.8,
110
- )
111
-
112
- # 也可以在程式中直接抽取(不寫檔):
113
- from bluemagpie import extract_speaker_centroid
114
- centroid = extract_speaker_centroid("reference.wav") # [192]
115
- ```
116
-
117
- **B. 參考音檔(`reference_wav_path`)** —— 直接提供一段參考音檔:
118
 
119
  ```python
 
120
  audio = model.generate(
121
- target_text="今天天氣真好。",
122
- reference_wav_path="reference.wav",
123
- cfg_value=2.8,
124
- )
125
- ```
126
-
127
- ## 指定語者:以語者向量控制音色
128
-
129
- 模型自帶一個**多語者向量表** `checkpoints/speaker_centroids.pt`,目前內含兩個語者:
130
-
131
- | 語者 ID | 說明 | 建議 `cfg_value` |
132
- | --- | --- | --- |
133
- | `hung_yi_lee` | 李宏毅(Hung-yi Lee)老師的語者向量(已取得本人授權;官方最佳參數即針對此語者調校) | 2.0–2.8 |
134
- | `female_voice` | 一個通用女聲語者向量 | 2.0–2.8 |
135
-
136
- 向量表的格式為 `{"speaker_ids": [...], "centroids": tensor[N, 192], "dim": 192}`。以 `torch.load` 載入後,**依語者 ID 取出該語者的 `[192]` 向量**,再透過 `speaker_centroid` 指定音色:
137
-
138
- ```python
139
- import os
140
- import torch
141
-
142
- table = torch.load(
143
- os.path.join(model_dir, "checkpoints", "speaker_centroids.pt"),
144
- map_location="cpu",
145
- weights_only=True,
146
  )
147
- print(table["speaker_ids"]) # ['hung_yi_lee', 'female_voice']
148
-
149
- # 切換語者只要改這一行("hung_yi_lee" 或 "female_voice")
150
- speaker_id = "female_voice"
151
- speaker_centroid = table["centroids"][table["speaker_ids"].index(speaker_id)] # [192]
152
 
 
153
  audio = model.generate(
154
- target_text="今天天氣真好。",
155
- speaker_centroid=speaker_centroid, # 也可以直接傳入你自己已取得授權的語者向量
156
  cfg_value=2.0,
 
157
  )
158
- ```
159
-
160
- 只用模型 ID(尚未先 `snapshot_download` 整個模型)時,可單獨抓向量表這一個檔:
161
 
162
- ```python
163
- from huggingface_hub import hf_hub_download
164
-
165
- path = hf_hub_download("OpenFormosa/BlueMagpie-TTS", "checkpoints/speaker_centroids.pt")
166
- table = torch.load(path, map_location="cpu", weights_only=True)
167
- ```
168
-
169
- > 想新增更多語者,用上方〈聲音複製〉的 `extract_speaker_centroid` 抽出你自己(已取得授權)的 `[192]` 向量即可,傳法完全相同。早期僅含李宏毅單一語者的 `checkpoints/hung_yi_lee_speaker_centroids.pt`(格式相同)仍保留可用。
170
-
171
- ## 串流輸出
172
-
173
- 需要邊合成邊播放時,改用 `generate_streaming`。它是一個產生器,會一段一段地回傳音訊區塊:
174
-
175
- ```python
176
- chunks = []
177
- for chunk in model.generate_streaming(target_text="今天天氣真好。"):
178
- chunks.append(chunk)
179
- # 這裡可以即時播放或寫出 chunk
180
  ```
181
 
182
- > 注意:串流模式下不支援自動重試(`retry_badcase`)。
183
-
184
- ## 四種輸入模式
185
-
186
- 模型支援四種輸入組合,皆透過同一個 `generate` 介面切換:
187
-
188
- | 模式 | 需要的參數 | 用途 |
189
- |---|---|---|
190
- | 一般合成 | `target_text` | 直接把文字唸出來 |
191
- | 語音接續 | `target_text`、`prompt_text`、`prompt_wav_path` | 從一段已有的語音與其文字接著往下唸 |
192
- | 參考音檔 | `target_text`、`reference_wav_path` | 模仿參考音檔的語者音色 |
193
- | 語者向量 | `target_text`、`speaker_centroid` | 以語者向量複製音色 |
194
-
195
- ## `generate` 常用參數
196
-
197
- | 參數 | 預設值 | 說明 |
198
- |---|---|---|
199
- | `target_text` | (必填) | 要合成的文字 |
200
- | `prompt_text` | `""` | 提示文字,搭配 `prompt_wav_path` 做語音接續 |
201
- | `prompt_wav_path` | `""` | 提示音檔路徑,用於語音接續 |
202
- | `reference_wav_path` | `""` | 參考音檔路徑,用於聲音複製 |
203
- | `speaker_centroid` | `None` | 語者向量,用於指定音色 |
204
- | `cfg_value` | `2.0` | 引導強度,數值越大越貼合條件、但可能較不自然 |
205
- | `inference_timesteps` | `10` | 取樣步數,越多通常品質越好、速度越慢 |
206
- | `min_len` / `max_len` | `2` / `2000` | 輸出長度的下限與上限 |
207
- | `retry_badcase` | `False` | 偵測到異常輸出時自動重試(串流模式不支援) |
208
-
209
- ## 批次推論引擎(多請求加速)
210
-
211
- 若你要同時處理多筆合成請求、追求更高吞吐量,可改用內建的批次推論引擎 `BlueMagpieEngine`。它採用**連續批次**(continuous batching):多筆請求會一起批次解碼,新請求能在解碼途中加入,彼此互不影響。
212
 
213
- 引擎的特點:
214
 
215
- - **不需額外相依套件**:只用到 `torch`,不必安裝 vLLM、flash-attn 等套件。
216
- - **跨裝置**:CUDA、Apple Silicon(MPS)、CPU 共用同一套程式碼;CUDA 專屬的最佳化會自動偵測並啟用,其餘裝置自動略過。
217
- - **與單筆 `generate` 數值一致**:在 batch=1 時,輸出與 `model.generate` 逐值相同(`model.generate` 始終是對照基準)。
218
 
219
- ### 基本用法
220
-
221
- ```python
222
- import soundfile as sf
223
- from bluemagpie.serving import BlueMagpieEngine, EngineConfig, Request
224
-
225
- # model 與 tokenizer 的載入方式同前(from_local)
226
- engine = BlueMagpieEngine(model, EngineConfig(max_num_seqs=16))
227
-
228
- engine.add_request(Request(target_text="今天天氣真好。", seed=0))
229
- engine.add_request(Request(target_text="第二句話。", reference_wav_path="speaker.wav"))
230
-
231
- for out in engine.run(): # 依請求加入順序回傳
232
- # out.audio:48 kHz 波形(已掛載 AudioVAE 時);out.latents:潛在表徵 [T, p, d]
233
- sf.write(f"output_{out.request_id}.wav", out.audio.numpy(), out.sample_rate)
234
- ```
235
-
236
- `Request` 支援與 `generate` 相同的四種輸入模式(一般合成、語音接續、參考音檔、語者向量),欄位對應 `target_text`、`prompt_text`、`prompt_wav_path`、`reference_wav_path`、`speaker_centroid`、`cfg_value`、`inference_timesteps` 等。每筆請求可給定 `seed`,使該請求的輸出與同批其他請求的數量、加入順序無關。
237
-
238
- ### 串流輸出
239
-
240
- `engine.stream()` 是一個產生器,會在每一步逐筆回傳各請求的區塊:
241
-
242
- ```python
243
- for chunk in engine.stream():
244
- # chunk.request_id、chunk.latents、chunk.audio、chunk.finished
245
- play_or_write(chunk)
246
- ```
247
 
248
- > 一般合成、參考音檔、語者向量這三種模式會回傳串流音訊(`chunk.audio`);語音接續模式目前只回傳 `latents`,需要音訊時請改用 `run()`。
 
249
 
250
- ### 設定
 
 
 
 
251
 
252
- `EngineConfig` 常用參數:
253
 
254
- | 參數 | 預設值 | 說明 |
255
- |---|---|---|
256
- | `max_num_seqs` | `16` | 同時批次處理的最大請求數 |
257
- | `max_model_len` | `2048` | 每筆序列的最大長度(提示+生成) |
258
- | `inference_timesteps` | `9` | 取樣步數 |
259
- | `cfg_value` | `2.8` | 引導強度 |
260
- | `enforce_eager` | `True` | 維持與單筆 `generate` 數值一致的路徑 |
261
- | `compile` | `False` | 啟用 `torch.compile`(僅 CUDA 有效,其餘裝置自動略過) |
262
 
263
- > 引擎的設計、取捨與已知限制詳見 [`src/bluemagpie/serving/DESIGN.md`](src/bluemagpie/serving/DESIGN.md)。
264
 
265
- ### 加速原理:為什麼不是直接套 vLLM?
 
 
 
 
 
 
266
 
267
- 很多人期待「用 vLLM 之類的框架就能加速」,但對 BlueMagpie 來說,直接套 vLLM 並不可行,原因有二:
268
-
269
- 1. **真正的運算瓶頸不在語言模型,而在擴散式解碼器。** 每生成一個音訊單元,DiT(擴散式解碼器 LocDiT/CFM)要被呼叫約 16–18 次(取樣步數 × 無條件/有條件兩路),而語言模型(Barbet、RALM)各只跑一次。vLLM 是**文字語言模型**的推論框架,它根本不處理擴散式解碼器——就算把語言模型搬到 vLLM,主要運算量仍是 eager 執行,端到端不會明顯變快。
270
- 2. **vLLM 不支援 Barbet 的混合架構。** BlueMagpie 的語意語言模型 Barbet 是 Mamba2 與注意力的混合模型,vLLM(以及 nano-vllm、vllm-omni)對這種混合 TSLM 是零支援,得自行實作一個 first-class 混合模型才跑得起來,工程量大且僅限 CUDA。
271
-
272
- 因此本引擎改採**借用 vLLM 的架構技術、但不依賴它的 CUDA 套件**的做法:
273
-
274
- - **連續批次**處理多請求(吞吐量的主要來源),跨請求共用批次運算。
275
- - 以 **padded KV cache + SDPA + 遮罩**取代 vLLM 的 PagedAttention/FlashAttention,換取跨裝置、零依賴(代價是單一運算略慢、記憶體較不精省)。
276
- - Barbet 的 Mamba 狀態以**純 PyTorch 單步遞迴**處理,不需融合 kernel。
277
- - 可選的 `compile=True` 透過 `torch.compile`(內部即 CUDA graphs)加速 **DiT 與 LocEnc**——也就是真正的熱點,而這正是直接套 vLLM 不會幫你做的部分。
278
-
279
- > 一句話總結:我們不追求單一運算比 vLLM 快,而是用 vLLM 級的**批次調度**搭配**針對 DiT 瓶頸的最佳化**,在零額外依賴、跨裝置的前提下提升整體吞吐量。
280
-
281
- ## Apple Silicon MLX 加速(選用)
282
-
283
- 在 Apple Silicon(M 系列)上,可改用 **MLX** 原生路徑,直接在 Apple GPU(Metal、統一記憶體)上推論,通常比 PyTorch 的 MPS 後端更快。這是**選用**功能,核心仍維持 torch-only:
284
-
285
- ```bash
286
- pip install -e .[mlx]
287
- ```
288
-
289
- ```python
290
- from bluemagpie import BlueMagpieModel
291
- from bluemagpie.mlx import BlueMagpieMLX, mlx_generate
292
-
293
- model = BlueMagpieModel.from_local(model_dir, tokenizer=tokenizer, device="cpu")
294
- mlx_model = BlueMagpieMLX(model) # 轉換權重(只需一次)
295
-
296
- import soundfile as sf
297
- audio = mlx_generate(model, mlx_model, "今天天氣真好。", seed=0) # 48 kHz 波形
298
- sf.write("output.wav", audio.numpy(), model.sample_rate)
299
- ```
300
-
301
- - 整條推論路徑(Barbet、RALM、LocEnc、LocDiT/CFM、**AudioVAE 解碼器**、AR 迴圈)皆以 MLX 重寫,並逐模組對 PyTorch 做數值 parity 驗證——生成過程可完全不經 PyTorch(僅斷詞與參考音檔編碼仍用 torch)。
302
- - decode 採用快取式單步(cached step),逐步推進、不重算整個序列。
303
- - `mlx_generate` 支援與 `generate` 相同的四種輸入模式(一般合成、語音接續、參考音檔、語者向量)。
304
- - 在**真實 7.75GB 模型**上端到端 **RTF 0.77**(比即時還快)——比 torch-MPS 快約 **1.45×**、比 torch-CPU 快約 **3.27×**(fp32,`scripts/bench_rtf.py`)。設計與限制詳見 [`src/bluemagpie/mlx/DESIGN.md`](src/bluemagpie/mlx/DESIGN.md)。
305
-
306
- ## 注意事項
307
-
308
- - 上面範例都直接從 `tokenizer.json` 載入 tokenizer 再傳給 `from_local`,在較新版 transformers(5.x)也能穩定運作;背後原因見〈疑難排解〉。
309
- - 沒有 GPU 也可以執行:把 `device` 設為 `"cpu"` 即可(速度較慢,但短句合成只需數十秒)。輸出為 48 kHz 單聲道。
310
- - 模型內附的 `hung_yi_lee` 語者向量已取得本人授權,可直接作為範例使用;指定其他語者或進行聲音複製時,請只使用你已取得授權的參考音檔或語者向量。
311
- - 請妥善保管語者向量表與合成出來的音檔,未經授權前不要對外散布。
312
-
313
- ## 疑難排解
314
-
315
- **較新版 transformers(5.x)的 tokenizer 載入**
316
-
317
- 上面的範例都直接從 `tokenizer.json` 載入 tokenizer 再傳給 `from_local`,因此在 transformers 5.x 也能正常運作,不需額外處理(模型只用到 tokenizer 的 `encode`)。
318
-
319
- 若你改用 `from_local` 的自動載入(不傳入 `tokenizer`),在 transformers 5.x 可能會失敗 —— 解析 `tokenizer_config.json` 時出現
320
-
321
- ```
322
- TypeError: ..._patch_mistral_regex() got multiple values for keyword argument 'fix_mistral_regex'
323
- ```
324
 
325
- 或載入看似成功、但呼叫 `generate()` 時才報 `ValueError: No tokenizer attached to BlueMagpieModel`。遇到時改回上面範例的明確載入方式即可。
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - zh
4
+ - en
5
+ tags:
6
+ - text-to-speech
7
+ - speech-synthesis
8
+ - code-switching
9
+ library_name: bluemagpie
10
+ pipeline_tag: text-to-speech
11
+ license: other
12
+ ---
13
 
14
+ # BlueMagpie-TTS
15
 
16
+ BlueMagpie-TTS checkpoint for research and evaluation.
17
 
18
+ This repository contains the inference artifact only: model weights, AudioVAE
19
+ weights, tokenizer files, config, and usage documentation. It does not include
20
+ optimizer state, scheduler state, training logs, speaker tables, local configs,
21
+ or training-data metadata.
22
 
23
+ ## Intended Use
 
 
 
24
 
25
+ - Mandarin and mixed Mandarin/English text-to-speech evaluation.
26
+ - Experiments with two mutually exclusive generation modes:
27
+ centroid-only and speaker-reference-audio-only.
28
+ - Do not redistribute the checkpoint or generated speech unless rights and
29
+ consent are cleared for the intended use.
30
 
31
+ ## Install
32
 
33
  ```bash
34
+ git clone https://github.com/voidful/BlueMagpie-TTS
35
  cd BlueMagpie-TTS
36
+ pip install -e ".[train]"
37
+ pip install soundfile huggingface_hub
 
 
 
 
 
 
 
38
  ```
39
 
40
+ ## Quick Start
 
 
41
 
42
  ```python
 
43
  from huggingface_hub import snapshot_download
44
+ import soundfile as sf
 
 
 
 
 
 
 
 
 
 
 
45
 
 
 
 
46
  from bluemagpie import BlueMagpieModel
47
 
48
+ model_dir = snapshot_download("OpenFormosa/BlueMagpie-TTS", token=True)
49
+ model = BlueMagpieModel.from_local(model_dir, training=False, device="cuda")
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  audio = model.generate(
52
+ target_text="這是 AI TTS code switching 測試。",
53
+ reference_wav_path="reference_speaker.wav",
54
  cfg_value=2.0,
55
+ inference_timesteps=10,
56
+ retry_badcase=True,
57
  )
58
 
59
+ sf.write("sample.wav", audio.detach().cpu().numpy(), model.sample_rate)
60
  ```
61
 
62
+ ## Conditioning Modes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  ```python
65
+ # centroid-only
66
  audio = model.generate(
67
+ target_text="今天的會議改到下午三點。",
68
+ speaker_centroid=centroid_tensor,
69
+ cfg_value=2.0,
70
+ inference_timesteps=10,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  )
 
 
 
 
 
72
 
73
+ # speaker-reference-audio-only: no reference transcript required
74
  audio = model.generate(
75
+ target_text="今天的會議改到下午三點。",
76
+ reference_wav_path="reference_speaker.wav",
77
  cfg_value=2.0,
78
+ inference_timesteps=10,
79
  )
 
 
 
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  ```
82
 
83
+ Only use reference audio or speaker centroids from speakers you have permission
84
+ to synthesize. Reference clips should be at least 3 seconds. The
85
+ speaker-reference-audio-only mode uses the raw reference-audio token path and
86
+ does not require a reference transcript.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ ## Long Text
89
 
90
+ For long-form synthesis, split text into sentence-sized chunks and concatenate
91
+ the generated waveforms. For stronger continuity, keep the same centroid or
92
+ reference audio across chunks.
93
 
94
+ ## Evaluation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
+ Numbers below are from an internal held-out evaluation set. The eval set and
97
+ training data are intentionally not described in this model card.
98
 
99
+ | System | Setting | CER | WER |
100
+ | --- | --- | ---: | ---: |
101
+ | BlueMagpie-TTS | centroid-only | 7.44% | 8.57% |
102
+ | BlueMagpie-TTS | speaker-reference-audio-only | 8.99% | 11.77% |
103
+ | Reference baseline | same internal eval | 11.45% | 14.83% |
104
 
105
+ Long-form diagnostics on the selected checkpoint:
106
 
107
+ | Metric | Value |
108
+ | --- | ---: |
109
+ | centroid-only CER / WER | 7.51% / 7.51% |
110
+ | speaker-reference-audio-only CER / WER | 8.92% / 8.92% |
111
+ | Median chars/sec | 4.017 |
112
+ | speaker-reference chunk speaker-sim drop | 0.109 |
 
 
113
 
114
+ ## Limitations
115
 
116
+ - Metrics are not a public benchmark and should be used only for internal model
117
+ selection.
118
+ - Speaker similarity depends on the quality and rights-cleared status of the
119
+ supplied reference audio or centroid.
120
+ - Very long passages should be chunked to avoid stop-token and prosody drift.
121
+ - Generated speech may be incorrect; do not use it as a real-world notification
122
+ without human review.
123
 
124
+ ## Files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
+ - `pytorch_model.bin`: BlueMagpie model weights.
127
+ - `audiovae.pth`: AudioVAE weights.
128
+ - `config.json`: BlueMagpie architecture/runtime config.
129
+ - `tokenizer.json`, `tokenizer_config.json`: tokenizer files.
130
+ - `USAGE.md`: expanded usage guide.
USAGE.md CHANGED
@@ -1,363 +1,97 @@
1
- # BlueMagpie-TTS — Usage
2
 
3
- BlueMagpie-TTS is a text-to-speech (TTS) model that synthesizes natural speech
4
- from text. It supports three scenarios:
5
-
6
- - **Plain synthesis** — read the text aloud.
7
- - **Voice cloning** — mimic the timbre of a reference clip.
8
- - **Speaker selection** — control the timbre with a prepared speaker vector.
9
-
10
- It also supports **streaming output** for synthesize-while-you-play applications.
11
-
12
- 🔊 **Try it online:** [BlueMagpie-TTS Demo (Hugging Face Space)](https://huggingface.co/spaces/voidful/BlueMagpie-TTS-Demo)
13
-
14
- ## Install
15
 
16
  ```bash
17
- git clone https://github.com/OpenFormosa/BlueMagpie-TTS
18
  cd BlueMagpie-TTS
19
- pip install -e .
20
- ```
21
-
22
- The install pulls in the [`barbet`](https://github.com/OpenFormosa/Barbet)
23
- package (the text-semantic language model) from GitHub. The acoustic modules are
24
- vendored in `bluemagpie/_vendor/` (sourced from
25
- [VoxCPM](https://github.com/OpenBMB/VoxCPM), Apache-2.0) and need no separate
26
- install. To save synthesized audio, also install `soundfile`:
27
-
28
- ```bash
29
- pip install soundfile
30
  ```
31
 
32
- ## Load the model
33
-
34
- ### From Hugging Face
35
 
36
  ```python
37
- import os
38
  from huggingface_hub import snapshot_download
39
- from transformers import PreTrainedTokenizerFast
40
  from bluemagpie import BlueMagpieModel
41
 
42
  model_dir = snapshot_download("OpenFormosa/BlueMagpie-TTS", token=True)
43
- # Load the tokenizer straight from tokenizer.json (works on transformers 5.x).
44
- tokenizer = PreTrainedTokenizerFast(tokenizer_file=os.path.join(model_dir, "tokenizer.json"))
45
- model = BlueMagpieModel.from_local(model_dir, tokenizer=tokenizer, training=False, device="cuda")
46
- ```
47
-
48
- ### From a local directory
49
-
50
- ```python
51
- import os
52
- from transformers import PreTrainedTokenizerFast
53
- from bluemagpie import BlueMagpieModel
54
-
55
- model_dir = "checkpoints/bluemagpie"
56
- tokenizer = PreTrainedTokenizerFast(tokenizer_file=os.path.join(model_dir, "tokenizer.json"))
57
- model = BlueMagpieModel.from_local(model_dir, tokenizer=tokenizer, training=False, device="cuda")
58
  ```
59
 
60
- - `device` may be `"cuda"`, `"mps"`, or `"cpu"` (auto-selected if omitted).
61
- - Always use `training=False` for inference.
62
-
63
- ## Basic synthesis: text to speech
64
-
65
- `generate` returns a speech waveform (`torch.Tensor`); pair it with `soundfile`
66
- to write a `.wav`. The output sample rate is `model.sample_rate` (48 kHz).
67
 
68
  ```python
69
  import soundfile as sf
70
 
71
- audio = model.generate(target_text="今天天氣真好。", cfg_value=2.0)
72
- sf.write("output.wav", audio.squeeze().cpu().numpy(), model.sample_rate)
73
- ```
74
-
75
- ## Voice cloning: mimic a reference speaker
76
-
77
- Two ways.
78
-
79
- **A. Speaker vector (`speaker_centroid`)** — extract a vector from the reference
80
- audio, then synthesize (no transcript needed):
81
-
82
- ```bash
83
- pip install -e ".[clone]" # extraction needs speechbrain (ECAPA-TDNN)
84
- python scripts/extract_speaker_centroid.py --audio reference.wav --out my_voice.pt
85
- # more clips of the same speaker -> cleaner centroid: --audio a.wav b.wav c.wav
86
- ```
87
-
88
- ```python
89
- import torch
90
-
91
- centroid = torch.load("my_voice.pt", weights_only=True) # [192] speaker vector
92
- audio = model.generate(
93
- target_text="今天天氣真好。",
94
- speaker_centroid=centroid,
95
- cfg_value=2.8,
96
- )
97
-
98
- # or extract it in-process:
99
- from bluemagpie import extract_speaker_centroid
100
- centroid = extract_speaker_centroid("reference.wav") # [192]
101
- ```
102
-
103
- **B. Reference clip (`reference_wav_path`)** — pass a reference clip directly:
104
-
105
- ```python
106
- audio = model.generate(
107
- target_text="今天天氣真好。",
108
- reference_wav_path="reference.wav",
109
- cfg_value=2.8,
110
  )
 
111
  ```
112
 
113
- ## Speaker selection: control timbre with a speaker vector
114
-
115
- The model bundles a **multi-speaker table** at `checkpoints/speaker_centroids.pt`,
116
- currently holding two speakers:
117
-
118
- | speaker id | description | suggested `cfg_value` |
119
- | --- | --- | --- |
120
- | `hung_yi_lee` | Prof. Hung-yi Lee's speaker vector (used with his authorization; the official best params are tuned for this speaker) | 2.0–2.8 |
121
- | `female_voice` | a generic female voice | 2.0–2.8 |
122
-
123
- The table has the format `{"speaker_ids": [...], "centroids": tensor[N, 192], "dim": 192}`.
124
- Load it with `torch.load`, **pick a speaker's `[192]` vector by id**, and pass it as
125
- `speaker_centroid`:
126
 
127
  ```python
128
- import os
129
- import torch
130
-
131
- table = torch.load(
132
- os.path.join(model_dir, "checkpoints", "speaker_centroids.pt"),
133
- map_location="cpu",
134
- weights_only=True,
135
  )
136
- print(table["speaker_ids"]) # ['hung_yi_lee', 'female_voice']
137
-
138
- # switch speaker by changing this line ("hung_yi_lee" or "female_voice")
139
- speaker_id = "female_voice"
140
- speaker_centroid = table["centroids"][table["speaker_ids"].index(speaker_id)] # [192]
141
 
142
- audio = model.generate(
143
- target_text="今天天氣真好。",
144
- speaker_centroid=speaker_centroid, # or your own authorized speaker vector
 
145
  cfg_value=2.0,
 
146
  )
147
- ```
148
-
149
- If you only have the model id (haven't `snapshot_download`-ed the whole model yet),
150
- grab just the table:
151
-
152
- ```python
153
- from huggingface_hub import hf_hub_download
154
-
155
- path = hf_hub_download("OpenFormosa/BlueMagpie-TTS", "checkpoints/speaker_centroids.pt")
156
- table = torch.load(path, map_location="cpu", weights_only=True)
157
- ```
158
 
159
- > To add more speakers, extract your own (authorized) `[192]` vector with
160
- > `extract_speaker_centroid` from the *Voice cloning* section above — it's passed the
161
- > exact same way. The earlier single-speaker file
162
- > `checkpoints/hung_yi_lee_speaker_centroids.pt` (same format) is still available.
163
-
164
- ## Streaming output
165
-
166
- When you need to play while synthesizing, use `generate_streaming`. It is a
167
- generator that yields audio chunks one at a time:
168
-
169
- ```python
170
- chunks = []
171
- for chunk in model.generate_streaming(target_text="今天天氣真好。"):
172
- chunks.append(chunk)
173
- # play or write each chunk in real time here
174
- ```
175
-
176
- > Note: automatic retry (`retry_badcase`) is not supported in streaming mode.
177
-
178
- ## Four input modes
179
-
180
- The model supports four input combinations through the same `generate` interface:
181
-
182
- | Mode | Parameters | Use |
183
- |---|---|---|
184
- | Plain synthesis | `target_text` | Read the text aloud |
185
- | Continuation | `target_text`, `prompt_text`, `prompt_wav_path` | Continue from an existing clip and its text |
186
- | Reference clip | `target_text`, `reference_wav_path` | Mimic the reference speaker's timbre |
187
- | Speaker vector | `target_text`, `speaker_centroid` | Clone a voice from a speaker vector |
188
-
189
- ## Common `generate` parameters
190
-
191
- | Parameter | Default | Description |
192
- |---|---|---|
193
- | `target_text` | (required) | The text to synthesize |
194
- | `prompt_text` | `""` | Prompt text, paired with `prompt_wav_path` for continuation |
195
- | `prompt_wav_path` | `""` | Prompt audio path, for continuation |
196
- | `reference_wav_path` | `""` | Reference audio path, for voice cloning |
197
- | `speaker_centroid` | `None` | Speaker vector, to select a timbre |
198
- | `cfg_value` | `2.0` | Guidance strength; higher follows the condition more closely but can sound less natural |
199
- | `inference_timesteps` | `10` | Sampling steps; more usually means better quality and slower speed |
200
- | `min_len` / `max_len` | `2` / `2000` | Lower / upper bound on output length |
201
- | `retry_badcase` | `False` | Auto-retry on detected bad output (unsupported in streaming) |
202
-
203
- ## Batch serving engine (multi-request acceleration)
204
-
205
- To serve many synthesis requests at once for higher throughput, use the built-in
206
- batch engine `BlueMagpieEngine`. It does **continuous batching**: requests are
207
- decoded together as a batch, new requests can join mid-decode, and they do not
208
- interfere with one another.
209
-
210
- Highlights:
211
-
212
- - **No extra dependencies** — torch only; no vLLM, flash-attn, etc.
213
- - **Cross-device** — one code path on CUDA, Apple Silicon (MPS), and CPU.
214
- CUDA-only optimizations are auto-detected and enabled, and skipped elsewhere.
215
- - **Numerically identical to single-call `generate`** at batch=1 (`model.generate`
216
- is always the reference).
217
-
218
- ### Basic usage
219
-
220
- ```python
221
- import soundfile as sf
222
- from bluemagpie.serving import BlueMagpieEngine, EngineConfig, Request
223
-
224
- # load `model` and `tokenizer` as shown above (from_local)
225
- engine = BlueMagpieEngine(model, EngineConfig(max_num_seqs=16))
226
-
227
- engine.add_request(Request(target_text="今天天氣真好。", seed=0))
228
- engine.add_request(Request(target_text="第二句話。", reference_wav_path="speaker.wav"))
229
-
230
- for out in engine.run(): # returned in request-id (submission) order
231
- # out.audio: 48 kHz waveform (when an AudioVAE is attached); out.latents: [T, p, d]
232
- sf.write(f"output_{out.request_id}.wav", out.audio.numpy(), out.sample_rate)
233
- ```
234
-
235
- `Request` supports the same four input modes as `generate` (plain, continuation,
236
- reference clip, speaker vector) via the fields `target_text`, `prompt_text`,
237
- `prompt_wav_path`, `reference_wav_path`, `speaker_centroid`, `cfg_value`,
238
- `inference_timesteps`, etc. Each request may set a `seed`, which makes its output
239
- independent of how many neighbours share the batch and of admission order.
240
-
241
- ### Streaming
242
-
243
- `engine.stream()` is a generator that yields a chunk per request per step:
244
-
245
- ```python
246
- for chunk in engine.stream():
247
- # chunk.request_id, chunk.latents, chunk.audio, chunk.finished
248
- play_or_write(chunk)
249
  ```
250
 
251
- > Plain synthesis, reference-clip, and speaker-vector modes stream audio
252
- > (`chunk.audio`); prompt-audio continuation streams `latents` only — use `run()`
253
- > when you need its audio.
254
-
255
- ### Configuration
256
-
257
- Common `EngineConfig` parameters:
258
-
259
- | Parameter | Default | Description |
260
- |---|---|---|
261
- | `max_num_seqs` | `16` | Max concurrent requests batched together |
262
- | `max_model_len` | `2048` | Max length per sequence (prompt + generated) |
263
- | `inference_timesteps` | `9` | Sampling steps |
264
- | `cfg_value` | `2.8` | Guidance strength |
265
- | `enforce_eager` | `True` | Keep the path numerically identical to single-call `generate` |
266
- | `compile` | `False` | Enable `torch.compile` (CUDA only; auto-skipped elsewhere) |
267
-
268
- > See [`src/bluemagpie/serving/DESIGN.md`](src/bluemagpie/serving/DESIGN.md) for the
269
- > engine's design, trade-offs, and known limitations.
270
-
271
- ### Why not just use vLLM?
272
-
273
- People often expect "wrap it in vLLM and it gets fast", but for BlueMagpie that
274
- does not work, for two reasons:
275
-
276
- 1. **The real compute bottleneck is the diffusion decoder, not the language
277
- model.** Per generated audio unit the DiT (LocDiT / CFM diffusion decoder) is
278
- called ~16–18 times (sampling steps × the unconditional/conditional CFG
279
- pair), while the language models (Barbet, RALM) run once each. vLLM is a
280
- *text language-model* inference framework — it does not touch the diffusion
281
- decoder at all, so even moving the LMs onto vLLM leaves the dominant compute
282
- running eagerly and barely moves end-to-end latency.
283
- 2. **vLLM does not support Barbet's hybrid architecture.** Barbet (the
284
- text-semantic LM) is a Mamba2 + attention hybrid, and vLLM (as well as
285
- nano-vllm and vllm-omni) has zero support for such a hybrid TSLM — you'd have
286
- to implement a first-class hybrid model yourself (large effort, CUDA-only).
287
-
288
- So this engine **borrows vLLM's architectural techniques without depending on its
289
- CUDA kernels**:
290
-
291
- - **Continuous batching** of many requests (the main throughput win), sharing
292
- batched compute across requests.
293
- - A **padded KV cache + SDPA + masks** instead of vLLM's PagedAttention /
294
- FlashAttention — trading peak speed and memory efficiency for cross-device,
295
- zero-dependency portability.
296
- - Barbet's Mamba state handled with a **pure-PyTorch single-step recurrence**, no
297
- fused kernel required.
298
- - Optional `compile=True` uses `torch.compile` (which captures CUDA graphs
299
- internally) to accelerate the **DiT and LocEnc** — the actual hot path, and
300
- exactly what wrapping in vLLM would *not* do for you.
301
-
302
- > In short: we don't aim to beat vLLM on a single op; we use vLLM-class **batch
303
- > scheduling** plus **DiT-bottleneck optimization** to raise overall throughput
304
- > with no extra dependencies, across CUDA / MPS / CPU.
305
-
306
- ## Apple Silicon MLX acceleration (optional)
307
-
308
- On Apple Silicon (M-series), a native **MLX** path runs inference directly on the
309
- Apple GPU (Metal, unified memory) — typically faster than PyTorch's MPS backend.
310
- It is an optional extra; the core package stays torch-only:
311
-
312
- ```bash
313
- pip install -e .[mlx]
314
- ```
315
 
316
  ```python
 
317
  import soundfile as sf
318
- from bluemagpie import BlueMagpieModel
319
- from bluemagpie.mlx import BlueMagpieMLX, mlx_generate
320
 
321
- model = BlueMagpieModel.from_local(model_dir, tokenizer=tokenizer, device="cpu")
322
- mlx_model = BlueMagpieMLX(model) # converts the weights once
 
 
 
 
 
 
323
 
324
- audio = mlx_generate(model, mlx_model, "今天天氣真好。", seed=0) # 48 kHz waveform
325
- sf.write("output.wav", audio.numpy(), model.sample_rate)
326
  ```
327
 
328
- - The whole inference path (Barbet, RALM, LocEnc, LocDiT/CFM, the **AudioVAE
329
- decoder**, the AR loop) is re-implemented in MLX and numerically parity-checked,
330
- module by module — generation can run torch-free (only tokenization and
331
- reference-wav encoding stay in torch).
332
- - Decode uses cached single-step kernels (it advances one position per step, not a
333
- full re-run).
334
- - `mlx_generate` supports the same four input modes as `generate`.
335
- - On the real 7.75 GB model: end-to-end **RTF 0.77** (faster than real time) —
336
- ~**1.45×** over torch-MPS and ~**3.27×** over torch-CPU (fp32,
337
- `scripts/bench_rtf.py`). See [`src/bluemagpie/mlx/DESIGN.md`](src/bluemagpie/mlx/DESIGN.md).
338
 
339
- ## Notes
 
 
 
 
340
 
341
- - The examples load the tokenizer from `tokenizer.json` and pass it to
342
- `from_local`, which is stable on transformers 5.x. (`from_local`'s automatic
343
- tokenizer loading can fail on 5.x — see Troubleshooting.)
344
- - A GPU is optional: set `device="cpu"` (slower, but short utterances take only
345
- tens of seconds). Output is 48 kHz mono.
346
- - The bundled `hung_yi_lee` speaker vector is authorized for example use. For any
347
- other speaker or voice cloning, use only reference audio or speaker vectors you
348
- are authorized to use.
349
- - Keep speaker-vector tables and synthesized audio private; do not distribute
350
- them without authorization.
351
 
352
- ## Troubleshooting
 
 
 
 
353
 
354
- **Tokenizer loading on newer transformers (5.x).** The examples load the
355
- tokenizer explicitly from `tokenizer.json`, so they work on transformers 5.x with
356
- no extra steps (the model only uses the tokenizer's `encode`).
357
 
358
- If you instead rely on `from_local`'s automatic tokenizer loading (passing no
359
- `tokenizer`), transformers 5.x may fail while parsing `tokenizer_config.json`
360
- with `TypeError: ..._patch_mistral_regex() got multiple values for keyword
361
- argument 'fix_mistral_regex'`, or appear to load but raise `ValueError: No
362
- tokenizer attached to BlueMagpieModel` when you call `generate()`. Use the
363
- explicit loading shown above instead.
 
1
+ # BlueMagpie-TTS Usage
2
 
3
+ This is an inference checkpoint. Install the local package first:
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  ```bash
6
+ git clone https://github.com/voidful/BlueMagpie-TTS
7
  cd BlueMagpie-TTS
8
+ pip install -e ".[train]"
9
+ pip install soundfile huggingface_hub
 
 
 
 
 
 
 
 
 
10
  ```
11
 
12
+ Download and load:
 
 
13
 
14
  ```python
 
15
  from huggingface_hub import snapshot_download
 
16
  from bluemagpie import BlueMagpieModel
17
 
18
  model_dir = snapshot_download("OpenFormosa/BlueMagpie-TTS", token=True)
19
+ model = BlueMagpieModel.from_local(model_dir, training=False, device="cuda")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  ```
21
 
22
+ Generate a short utterance:
 
 
 
 
 
 
23
 
24
  ```python
25
  import soundfile as sf
26
 
27
+ wav = model.generate(
28
+ target_text="這是合成語音測試。",
29
+ reference_wav_path="reference_speaker.wav",
30
+ cfg_value=2.0,
31
+ inference_timesteps=10,
32
+ retry_badcase=True,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  )
34
+ sf.write("short.wav", wav.detach().cpu().numpy(), model.sample_rate)
35
  ```
36
 
37
+ Generation modes:
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  ```python
40
+ # centroid-only
41
+ wav = model.generate(
42
+ target_text="這是指定 speaker centroid 的測試。",
43
+ speaker_centroid=centroid_tensor,
44
+ cfg_value=2.0,
45
+ inference_timesteps=10,
 
46
  )
 
 
 
 
 
47
 
48
+ # speaker-reference-audio-only; no reference transcript required
49
+ wav = model.generate(
50
+ target_text="明天 meeting 取消一次,我們大家放假。",
51
+ reference_wav_path="reference_speaker.wav",
52
  cfg_value=2.0,
53
+ inference_timesteps=10,
54
  )
 
 
 
 
 
 
 
 
 
 
 
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  ```
57
 
58
+ Streaming:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  ```python
61
+ import torch
62
  import soundfile as sf
 
 
63
 
64
+ chunks = []
65
+ for chunk in model.generate_streaming(
66
+ target_text="這是一段串流語音合成測試。",
67
+ reference_wav_path="reference_speaker.wav",
68
+ cfg_value=2.0,
69
+ inference_timesteps=10,
70
+ ):
71
+ chunks.append(chunk.detach().cpu())
72
 
73
+ wav = torch.cat(chunks, dim=-1)
74
+ sf.write("streaming.wav", wav.numpy(), model.sample_rate)
75
  ```
76
 
77
+ Long text:
 
 
 
 
 
 
 
 
 
78
 
79
+ 1. Split the text by sentence or paragraph.
80
+ 2. Generate each chunk separately.
81
+ 3. Concatenate the waveforms with a short crossfade if needed.
82
+ 4. Keep the same centroid or reference audio across chunks to reduce speaker
83
+ drift.
84
 
85
+ Recommended generation defaults:
 
 
 
 
 
 
 
 
 
86
 
87
+ - `cfg_value=2.0`
88
+ - `inference_timesteps=10`
89
+ - `retry_badcase=True` for offline generation
90
+ - `max_len=2000` unless a longer chunk is intentionally needed
91
+ - Reference wavs for `reference_wav_path=...` should be at least 3 seconds.
92
 
93
+ Safety:
 
 
94
 
95
+ - Use only rights-cleared reference audio or speaker embeddings.
96
+ - Do not present generated speech as a real person or real notification unless
97
+ that is explicitly authorized and reviewed.
 
 
 
checkpoints/hung_yi_lee_speaker_centroids.pt DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e1d4c95a4c33935ff1fee0ab47fa796dcc13908a183c60e9b02bc0a61c541c4c
3
- size 2691
 
 
 
 
checkpoints/speaker_centroids.pt DELETED
Binary file (3.31 kB)
 
config.json CHANGED
@@ -286,6 +286,7 @@
286
  "rms_norm_eps": 1e-06
287
  },
288
  "speaker_embed_dim": 192,
 
289
  "audio_start_token": -1,
290
  "audio_end_token": -1,
291
  "ref_audio_start_token": -1,
@@ -294,31 +295,5 @@
294
  "barbet_effective_vocab_size": null,
295
  "max_length": 8192,
296
  "device": "cuda",
297
- "dtype": "bfloat16",
298
- "generation_defaults": {
299
- "cfg_value": 2.8,
300
- "inference_timesteps": 9,
301
- "max_len": 2000,
302
- "retry_badcase": true,
303
- "retry_badcase_max_times": 3,
304
- "retry_badcase_ratio_threshold": 6.0,
305
- "speaker_id": "hung_yi_lee",
306
- "speaker_source_dataset": "voidful/hung-yi_lee",
307
- "speaker_centroid_path": "checkpoints/hung_yi_lee_speaker_centroids.pt",
308
- "speaker_centroid_sha256": "e1d4c95a4c33935ff1fee0ab47fa796dcc13908a183c60e9b02bc0a61c541c4c",
309
- "speaker_centroid_dim": 192
310
- },
311
- "generation_defaults_source": {
312
- "scope": "tts_hard_sentences_zh_500 + Breeze-ASR-25 normalized CER",
313
- "sentences": "/home/voidful/tts_hard_sentences_zh_500.txt",
314
- "asr_model": "MediaTek-Research/Breeze-ASR-25",
315
- "conversion": "s2twp",
316
- "normalized_cer": 0.09669792733863977,
317
- "mixed_token_error_rate": 0.0911015155363644,
318
- "char_errors": 1227,
319
- "char_reference_length": 12689,
320
- "evaluated_examples": 500,
321
- "trial": "hy_cfg2p8_steps9",
322
- "run": "hungyi_high_refine_hy_cfg2p8_steps9_20260620"
323
- }
324
  }
 
286
  "rms_norm_eps": 1e-06
287
  },
288
  "speaker_embed_dim": 192,
289
+ "ref_audio_bottleneck": "none",
290
  "audio_start_token": -1,
291
  "audio_end_token": -1,
292
  "ref_audio_start_token": -1,
 
295
  "barbet_effective_vocab_size": null,
296
  "max_length": 8192,
297
  "device": "cuda",
298
+ "dtype": "bfloat16"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }
pytorch_model.bin CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:33dc9593a5cf25619853a4140f5114b4fb61954b163c86d28f145321272806dd
3
  size 7746547131
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e454c077ded2ce9d5f3b8ec4f336af840a2fe9912149d1f25afd4938bf7a0319
3
  size 7746547131
release_metadata.json CHANGED
@@ -1,45 +1,37 @@
1
  {
2
  "format": "bluemagpie-pretrained",
3
- "checkpoint": "step_0003900",
4
  "files": [
5
  "pytorch_model.bin",
6
  "audiovae.pth",
7
  "config.json",
8
  "tokenizer.json",
9
- "tokenizer_config.json",
10
- "checkpoints/hung_yi_lee_speaker_centroids.pt"
11
  ],
12
  "evaluation": {
13
  "scope": "internal held-out evaluation",
14
- "cer": 0.048101,
15
- "wer": 0.05356,
16
- "reference_baseline_cer": 0.114483,
17
- "reference_baseline_wer": 0.148266
18
- },
19
- "recommended_generation_defaults": {
20
- "cfg_value": 2.8,
21
- "inference_timesteps": 9,
22
- "max_len": 2000,
23
- "retry_badcase": true,
24
- "retry_badcase_max_times": 3,
25
- "retry_badcase_ratio_threshold": 6.0,
26
- "speaker_id": "hung_yi_lee",
27
- "speaker_source_dataset": "voidful/hung-yi_lee",
28
- "speaker_centroid_path": "checkpoints/hung_yi_lee_speaker_centroids.pt",
29
- "speaker_centroid_sha256": "e1d4c95a4c33935ff1fee0ab47fa796dcc13908a183c60e9b02bc0a61c541c4c",
30
- "speaker_centroid_dim": 192
31
- },
32
- "recommended_generation_defaults_source": {
33
- "scope": "tts_hard_sentences_zh_500 + Breeze-ASR-25 normalized CER",
34
- "sentences": "/home/voidful/tts_hard_sentences_zh_500.txt",
35
- "asr_model": "MediaTek-Research/Breeze-ASR-25",
36
- "conversion": "s2twp",
37
- "normalized_cer": 0.09669792733863977,
38
- "mixed_token_error_rate": 0.0911015155363644,
39
- "char_errors": 1227,
40
- "char_reference_length": 12689,
41
- "evaluated_examples": 500,
42
- "trial": "hy_cfg2p8_steps9",
43
- "run": "hungyi_high_refine_hy_cfg2p8_steps9_20260620"
44
  }
45
  }
 
1
  {
2
  "format": "bluemagpie-pretrained",
3
+ "checkpoint": "step_0006000",
4
  "files": [
5
  "pytorch_model.bin",
6
  "audiovae.pth",
7
  "config.json",
8
  "tokenizer.json",
9
+ "tokenizer_config.json"
 
10
  ],
11
  "evaluation": {
12
  "scope": "internal held-out evaluation",
13
+ "centroid_only": {
14
+ "cer": 0.07441389020336389,
15
+ "wer": 0.08565566378066376
16
+ },
17
+ "speaker_reference_audio_only": {
18
+ "cer": 0.08992608978902839,
19
+ "wer": 0.11774568024568023
20
+ },
21
+ "long_centroid_only": {
22
+ "cer": 0.07511737089201878,
23
+ "wer": 0.07511737089201878,
24
+ "chars_per_second": 4.017351942663145
25
+ },
26
+ "long_speaker_reference_audio_only": {
27
+ "cer": 0.0892018779342723,
28
+ "wer": 0.0892018779342723,
29
+ "chars_per_second": 4.017351942663145,
30
+ "chunk_speaker_similarity_drop": 0.1085478663444519
31
+ },
32
+ "reference_baseline": {
33
+ "cer": 0.114483,
34
+ "wer": 0.148266
35
+ }
 
 
 
 
 
 
 
36
  }
37
  }