File size: 5,460 Bytes
63e7bc2
4e9e0e4
63e7bc2
4e9e0e4
 
63e7bc2
4e9e0e4
71084e9
 
4e9e0e4
 
63e7bc2
4e9e0e4
 
 
71084e9
4e9e0e4
71084e9
63e7bc2
4e9e0e4
 
63e7bc2
4e9e0e4
 
 
 
71084e9
 
 
63e7bc2
 
71084e9
63e7bc2
 
 
9f63115
71084e9
 
4e9e0e4
63e7bc2
4e9e0e4
 
63e7bc2
4e9e0e4
 
63e7bc2
 
 
 
 
 
71084e9
 
6fbb52c
 
71084e9
 
 
 
63e7bc2
9f63115
71084e9
6fbb52c
63e7bc2
71084e9
 
6fbb52c
 
 
 
78b3cbe
 
 
 
 
71084e9
78b3cbe
 
 
 
 
 
 
 
63e7bc2
6fbb52c
 
63e7bc2
6fbb52c
 
63e7bc2
 
 
71084e9
63e7bc2
 
 
 
6fbb52c
63e7bc2
 
6fbb52c
 
63e7bc2
6fbb52c
71084e9
5fb8b3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71084e9
 
8909649
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71084e9
5fb8b3f
 
 
 
6fbb52c
63e7bc2
6fbb52c
63e7bc2
 
5fb8b3f
9f63115
71084e9
63e7bc2
9f63115
5fb8b3f
71084e9
6fbb52c
4e11051
 
 
 
 
 
63e7bc2
6fbb52c
63e7bc2
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# BlueMagpie-TTS Usage

This is an inference checkpoint. Install the local package first:

```bash
git clone https://github.com/voidful/BlueMagpie-TTS
cd BlueMagpie-TTS
pip install -e ".[speaker]"
pip install soundfile
```

Download and load:

```python
from huggingface_hub import snapshot_download
from bluemagpie import BlueMagpieModel, speaker_embedding_from_wav

model_dir = snapshot_download("OpenFormosa/BlueMagpie-TTS")
model = BlueMagpieModel.from_local(model_dir, training=False, device="cuda")
```

Generate a short utterance:

```python
import soundfile as sf

reference_embedding = speaker_embedding_from_wav(
    "reference_speaker.wav", window_sec=3.0, hop_sec=1.5
)
wav = model.generate(
    target_text="這是合成語音測試。",
    speaker_centroid=reference_embedding,
    cfg_value=2.0,
    inference_timesteps=10,
    retry_badcase=True,
    retry_badcase_ratio_threshold=6.0,
    stop_threshold=0.65,
    stop_consecutive=2,
)
sf.write("short.wav", wav.detach().cpu().numpy(), model.sample_rate)
```

Generation modes:

```python
# centroid-only
wav = model.generate(
    target_text="這是指定 speaker centroid 的測試。",
    speaker_centroid=centroid_tensor,
    cfg_value=2.0,
    inference_timesteps=10,
    stop_threshold=0.65,
    stop_consecutive=2,
)

# speaker-reference-audio-only; extract once, no reference transcript required
reference_embedding = speaker_embedding_from_wav(
    "reference_speaker.wav", window_sec=3.0, hop_sec=1.5
)
wav = model.generate(
    target_text="今天的 meeting 依照原定時間進行。",
    speaker_centroid=reference_embedding,
    cfg_value=2.0,
    inference_timesteps=10,
    stop_threshold=0.65,
    stop_consecutive=2,
)

```

Centroid demo:

```python
import torch

table = torch.load(model_dir + "/checkpoints/speaker_centroids.pt", map_location="cpu")
wav = model.generate(
    target_text="這是 centroid demo 的測試。",
    speaker_centroid=table["centroids"][0],
    cfg_value=2.0,
    inference_timesteps=10,
)
```

Streaming:

```python
import torch
import soundfile as sf

chunks = []
for chunk in model.generate_streaming(
    target_text="這是一段串流語音合成測試。",
    speaker_centroid=reference_embedding,
    cfg_value=2.0,
    inference_timesteps=10,
):
    chunks.append(chunk.detach().cpu())

wav = torch.cat(chunks, dim=-1)
sf.write("streaming.wav", wav.numpy(), model.sample_rate)
```

Long text:

```bash
python scripts/generate_tts.py \
  --checkpoint /path/to/model-snapshot \
  --mode speaker-reference-audio-only \
  --speaker-reference-wav /path/to/rights-cleared-reference.wav \
  --reference-audio-conditioning speaker-embedding \
  --text-file long_text.txt \
  --chunk-chars 80 \
  --min-chunk-chars 12 \
  --target-chars-per-sec 4.0 \
  --stop-threshold 0.65 \
  --stop-consecutive 2 \
  --crossfade-ms 80 \
  --chunk-rms-match-db 4 \
  --chunk-edge-fade-ms 80 \
  --continuation-context-sec 0 \
  --no-retry-badcase \
  --out long.wav
```

Quality-first short or medium text:

```bash
python scripts/generate_tts_quality.py \
  --checkpoint /path/to/model-snapshot \
  --mode speaker-reference-audio-only \
  --speaker-reference-wav /path/to/rights-cleared-reference.wav \
  --text "這是離線品質優先的語音合成測試。" \
  --candidates 10 \
  --asr-backend whisper \
  --asr-model /path/to/compatible-asr-checkpoint \
  --candidate-speaker-weight 0.05 \
  --candidate-boundary-speaker-weight 0.1 \
  --candidate-max-boundary-speaker-drop 0.03 \
  --target-chars-per-sec 4.2 \
  --out quality.wav
```

This opt-in path is approximately proportional to the candidate count in
latency. It fails closed if no candidate passes the speaker-boundary gate.
`--allow-boundary-fallback` is a research override, not part of the measured
contract. The quality policy is promoted only for speaker-reference
short/medium text; keep using `generate_tts.py` for centroid and long-form
production requests.

This path extracts the windowed speaker embedding once and reuses it for every
chunk. Each request gets a new random seed that is reused inside that request;
the release gate varies request seeds, so stability does not depend on one
global fixed seed. `--reference-audio-conditioning tokens` enables the
raw-reference-token research backend; it is not the production default.

Recommended generation defaults:

- `cfg_value=2.0`
- `inference_timesteps=10`
- `retry_badcase=False` for the measured long-form contract
- `retry_badcase_ratio_threshold=6.0` so retry detection is not a pace cap
- `stop_threshold=0.65`, `stop_consecutive=2` for offline generation
- `max_len=2000` unless a longer chunk is intentionally needed
- `target-chars-per-sec=4.0` for controlled long-form chunking
- `continuation-context-sec=0` until generated-context continuation passes its own gate
- Reference wavs used to extract speaker embeddings should be at least 3 seconds.

The hosted interactive demo uses a separate endpoint-only policy with the same
weights: a 0.50 stop threshold that relaxes after 75% of the native-rate
duration estimate to 0.05 at 95%, one stop hit, and a native-rate hard cap plus
one latent step. It applies pace correction after generation. The offline
defaults above remain the fixed evaluation contract.

Safety:

- Use only rights-cleared reference audio or speaker embeddings.
- Do not present generated speech as a real person or real notification unless
  that is explicitly authorized and reviewed.