| # 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. |
|
|