-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathf5_debug.py
More file actions
289 lines (234 loc) · 9.71 KB
/
Copy pathf5_debug.py
File metadata and controls
289 lines (234 loc) · 9.71 KB
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#!/usr/bin/env python3
"""
F5-TTS MLX Debug Script - Output Path Fix
Test using the output_path parameter to save files instead of relying on return values
"""
import json
import sys
import tempfile
from pathlib import Path
def create_test_audio():
"""Create a simple test audio file for F5-TTS"""
try:
import numpy as np
import soundfile as sf
# Create 3 seconds of simple sine wave at 24kHz
duration = 3.0
sample_rate = 24000
frequency = 440 # A4 note
t = np.linspace(0, duration, int(sample_rate * duration), False)
audio = np.sin(2 * np.pi * frequency * t) * 0.3
# Add some variation to make it more voice-like
audio += np.sin(2 * np.pi * frequency * 2 * t) * 0.1
audio += np.random.normal(0, 0.01, len(audio)) # Small amount of noise
temp_file = tempfile.mktemp(suffix=".wav") # noqa: S306
sf.write(temp_file, audio, sample_rate)
print(f"✅ Created test audio: {temp_file}")
return temp_file
except Exception as e:
print(f"❌ Failed to create test audio: {e}")
return None
def test_f5_mlx_with_output_path():
"""Test F5-TTS MLX using the output_path parameter"""
try:
import soundfile as sf
from f5_tts_mlx.generate import generate
print("🧪 Testing F5-TTS MLX with output_path parameter...")
# Create test audio
test_audio = create_test_audio()
if not test_audio:
return False
# Create output file path
output_file = "f5_output_path_test.wav"
try:
print("🚀 Calling F5-TTS MLX with output_path...")
# Test with output_path parameter
params = {
'generation_text': "Hello, this is a test of the output path parameter.",
'model_name': "lucasnewman/f5-tts-mlx",
'ref_audio_path': test_audio,
'ref_audio_text': "This is a test reference audio.",
'steps': 8,
'cfg_strength': 1.0,
'speed': 1.0,
'sway_sampling_coef': -1.0,
'estimate_duration': False,
'output_path': output_file # KEY: This should make it save to file
}
print(f"Parameters: {json.dumps(params, indent=2)}")
result = generate(**params)
print("✅ F5-TTS MLX call completed!")
print(f" Return value: {result}")
print(f" Type: {type(result)}")
# Check if output file was created
output_path = Path(output_file)
if output_path.exists():
file_size = output_path.stat().st_size
print("🎉 SUCCESS: Output file created!")
print(f" File: {output_file}")
print(f" Size: {file_size} bytes")
# Analyze the saved audio
try:
info = sf.info(output_file)
duration = info.duration
sample_rate = info.samplerate
print(f" Duration: {duration:.2f}s")
print(f" Sample Rate: {sample_rate}Hz")
print(f" Channels: {info.channels}")
# Read and analyze audio data
audio_data, sr = sf.read(output_file)
import numpy as np
rms = np.sqrt(np.mean(audio_data**2))
peak = np.abs(audio_data).max()
print(f" RMS: {rms:.4f}")
print(f" Peak: {peak:.4f}")
if duration > 0.1 and rms > 0.001:
print("✅ Audio appears to be valid!")
return True
else:
print("⚠️ Audio may be too short or silent")
return False
except Exception as e:
print(f" Audio analysis failed: {e}")
return False
else:
print("❌ FAILED: No output file was created")
print("💡 The output_path parameter may not be working as expected")
return False
finally:
# Cleanup
try:
Path(test_audio).unlink()
except Exception: # noqa: S110
pass
except ImportError:
print("❌ F5-TTS MLX not available")
return False
except Exception as e:
print(f"❌ Test failed: {e}")
import traceback
traceback.print_exc()
return False
def test_german_with_output_path():
"""Test with german.wav using output_path"""
german_file = "./german.wav"
if not Path(german_file).exists():
print(f"❌ {german_file} not found")
return False
try:
import numpy as np
import soundfile as sf
print("🎵 Testing german.wav with output_path...")
# Prepare the audio
audio_data, sr = sf.read(german_file)
# Convert to mono and trim
if len(audio_data.shape) > 1:
audio_data = np.mean(audio_data, axis=1)
# Take 5 seconds from middle
if len(audio_data) > sr * 5:
mid = len(audio_data) // 2
half_duration = int(sr * 2.5)
audio_data = audio_data[mid - half_duration:mid + half_duration]
# Resample to 24kHz if needed
if sr != 24000:
try:
import torch
import torchaudio
audio_tensor = torch.from_numpy(audio_data).float().unsqueeze(0)
resampler = torchaudio.transforms.Resample(sr, 24000)
audio_data = resampler(audio_tensor).squeeze().numpy()
sr = 24000
except Exception:
print("⚠️ Cannot resample, using original sample rate")
# Save prepared audio
temp_audio = tempfile.mktemp(suffix="_prepared.wav") # noqa: S306
sf.write(temp_audio, audio_data, sr)
# Create output file
output_file = "german_output_path_test.wav"
print(f"📊 Prepared audio: {len(audio_data)/sr:.1f}s at {sr}Hz")
# Test F5-TTS
from f5_tts_mlx.generate import generate
params = {
'generation_text': "Das ist ein einfacher deutscher Testtext für die Sprachsynthese mit output_path.",
'model_name': "lucasnewman/f5-tts-mlx",
'ref_audio_path': temp_audio,
'ref_audio_text': "Dies ist eine deutsche Referenzaufnahme für Tests.",
'steps': 16,
'cfg_strength': 1.5,
'speed': 1.0,
'output_path': output_file # KEY: Save to specific file
}
print("🚀 Calling F5-TTS with german audio and output_path...")
result = generate(**params)
print("✅ Generation completed!")
print(f" Return value: {result}")
# Check output file
output_path = Path(output_file)
if output_path.exists():
file_size = output_path.stat().st_size
print("🎉 SUCCESS: German output file created!")
print(f" File: {output_file}")
print(f" Size: {file_size} bytes")
try:
info = sf.info(output_file)
duration = info.duration
print(f" Duration: {duration:.2f}s")
if duration > 0.5:
print("✅ German synthesis appears successful!")
return True
else:
print("⚠️ German audio may be too short")
return False
except Exception as e:
print(f" Analysis failed: {e}")
return False
else:
print("❌ FAILED: German output file not created")
return False
# Cleanup
Path(temp_audio).unlink()
except Exception as e:
print(f"❌ German test failed: {e}")
import traceback
traceback.print_exc()
return False
def main():
print("🛠️ F5-TTS MLX Output Path Fix Test")
print("=" * 50)
if len(sys.argv) < 2:
print("Usage:")
print(" python f5_debug_output_path.py test - Test with output_path parameter")
print(" python f5_debug_output_path.py german - Test german.wav with output_path")
print(" python f5_debug_output_path.py both - Run both tests")
return
command = sys.argv[1]
if command == "test":
success = test_f5_mlx_with_output_path()
if success:
print("\n🎉 The output_path parameter fix WORKS!")
print("💡 Update your handler to use output_path instead of trying to capture return values")
else:
print("\n❌ The output_path parameter test failed")
elif command == "german":
success = test_german_with_output_path()
if success:
print("\n🎉 German synthesis with output_path WORKS!")
else:
print("\n❌ German synthesis with output_path failed")
elif command == "both":
print("🔍 Running both tests...\n")
test1 = test_f5_mlx_with_output_path()
print("\n" + "="*30 + "\n")
test2 = test_german_with_output_path()
print("\n📊 Results Summary:")
print(f" Basic test: {'✅ PASS' if test1 else '❌ FAIL'}")
print(f" German test: {'✅ PASS' if test2 else '❌ FAIL'}")
if test1 and test2:
print("\n🎉 ALL TESTS PASSED!")
print("💡 The F5-TTS handler should now work correctly with output_path parameter")
else:
print("\n⚠️ Some tests failed - check the output above")
else:
print(f"❌ Unknown command: {command}")
if __name__ == "__main__":
main()