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 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.4.6"
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
- if self.debug_mode:
235
- print(f"📥 Downloading {model_name}...")
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
- tts = TTS(model_name=model_name, progress_bar=True)
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
- if self.debug_mode:
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
- if self.debug_mode:
252
- print(f"❌ Failed to download {model_name}: {e}")
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
- manager.clear_cache()
458
- print(" Cache cleared")
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:
@@ -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
- models_to_try = [selected_model, self.SAFE_FALLBACK]
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"🌍 Switching to {lang_name} voice: {model_name}")
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
- if self.debug_mode:
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
- # Check compatibility
861
- if voice_info['requires'] == 'espeak-ng' and not self._test_model_compatibility(voice_info['model']):
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
- return False
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.4.6
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.4.0+)
175
+ ### ⚡ Instant TTS (v0.5.0+)
176
176
 
177
177
  ```python
178
178
  from abstractvoice import VoiceManager
179
179
 
180
- # Initialize voice manager - automatically downloads essential model if needed
180
+ # Initialize voice manager - works immediately with included dependencies
181
181
  vm = VoiceManager()
182
182
 
183
- # Text-to-speech works immediately!
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.4.0+ automatically:
188
- - ✅ Downloads essential English model (107MB) on first use
189
- - ✅ Caches models permanently for offline use
190
- - ✅ Works immediately after first setup
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
- # Download and use French voice
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
- # Download and use German voice
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
- # Download and set specific voice
1381
- /setvoice fr.css10_vits # French CSS10 VITS
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=lUnhUk3fGSJ1DoiQ0o7gSxGbfm8QerKZOc12Vgp-DBY,1011
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=nmKP4aAZXKqUG38fylCc7pELNvJWXTzO-YUYHc_jjJc,17484
7
- abstractvoice/voice_manager.py,sha256=46tQnu9WlwE3mFcwfTmu7Q5hwg8nun9PBZRSIemLsUA,35587
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.4.6.dist-info/licenses/LICENSE,sha256=TiDPM5WcFRQPoC5e46jGMeMppZ-eu0eFx_HytjE49bk,1105
19
- abstractvoice-0.4.6.dist-info/METADATA,sha256=YyQn5POiq7AE0NYO3JuyYmg3cYKgPH8YAgnB--f7ubE,41000
20
- abstractvoice-0.4.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
- abstractvoice-0.4.6.dist-info/entry_points.txt,sha256=3bDX2dNOGvrsTx1wZ_o_hVgmM_a2zbcHc1ZkL154rN4,72
22
- abstractvoice-0.4.6.dist-info/top_level.txt,sha256=a1qyxqgF1O8cJtPKpcJuImGZ_uXqPNghbLZ9gp-UiOo,14
23
- abstractvoice-0.4.6.dist-info/RECORD,,
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,,