You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
echo "🎤 Generating TTS audio (ground truth test)..."
22
+
TEXT="I can't believe we finally made it to the summit after climbing for twelve exhausting hours through wind and rain, but wow, this view of the endless mountain ranges stretching to the horizon makes every single difficult step completely worth the journey."
23
+
24
+
# This will auto-download model and generate audio
25
+
swift run --configuration release fluidaudio tts "$TEXT" --output kokoro_output.wav --auto-download
We generated the same strings with to gerneate audio between 1s to ~300s in order to test the speed across a range of varying inputs on Pytorch CPU, MPS, and MLX pipeline, and compared it against the native Swift version with Core ML models.
86
+
87
+
Each pipeline warmed up the models by running through it once with pesudo inputs, and then comparing the raw inference time with the model already loaded. You can see that for the Core ML model, we traded lower memory and very slightly faster inference for longer initial warm-up.
88
+
89
+
Note that the Pytorch kokoro model in Pytorch has a memory leak issue: https://github.com/hexgrad/kokoro/issues/152
90
+
91
+
The following tests were ran on M4 Pro, 48GB RAM, Macbook Pro. If you have another device, please do try replicating it as well!
92
+
93
+
### Kokoro-82M PyTorch (CPU)
94
+
95
+
```bash
96
+
KPipeline benchmark for voice af_heart (warm-up took 0.175s) using hexgrad/kokoro
97
+
Test Chars Output (s) Inf(s) RTFx Peak GB
98
+
1 42 2.750 0.187 14.737x 1.44
99
+
2 129 8.625 0.530 16.264x 1.85
100
+
3 254 15.525 0.923 16.814x 2.65
101
+
4 93 6.125 0.349 17.566x 2.66
102
+
5 104 7.200 0.410 17.567x 2.70
103
+
6 130 9.300 0.504 18.443x 2.72
104
+
7 197 12.850 0.726 17.711x 2.83
105
+
8 6 1.350 0.098 13.823x 2.83
106
+
9 1228 76.200 4.342 17.551x 3.19
107
+
10 567 35.200 2.069 17.014x 4.85
108
+
11 4615 286.525 17.041 16.814x 4.78
109
+
Total - 461.650 27.177 16.987x 4.85
110
+
```
111
+
112
+
### Kokoro-82M PyTorch (MPS)
113
+
114
+
I wasn't able to run the MPS model for longer durations, even with `PYTORCH_ENABLE_MPS_FALLBACK=1` enabled, it kept crashing for the longer strings.
115
+
116
+
```bash
117
+
KPipeline benchmark for voice af_heart (warm-up took 0.568s) using pip package
118
+
Test Chars Output (s) Inf(s) RTFx Peak GB
119
+
1 42 2.750 0.414 6.649x 1.41
120
+
2 129 8.625 0.729 11.839x 1.54
121
+
Total - 11.375 1.142 9.960x 1.54
122
+
```
123
+
124
+
### Kokoro-82M MLX Pipeline
125
+
126
+
```bash
127
+
TTS benchmark for voice af_heart (warm-up took an extra 2.155s) using model prince-canuma/Kokoro-82M
128
+
Test Chars Output (s) Inf(s) RTFx Peak GB
129
+
1 42 2.750 0.347 7.932x 1.12
130
+
2 129 8.650 0.597 14.497x 2.47
131
+
3 254 15.525 0.825 18.829x 2.65
132
+
4 93 6.125 0.306 20.039x 2.65
133
+
5 104 7.200 0.343 21.001x 2.65
134
+
6 130 9.300 0.560 16.611x 2.65
135
+
7 197 12.850 0.596 21.573x 2.65
136
+
8 6 1.350 0.364 3.706x 2.65
137
+
9 1228 76.200 2.979 25.583x 3.29
138
+
10 567 35.200 1.374 25.615x 3.37
139
+
11 4615 286.500 11.112 25.783x 3.37
140
+
Total - 461.650 19.401 23.796x 3.37
141
+
```
142
+
143
+
#### Swift + Fluid Audio Core ML models
144
+
145
+
Note that it does take `~15s` to compile the model on the first run, subsequent runs are shorter, we expect ~2s to load.
146
+
147
+
```bash
148
+
> swift run fluidaudio tts --benchmark
149
+
...
150
+
FluidAudio TTS benchmark for voice af_heart (warm-up took an extra 2.348s)
151
+
Test Chars Ouput (s) Inf(s) RTFx
152
+
1 42 2.825 0.440 6.424x
153
+
2 129 7.725 0.594 13.014x
154
+
3 254 13.400 0.776 17.278x
155
+
4 93 5.875 0.587 10.005x
156
+
5 104 6.675 0.613 10.889x
157
+
6 130 8.075 0.621 13.008x
158
+
7 197 10.650 0.627 16.983x
159
+
8 6 0.825 0.360 2.290x
160
+
9 1228 67.625 2.362 28.625x
161
+
10 567 33.025 1.341 24.619x
162
+
11 4269 247.600 9.087 27.248x
163
+
Total - 404.300 17.408 23.225
164
+
165
+
Peak memory usage (process-wide): 1.503 GB
166
+
```
167
+
83
168
## Voice Activity Detection
84
169
85
170
Model is nearly identical to the base model in terms of quality, perforamnce wise we see an up to ~3.5x improvement compared to the silero Pytorch VAD model with the 256ms batch model (8 chunks of 32ms)
FluidAudio bundles the eSpeak-NG phoneme resources so Kokoro can fall back to G2P lookups when the US lexicons don’t contain a word. The Core ML pipeline expects the resources under `Resources/espeak-ng/espeak-ng-data.bundle` with the canonical `voices/` directory inside.
4
+
5
+
## All Platforms (Primary Flow)
6
+
-`TtsResourceDownloader.ensureEspeakDataBundle` first attempts to stage the packaged `espeak-ng-data.bundle` from SwiftPM resources (`Sources/FluidAudio/Resources/espeak-ng/`).
7
+
- The bundle is copied to `~/.cache/fluidaudio/Models/kokoro/Resources/espeak-ng/`.
8
+
- The `voices/` directory is validated after staging; if missing, `TTSError.downloadFailed` is raised.
9
+
10
+
## Fallback Behavior (macOS Only)
11
+
- If the packaged bundle is unavailable, **macOS only** falls back to downloading `espeak-ng.zip` from HuggingFace and extracting it with `/usr/bin/unzip`.
12
+
-**iOS/tvOS/watchOS** do not support fallback downloads and will throw `TTSError.downloadFailed` if the packaged bundle is missing.
13
+
- For mobile platforms, ensure the packaged bundle is present in the Swift package resources before building.
14
+
15
+
## Best practices
16
+
- Keep the `espeak-ng-data.bundle` (packaged copy) and the optional `espeak-ng.zip` fallback in sync with any updates to the Kokoro phoneme mapper.
17
+
- If you customize the cache location, be sure the `Resources/espeak-ng/espeak-ng-data.bundle/voices/` directory is present before running TTS.
18
+
- When testing on iOS, bundle the extracted resources with the app or seed the simulator cache in advance to avoid runtime failures.
19
+
20
+
## CocoaPods integration notes
21
+
- The `ESpeakNG.xcframework` now includes support for iOS device (arm64), iOS Simulator (arm64 + x86_64), and macOS (arm64 + x86_64).
22
+
- iOS Simulator support is provided via a stub framework that allows building and linking but returns failure values for ESpeakNG function calls.
23
+
- Pod validation passes successfully with `pod lib lint FluidAudio.podspec --allow-warnings` for all platforms.
24
+
- On iOS Simulator, ESpeakNG initialization will fail gracefully and phonemization requests will return `nil` due to the stub implementation.
25
+
- Full ESpeakNG functionality is available on iOS device and macOS platforms.
26
+
27
+
## Licensing notes
28
+
- eSpeak-NG is distributed under the GNU GPL v3 (or later). Both the core library and the `espeak-ng-data` voices inherit the same license.
29
+
- The full license text now lives at `Licenses/ESpeakNG_LICENSE.txt`; ship this file (or the upstream `COPYING`) anywhere the framework is redistributed and surface it in your third-party notices UI.
30
+
- If you republish the prebuilt `ESpeakNG.xcframework`, keep the license alongside the binary and ensure downstream consumers can obtain the corresponding source per GPL requirements.
0 commit comments