add speed parameter

This commit is contained in:
ANLGBOY
2025-11-19 19:42:24 +09:00
parent c31b6745e4
commit 8518b839c1
30 changed files with 246 additions and 61 deletions

View File

@@ -4,6 +4,8 @@ This guide provides examples for running TTS inference using `example_onnx.py`.
## 📰 Update News
**2025.11.19** - Added `--speed` parameter to control speech synthesis speed. Adjust the speed factor to make speech faster or slower while maintaining natural quality.
**2025.11.19** - Added automatic text chunking for long-form inference. Long texts are split into chunks and synthesized with natural pauses.
## Installation
@@ -85,6 +87,28 @@ This will:
**Note**: When using batch mode (`--batch`), automatic text chunking is disabled. Use non-batch mode for long-form text synthesis.
### Example 5: Adjusting Speech Speed
Control the speed of speech synthesis:
```bash
# Faster speech (speed > 1.0)
uv run example_onnx.py \
--voice-style assets/voice_styles/F2.json \
--text "This text will be synthesized at a faster pace." \
--speed 1.2
# Slower speech (speed < 1.0)
uv run example_onnx.py \
--voice-style assets/voice_styles/M2.json \
--text "This text will be synthesized at a slower, more deliberate pace." \
--speed 0.9
```
This will:
- Use `--speed 1.2` to generate faster speech
- Use `--speed 0.9` to generate slower speech
- Default speed is 1.05 if not specified
- Recommended speed range is between 0.9 and 1.5 for natural-sounding results
## Available Arguments
| Argument | Type | Default | Description |
@@ -92,6 +116,7 @@ This will:
| `--use-gpu` | flag | False | Use GPU for inference (with CPU fallback) |
| `--onnx-dir` | str | `assets/onnx` | Path to ONNX model directory |
| `--total-step` | int | 5 | Number of denoising steps (higher = better quality, slower) |
| `--speed` | float | 1.05 | Speech speed factor (higher = faster, lower = slower) |
| `--n-test` | int | 4 | Number of times to generate each sample |
| `--voice-style` | str+ | `assets/voice_styles/M1.json` | Voice style file path(s) |
| `--text` | str+ | (long default text) | Text(s) to synthesize |

View File

@@ -26,6 +26,12 @@ def parse_args():
parser.add_argument(
"--total-step", type=int, default=5, help="Number of denoising steps"
)
parser.add_argument(
"--speed",
type=float,
default=1.05,
help="Speech speed (default: 1.05, higher = faster)",
)
parser.add_argument(
"--n-test", type=int, default=4, help="Number of times to generate"
)
@@ -62,6 +68,7 @@ print("=== TTS Inference with ONNX Runtime (Python) ===\n")
# --- 1. Parse arguments --- #
args = parse_args()
total_step = args.total_step
speed = args.speed
n_test = args.n_test
save_dir = args.save_dir
voice_style_paths = args.voice_style
@@ -84,9 +91,9 @@ for n in range(n_test):
print(f"\n[{n+1}/{n_test}] Starting synthesis...")
with timer("Generating speech from text"):
if batch:
wav, duration = text_to_speech.batch(text_list, style, total_step)
wav, duration = text_to_speech.batch(text_list, style, total_step, speed)
else:
wav, duration = text_to_speech(text_list[0], style, total_step)
wav, duration = text_to_speech(text_list[0], style, total_step, speed)
if not os.path.exists(save_dir):
os.makedirs(save_dir)
for b in range(bsz):

View File

@@ -86,7 +86,7 @@ class TextToSpeech:
return noisy_latent, latent_mask
def _infer(
self, text_list: list[str], style: Style, total_step: int
self, text_list: list[str], style: Style, total_step: int, speed: float = 1.05
) -> tuple[np.ndarray, np.ndarray]:
assert (
len(text_list) == style.ttl.shape[0]
@@ -96,6 +96,7 @@ class TextToSpeech:
dur_onnx, *_ = self.dp_ort.run(
None, {"text_ids": text_ids, "style_dp": style.dp, "text_mask": text_mask}
)
dur_onnx = dur_onnx / speed
text_emb_onnx, *_ = self.text_enc_ort.run(
None,
{"text_ids": text_ids, "style_ttl": style.ttl, "text_mask": text_mask},
@@ -120,7 +121,12 @@ class TextToSpeech:
return wav, dur_onnx
def __call__(
self, text: str, style: Style, total_step: int, silence_duration: float = 0.3
self,
text: str,
style: Style,
total_step: int,
speed: float = 1.05,
silence_duration: float = 0.3,
) -> tuple[np.ndarray, np.ndarray]:
assert (
style.ttl.shape[0] == 1
@@ -129,7 +135,7 @@ class TextToSpeech:
wav_cat = None
dur_cat = None
for text in text_list:
wav, dur_onnx = self._infer([text], style, total_step)
wav, dur_onnx = self._infer([text], style, total_step, speed)
if wav_cat is None:
wav_cat = wav
dur_cat = dur_onnx
@@ -142,9 +148,9 @@ class TextToSpeech:
return wav_cat, dur_cat
def batch(
self, text_list: list[str], style: Style, total_step: int
self, text_list: list[str], style: Style, total_step: int, speed: float = 1.05
) -> tuple[np.ndarray, np.ndarray]:
return self._infer(text_list, style, total_step)
return self._infer(text_list, style, total_step, speed)
def length_to_mask(lengths: np.ndarray, max_len: Optional[int] = None) -> np.ndarray: