abstractvoice 0.4.6__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- abstractvoice/__init__.py +1 -1
- abstractvoice/simple_model_manager.py +49 -10
- abstractvoice/voice_manager.py +51 -9
- {abstractvoice-0.4.6.dist-info → abstractvoice-0.5.0.dist-info}/METADATA +38 -21
- {abstractvoice-0.4.6.dist-info → abstractvoice-0.5.0.dist-info}/RECORD +9 -9
- {abstractvoice-0.4.6.dist-info → abstractvoice-0.5.0.dist-info}/WHEEL +0 -0
- {abstractvoice-0.4.6.dist-info → abstractvoice-0.5.0.dist-info}/entry_points.txt +0 -0
- {abstractvoice-0.4.6.dist-info → abstractvoice-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {abstractvoice-0.4.6.dist-info → abstractvoice-0.5.0.dist-info}/top_level.txt +0 -0
abstractvoice/__init__.py
CHANGED
|
@@ -32,5 +32,5 @@ from .voice_manager import VoiceManager
|
|
|
32
32
|
# Import simple APIs for third-party applications
|
|
33
33
|
from .simple_model_manager import list_models, download_model, get_status, is_ready
|
|
34
34
|
|
|
35
|
-
__version__ = "0.
|
|
35
|
+
__version__ = "0.5.0"
|
|
36
36
|
__all__ = ['VoiceManager', 'list_models', 'download_model', 'get_status', 'is_ready']
|
|
@@ -212,7 +212,7 @@ class SimpleModelManager:
|
|
|
212
212
|
return False
|
|
213
213
|
|
|
214
214
|
def download_model(self, model_name: str, progress_callback: Optional[Callable[[str, bool], None]] = None) -> bool:
|
|
215
|
-
"""Download a specific model.
|
|
215
|
+
"""Download a specific model with improved error handling.
|
|
216
216
|
|
|
217
217
|
Args:
|
|
218
218
|
model_name: TTS model name (e.g., 'tts_models/en/ljspeech/fast_pitch')
|
|
@@ -231,25 +231,56 @@ class SimpleModelManager:
|
|
|
231
231
|
try:
|
|
232
232
|
TTS, _ = _import_tts()
|
|
233
233
|
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
print(f"📥 Downloading {model_name}...")
|
|
235
|
+
print(f" This may take a few minutes depending on your connection...")
|
|
236
236
|
|
|
237
237
|
start_time = time.time()
|
|
238
238
|
|
|
239
239
|
# Initialize TTS to trigger download
|
|
240
|
-
|
|
240
|
+
# Set gpu=False to avoid CUDA errors on systems without GPU
|
|
241
|
+
try:
|
|
242
|
+
tts = TTS(model_name=model_name, progress_bar=True, gpu=False)
|
|
243
|
+
|
|
244
|
+
# Verify the model actually downloaded
|
|
245
|
+
if not self.is_model_cached(model_name):
|
|
246
|
+
print(f"⚠️ Model download completed but not found in cache")
|
|
247
|
+
return False
|
|
248
|
+
|
|
249
|
+
except Exception as init_error:
|
|
250
|
+
# Try alternative download method
|
|
251
|
+
error_msg = str(init_error).lower()
|
|
252
|
+
if "connection" in error_msg or "timeout" in error_msg:
|
|
253
|
+
print(f"❌ Network error: Check your internet connection")
|
|
254
|
+
elif "not found" in error_msg:
|
|
255
|
+
print(f"❌ Model '{model_name}' not found in registry")
|
|
256
|
+
else:
|
|
257
|
+
print(f"❌ Download error: {init_error}")
|
|
258
|
+
raise
|
|
241
259
|
|
|
242
260
|
download_time = time.time() - start_time
|
|
243
|
-
|
|
244
|
-
print(f"✅ Downloaded {model_name} in {download_time:.1f}s")
|
|
261
|
+
print(f"✅ Downloaded {model_name} in {download_time:.1f}s")
|
|
245
262
|
|
|
246
263
|
if progress_callback:
|
|
247
264
|
progress_callback(model_name, True)
|
|
248
265
|
return True
|
|
249
266
|
|
|
250
267
|
except Exception as e:
|
|
251
|
-
|
|
252
|
-
|
|
268
|
+
error_msg = str(e).lower()
|
|
269
|
+
|
|
270
|
+
# Provide helpful error messages
|
|
271
|
+
if "connection" in error_msg or "timeout" in error_msg:
|
|
272
|
+
print(f"❌ Failed to download {model_name}: Network issue")
|
|
273
|
+
print(f" Check your internet connection and try again")
|
|
274
|
+
elif "permission" in error_msg:
|
|
275
|
+
print(f"❌ Failed to download {model_name}: Permission denied")
|
|
276
|
+
print(f" Check write permissions for cache directory")
|
|
277
|
+
elif "space" in error_msg:
|
|
278
|
+
print(f"❌ Failed to download {model_name}: Insufficient disk space")
|
|
279
|
+
else:
|
|
280
|
+
print(f"❌ Failed to download {model_name}")
|
|
281
|
+
if self.debug_mode:
|
|
282
|
+
print(f" Error: {e}")
|
|
283
|
+
|
|
253
284
|
if progress_callback:
|
|
254
285
|
progress_callback(model_name, False)
|
|
255
286
|
return False
|
|
@@ -454,8 +485,16 @@ def download_models_cli():
|
|
|
454
485
|
return
|
|
455
486
|
|
|
456
487
|
if args.clear:
|
|
457
|
-
|
|
458
|
-
|
|
488
|
+
# Ask for confirmation
|
|
489
|
+
response = input("⚠️ This will delete all downloaded TTS models. Continue? (y/N): ")
|
|
490
|
+
if response.lower() == 'y':
|
|
491
|
+
success = manager.clear_cache(confirm=True)
|
|
492
|
+
if success:
|
|
493
|
+
print("✅ Model cache cleared")
|
|
494
|
+
else:
|
|
495
|
+
print("❌ Failed to clear cache")
|
|
496
|
+
else:
|
|
497
|
+
print("Cancelled")
|
|
459
498
|
return
|
|
460
499
|
|
|
461
500
|
if args.model:
|
abstractvoice/voice_manager.py
CHANGED
|
@@ -548,13 +548,37 @@ class VoiceManager:
|
|
|
548
548
|
|
|
549
549
|
# Select best model for this language
|
|
550
550
|
selected_model = self._select_best_model(language)
|
|
551
|
-
|
|
551
|
+
|
|
552
|
+
# CRITICAL FIX: Check if model is available, download if not
|
|
553
|
+
from .instant_setup import is_model_cached
|
|
554
|
+
from .simple_model_manager import download_model
|
|
555
|
+
|
|
556
|
+
if not is_model_cached(selected_model):
|
|
557
|
+
if self.debug_mode:
|
|
558
|
+
print(f"📥 Model {selected_model} not cached, downloading...")
|
|
559
|
+
|
|
560
|
+
# Try to download the model
|
|
561
|
+
success = download_model(selected_model)
|
|
562
|
+
if not success:
|
|
563
|
+
if self.debug_mode:
|
|
564
|
+
print(f"❌ Failed to download {selected_model}")
|
|
565
|
+
# If download fails and it's not English, we have a problem
|
|
566
|
+
if language != 'en':
|
|
567
|
+
print(f"❌ Cannot switch to {self.LANGUAGES[language]['name']}: Model download failed")
|
|
568
|
+
print(f" Try: abstractvoice download-models --language {language}")
|
|
569
|
+
return False
|
|
570
|
+
|
|
571
|
+
models_to_try = [selected_model]
|
|
572
|
+
|
|
573
|
+
# Only add fallback if it's different from selected
|
|
574
|
+
if selected_model != self.SAFE_FALLBACK:
|
|
575
|
+
models_to_try.append(self.SAFE_FALLBACK)
|
|
552
576
|
|
|
553
577
|
for model_name in models_to_try:
|
|
554
578
|
try:
|
|
555
579
|
if self.debug_mode:
|
|
556
580
|
lang_name = self.LANGUAGES[language]['name']
|
|
557
|
-
print(f"🌍
|
|
581
|
+
print(f"🌍 Loading {lang_name} voice: {model_name}")
|
|
558
582
|
|
|
559
583
|
# Reinitialize TTS engine
|
|
560
584
|
TTSEngine = _import_tts_engine()
|
|
@@ -579,12 +603,16 @@ class VoiceManager:
|
|
|
579
603
|
|
|
580
604
|
except Exception as e:
|
|
581
605
|
if self.debug_mode:
|
|
582
|
-
print(f"⚠️ Model {model_name} failed: {e}")
|
|
606
|
+
print(f"⚠️ Model {model_name} failed to load: {e}")
|
|
607
|
+
# Don't silently continue - report the failure
|
|
608
|
+
if model_name == selected_model and language != 'en':
|
|
609
|
+
print(f"❌ Failed to load {lang_name} voice model")
|
|
610
|
+
print(f" The model might be corrupted. Try:")
|
|
611
|
+
print(f" abstractvoice download-models --language {language}")
|
|
583
612
|
continue
|
|
584
613
|
|
|
585
614
|
# All models failed
|
|
586
|
-
|
|
587
|
-
print(f"❌ All models failed for language '{language}'")
|
|
615
|
+
print(f"❌ Cannot switch to {self.LANGUAGES[language]['name']}: No working models")
|
|
588
616
|
return False
|
|
589
617
|
|
|
590
618
|
def get_language(self):
|
|
@@ -856,15 +884,29 @@ class VoiceManager:
|
|
|
856
884
|
return False
|
|
857
885
|
|
|
858
886
|
voice_info = self.VOICE_CATALOG[language][voice_id]
|
|
887
|
+
model_name = voice_info['model']
|
|
888
|
+
|
|
889
|
+
# CRITICAL FIX: Download model if not cached
|
|
890
|
+
from .instant_setup import is_model_cached
|
|
891
|
+
from .simple_model_manager import download_model
|
|
859
892
|
|
|
860
|
-
|
|
861
|
-
|
|
893
|
+
if not is_model_cached(model_name):
|
|
894
|
+
print(f"📥 Voice model '{voice_id}' not cached, downloading...")
|
|
895
|
+
success = download_model(model_name)
|
|
896
|
+
if not success:
|
|
897
|
+
print(f"❌ Failed to download voice '{voice_id}'")
|
|
898
|
+
print(f" Check your internet connection and try again")
|
|
899
|
+
return False
|
|
900
|
+
print(f"✅ Voice model '{voice_id}' downloaded successfully")
|
|
901
|
+
|
|
902
|
+
# Check compatibility after download
|
|
903
|
+
if voice_info['requires'] == 'espeak-ng' and not self._test_model_compatibility(model_name):
|
|
862
904
|
if self.debug_mode:
|
|
863
905
|
print(f"⚠️ Voice '{voice_id}' requires espeak-ng. Install it for premium quality.")
|
|
864
|
-
|
|
906
|
+
# Don't fail - try to load anyway
|
|
907
|
+
# return False
|
|
865
908
|
|
|
866
909
|
# Set the specific voice
|
|
867
|
-
model_name = voice_info['model']
|
|
868
910
|
if self.debug_mode:
|
|
869
911
|
print(f"🎭 Setting {language} voice to: {voice_id}")
|
|
870
912
|
print(f" Model: {model_name}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractvoice
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: A modular Python library for voice interactions with AI systems
|
|
5
5
|
Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -172,38 +172,51 @@ AbstractVoice automatically detects espeak-ng and upgrades to premium quality vo
|
|
|
172
172
|
|
|
173
173
|
## Quick Start
|
|
174
174
|
|
|
175
|
-
### ⚡ Instant TTS (v0.
|
|
175
|
+
### ⚡ Instant TTS (v0.5.0+)
|
|
176
176
|
|
|
177
177
|
```python
|
|
178
178
|
from abstractvoice import VoiceManager
|
|
179
179
|
|
|
180
|
-
# Initialize voice manager -
|
|
180
|
+
# Initialize voice manager - works immediately with included dependencies
|
|
181
181
|
vm = VoiceManager()
|
|
182
182
|
|
|
183
|
-
# Text-to-speech works
|
|
183
|
+
# Text-to-speech works right away!
|
|
184
184
|
vm.speak("Hello! TTS works out of the box!")
|
|
185
|
+
|
|
186
|
+
# Language switching with automatic model download
|
|
187
|
+
vm.set_language('fr')
|
|
188
|
+
vm.speak("Bonjour! Le français fonctionne aussi!")
|
|
185
189
|
```
|
|
186
190
|
|
|
187
|
-
**That's it!** AbstractVoice v0.
|
|
188
|
-
- ✅
|
|
189
|
-
- ✅
|
|
190
|
-
- ✅ Works immediately after
|
|
191
|
+
**That's it!** AbstractVoice v0.5.0+ automatically:
|
|
192
|
+
- ✅ Includes essential TTS dependencies in base installation
|
|
193
|
+
- ✅ Downloads models automatically when switching languages/voices
|
|
194
|
+
- ✅ Works immediately after `pip install abstractvoice`
|
|
195
|
+
- ✅ No silent failures - clear error messages if download fails
|
|
191
196
|
- ✅ No complex configuration needed
|
|
192
197
|
|
|
193
|
-
### 🌍 Multi-Language Support
|
|
198
|
+
### 🌍 Multi-Language Support (Auto-Download in v0.5.0+)
|
|
194
199
|
|
|
195
200
|
```python
|
|
196
|
-
#
|
|
197
|
-
vm.download_model('fr.css10_vits') # Downloads automatically
|
|
201
|
+
# Simply switch language - downloads model automatically if needed!
|
|
198
202
|
vm.set_language('fr')
|
|
199
203
|
vm.speak("Bonjour! Je parle français maintenant.")
|
|
200
204
|
|
|
201
|
-
#
|
|
202
|
-
vm.download_model('de.thorsten_vits')
|
|
205
|
+
# Switch to German - no manual download needed
|
|
203
206
|
vm.set_language('de')
|
|
204
207
|
vm.speak("Hallo! Ich spreche jetzt Deutsch.")
|
|
208
|
+
|
|
209
|
+
# Spanish, Italian also supported
|
|
210
|
+
vm.set_language('es')
|
|
211
|
+
vm.speak("¡Hola! Hablo español ahora.")
|
|
212
|
+
|
|
213
|
+
# If download fails, you'll get clear error messages with instructions
|
|
214
|
+
# Example: "❌ Cannot switch to French: Model download failed"
|
|
215
|
+
# " Try: abstractvoice download-models --language fr"
|
|
205
216
|
```
|
|
206
217
|
|
|
218
|
+
**New in v0.5.0:** No more manual `download_model()` calls! Language switching handles downloads automatically.
|
|
219
|
+
|
|
207
220
|
### 🔧 Check System Status
|
|
208
221
|
|
|
209
222
|
```python
|
|
@@ -1371,20 +1384,22 @@ abstractvoice check-deps
|
|
|
1371
1384
|
|
|
1372
1385
|
### CLI Voice Commands
|
|
1373
1386
|
|
|
1374
|
-
In the CLI REPL, use these commands:
|
|
1387
|
+
In the CLI REPL, use these commands (v0.5.0+):
|
|
1375
1388
|
|
|
1376
1389
|
```bash
|
|
1377
1390
|
# List all available voices with download status
|
|
1378
1391
|
/setvoice
|
|
1379
1392
|
|
|
1380
|
-
#
|
|
1381
|
-
/setvoice fr.css10_vits # French CSS10
|
|
1382
|
-
/setvoice de.thorsten_vits # German Thorsten
|
|
1383
|
-
/setvoice it.mai_male_vits # Italian Male
|
|
1393
|
+
# Automatically download and set specific voice (NEW in v0.5.0!)
|
|
1394
|
+
/setvoice fr.css10_vits # Downloads French CSS10 if needed
|
|
1395
|
+
/setvoice de.thorsten_vits # Downloads German Thorsten if needed
|
|
1396
|
+
/setvoice it.mai_male_vits # Downloads Italian Male if needed
|
|
1397
|
+
/setvoice en.jenny # Downloads Jenny voice if needed
|
|
1384
1398
|
|
|
1385
|
-
# Change language
|
|
1386
|
-
/language fr
|
|
1387
|
-
/language de
|
|
1399
|
+
# Change language (automatically downloads models if needed - NEW!)
|
|
1400
|
+
/language fr # Switches to French, downloads if needed
|
|
1401
|
+
/language de # Switches to German, downloads if needed
|
|
1402
|
+
/language es # Switches to Spanish, downloads if needed
|
|
1388
1403
|
|
|
1389
1404
|
# Voice controls
|
|
1390
1405
|
/pause # Pause current speech
|
|
@@ -1395,6 +1410,8 @@ In the CLI REPL, use these commands:
|
|
|
1395
1410
|
/exit
|
|
1396
1411
|
```
|
|
1397
1412
|
|
|
1413
|
+
**New in v0.5.0:** Language and voice commands now automatically download missing models with progress indicators. No more silent failures!
|
|
1414
|
+
|
|
1398
1415
|
## Perspectives
|
|
1399
1416
|
|
|
1400
1417
|
This is a test project that I designed with examples to work with Ollama, but I will adapt the examples and abstractvoice to work with any LLM provider (anthropic, openai, etc).
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
abstractvoice/__init__.py,sha256=
|
|
1
|
+
abstractvoice/__init__.py,sha256=EM_gfVmMvSOGeYPfMd8-AFThLrKwWh8TN4JFqdn0deU,1011
|
|
2
2
|
abstractvoice/__main__.py,sha256=e6jhoONg3uwwPUCdnr68bSRTT1RrpWy2DrOJ6ozMJVc,4775
|
|
3
3
|
abstractvoice/dependency_check.py,sha256=BUUADz4un4_FCZzNpgwk1qpJ6yqVi5Pvjfd3JLS8hAI,10045
|
|
4
4
|
abstractvoice/instant_setup.py,sha256=_Q8T6tcMSor--1XPlgdOya3lvC-VtClHz4FSgDOXFNI,2667
|
|
5
5
|
abstractvoice/recognition.py,sha256=4KtDUDFixEYuBUMDH2fWaD9csKlwA9tqXkMAkyQMSMo,11259
|
|
6
|
-
abstractvoice/simple_model_manager.py,sha256=
|
|
7
|
-
abstractvoice/voice_manager.py,sha256=
|
|
6
|
+
abstractvoice/simple_model_manager.py,sha256=DfmrF3t3-V6rIWs4IvJmB_0Cck0LBY3YMvMzHGsHg4Q,19423
|
|
7
|
+
abstractvoice/voice_manager.py,sha256=iw8Lu4VhsSMk0HQYlUU2NWAQR2C4dDiCAsiFjaeldiU,37664
|
|
8
8
|
abstractvoice/examples/__init__.py,sha256=94vpKJDlfOrEBIUETg-57Q5Z7fYDidg6v4UzV7V_lZA,60
|
|
9
9
|
abstractvoice/examples/cli_repl.py,sha256=kIgvgrGfyejX8-VFeFhvAVqrp3X-s-K3Ul861aM4Bh8,44220
|
|
10
10
|
abstractvoice/examples/voice_cli.py,sha256=VdgDT01wly8HjWF53t_hDLkJoZc9FWQq2I-nxcSIAp8,11592
|
|
@@ -15,9 +15,9 @@ abstractvoice/tts/__init__.py,sha256=WgJrxqdc_qaRyfFt1jbgMQD9S757jYuBpDzMRB02TFs
|
|
|
15
15
|
abstractvoice/tts/tts_engine.py,sha256=iTa9eBH9vPH8VR2qoJX6nmNi6yERvA4Uz1jPu4OXrTA,55074
|
|
16
16
|
abstractvoice/vad/__init__.py,sha256=RIIbFw25jNHgel06E4VvTWJnXjwjeFZ98m1Vx9hVjuo,119
|
|
17
17
|
abstractvoice/vad/voice_detector.py,sha256=ghrhpDFlIR5TsMB2gpigXY6t5c_1yZ7vEX1imAMgWjc,3166
|
|
18
|
-
abstractvoice-0.
|
|
19
|
-
abstractvoice-0.
|
|
20
|
-
abstractvoice-0.
|
|
21
|
-
abstractvoice-0.
|
|
22
|
-
abstractvoice-0.
|
|
23
|
-
abstractvoice-0.
|
|
18
|
+
abstractvoice-0.5.0.dist-info/licenses/LICENSE,sha256=TiDPM5WcFRQPoC5e46jGMeMppZ-eu0eFx_HytjE49bk,1105
|
|
19
|
+
abstractvoice-0.5.0.dist-info/METADATA,sha256=cH2FfruHztr3vENO6zo93yuKHkf6KmqI0-C1GnHCYA0,42154
|
|
20
|
+
abstractvoice-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
abstractvoice-0.5.0.dist-info/entry_points.txt,sha256=3bDX2dNOGvrsTx1wZ_o_hVgmM_a2zbcHc1ZkL154rN4,72
|
|
22
|
+
abstractvoice-0.5.0.dist-info/top_level.txt,sha256=a1qyxqgF1O8cJtPKpcJuImGZ_uXqPNghbLZ9gp-UiOo,14
|
|
23
|
+
abstractvoice-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|