Spaces:
Running
Running
| """ | |
| Kokoro TTS Engine - Simple ONNX implementation | |
| Works with Python 3.9+ without complex dependencies | |
| """ | |
| import os | |
| import logging | |
| import numpy as np | |
| from huggingface_hub import hf_hub_download | |
| log = logging.getLogger("kokoro_engine") | |
| class KokoroEngine: | |
| """ | |
| محرك Kokoro TTS بسيط باستخدام kokoro-onnx من PyPI | |
| """ | |
| def __init__(self, voice: str = "af_alloy", sample_rate: int = 24000): | |
| """ | |
| تهيئة محرك Kokoro | |
| Args: | |
| voice: اسم الصوت الافتراضي | |
| sample_rate: معدل العينة (دائماً 24000 لـ Kokoro) | |
| """ | |
| self.sample_rate = sample_rate | |
| self.voice = voice | |
| self.kokoro = None | |
| try: | |
| # استخدام kokoro-onnx من PyPI مباشرة | |
| from kokoro_onnx import Kokoro | |
| # تحميل ملفات النموذج | |
| model_path = self._download_model() | |
| voices_path = self._download_voices() | |
| # تهيئة Kokoro | |
| self.kokoro = Kokoro(model_path, voices_path) | |
| log.info(f"✅ Kokoro-ONNX initialized successfully") | |
| except Exception as e: | |
| log.error(f"❌ Failed to initialize Kokoro-ONNX: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| raise | |
| def _download_model(self) -> str: | |
| """تحميل ملف النموذج""" | |
| try: | |
| # جرب أولاً من onnx-community (الأكثر موثوقية) | |
| model_path = hf_hub_download( | |
| repo_id="fastrtc/kokoro-onnx", | |
| filename="kokoro-v1.0.onnx", | |
| cache_dir="./models" | |
| ) | |
| log.info(f"Model downloaded from onnx-community: {model_path}") | |
| return model_path | |
| except Exception as e1: | |
| log.warning(f"Failed to download from onnx-community: {e1}") | |
| try: | |
| # جرب من NeuML كبديل | |
| model_path = hf_hub_download( | |
| repo_id="onnx-community/Kokoro-82M-ONNX", | |
| filename="onnx/model.onnx", | |
| cache_dir="./models" | |
| ) | |
| log.info(f"Model downloaded from NeuML: {model_path}") | |
| return model_path | |
| except Exception as e2: | |
| log.error(f"Failed to download model from all sources") | |
| raise RuntimeError(f"Could not download model: {e2}") | |
| def _download_voices(self) -> str: | |
| """تحميل ملف الأصوات""" | |
| try: | |
| # جرب أولاً voices.bin من onnx-community | |
| voices_path = hf_hub_download( | |
| repo_id="fastrtc/kokoro-onnx", | |
| filename="voices-v1.0.bin", | |
| cache_dir="./models" | |
| ) | |
| log.info(f"Voices downloaded from onnx-community: {voices_path}") | |
| return voices_path | |
| except Exception as e1: | |
| log.warning(f"Failed to download voices.bin: {e1}") | |
| try: | |
| # جرب voices.json من NeuML كبديل | |
| voices_path = hf_hub_download( | |
| repo_id="onnx-community/Kokoro-82M-ONNX", | |
| filename="voices/voices.bin", | |
| cache_dir="./models" | |
| ) | |
| log.info(f"Voices downloaded from NeuML: {voices_path}") | |
| return voices_path | |
| except Exception as e2: | |
| log.error(f"Failed to download voices from all sources") | |
| raise RuntimeError(f"Could not download voices: {e2}") | |
| def set_voice(self, voice: str): | |
| """ | |
| تغيير الصوت | |
| Args: | |
| voice: اسم الصوت الجديد | |
| """ | |
| self.voice = voice | |
| log.debug(f"Voice changed to: {voice}") | |
| def synthesize(self, text: str, speed: float = 1.0) -> np.ndarray: | |
| """ | |
| تحويل النص إلى صوت | |
| Args: | |
| text: النص المراد تحويله | |
| speed: سرعة التحدث (1.0 = عادي) | |
| Returns: | |
| np.ndarray: البيانات الصوتية كـ numpy array (float32) | |
| """ | |
| if self.kokoro is None: | |
| raise RuntimeError("Kokoro engine not initialized") | |
| try: | |
| # استخدام kokoro-onnx للتوليد | |
| samples, sample_rate = self.kokoro.create( | |
| text, | |
| voice=self.voice, | |
| speed=speed, | |
| lang='en-us' | |
| ) | |
| log.info(f"✅ Audio generated: {len(samples)} samples, duration: {len(samples)/sample_rate:.2f}s") | |
| # التأكد من أن النوع float32 | |
| return samples.astype(np.float32) | |
| except Exception as e: | |
| log.error(f"❌ Synthesis failed: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| raise | |
| def get_available_voices(self): | |
| """ | |
| الحصول على قائمة الأصوات المتاحة | |
| """ | |
| return [ | |
| # British Female | |
| "bf_alice", "bf_emma", "bf_isabella", "bf_lily", | |
| # American Female | |
| "af_alloy", "af_aoede", "af_bella", "af_heart", | |
| "af_jessica", "af_kore", "af_nicole", "af_nova", | |
| "af_river", "af_sarah", "af_sky", | |
| # British Male | |
| "bm_daniel", "bm_fable", "bm_george", "bm_lewis", | |
| # American Male | |
| "am_adam", "am_echo", "am_eric", "am_fenrir", | |
| "am_liam", "am_michael", "am_onyx", "am_puck" | |
| ] | |