alidw commited on
Commit
8dcfafa
·
verified ·
1 Parent(s): 694dc03

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +140 -56
app.py CHANGED
@@ -1,98 +1,182 @@
1
  import gradio as gr
2
  import numpy as np
3
- from fastapi import Request, HTTPException
4
- from starlette.middleware.base import BaseHTTPMiddleware
5
  from tts_arabic import tts as arabic_tts
6
 
 
 
 
7
  API_KEY = "nGHjs7oK8jp7OvxZ5dVZdY6JEf3DVwRF"
8
 
9
- # ==========================================================
10
- # 🔐 MIDDLEWARE لحماية API
11
- # ==========================================================
12
-
13
- class APIKeyMiddleware(BaseHTTPMiddleware):
14
- async def dispatch(self, request: Request, call_next):
15
- # فقط API calls وليس الواجهة
16
- url_path = str(request.url)
17
- if "/api/predict" in url_path:
18
- key = request.headers.get("x-api-key")
19
- if key != API_KEY:
20
- return HTTPException(status_code=401, detail="Invalid or missing API Key")
21
- return await call_next(request)
22
-
23
-
24
- # ==========================================================
25
- # 🎙️ TTS
26
- # ==========================================================
27
-
28
  SAMPLE_RATE = 22050
29
 
 
30
  def generate_tts(
31
- text,
32
- speaker,
33
- pace,
34
- denoise,
35
- volume,
36
- vowelizer,
37
- model_id,
38
- vocoder_id,
 
39
  ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  text = (text or "").strip()
41
  if not text:
42
  return None, "❌ الرجاء إدخال نص عربي."
43
 
44
- vowelizer_arg = None if vowelizer == "بدون تشكيل" else vowelizer
 
 
 
 
 
 
 
 
 
 
45
 
46
  try:
 
 
 
47
  wave = arabic_tts(
48
  text,
49
- speaker=int(speaker),
50
- pace=float(pace),
51
- denoise=float(denoise),
52
- volume=float(volume),
53
- play=False,
54
- vowelizer=vowelizer_arg,
55
- model_id=model_id,
56
- vocoder_id=vocoder_id,
57
- cuda=None,
58
- save_to=None,
 
 
59
  )
60
 
 
61
  if isinstance(wave, list):
62
  wave = np.array(wave, dtype=np.float32)
 
 
 
 
 
 
 
 
 
63
 
64
  return (SAMPLE_RATE, wave), "�� تم توليد الصوت بنجاح."
65
 
66
  except Exception as e:
 
 
67
  return None, f"❌ حدث خطأ أثناء التوليد: {e}"
68
 
69
 
70
- # ==========================================================
71
  # 🎛️ واجهة Gradio
72
- # ==========================================================
73
 
74
  demo = gr.Interface(
75
  fn=generate_tts,
76
  inputs=[
77
- gr.Textbox(label="النص العربي", lines=4),
78
- gr.Dropdown(["0", "1", "2", "3"], value="1", label="المتحدث"),
79
- gr.Slider(0.6, 1.4, value=1.0, step=0.05, label="سرعة الكلام"),
80
- gr.Slider(0.0, 0.02, value=0.005, step=0.001, label="إزالة الضوضاء"),
81
- gr.Slider(0.4, 1.0, value=0.9, step=0.05, label="مستوى الصوت"),
82
- gr.Dropdown(["بدون تشكيل", "shakkelha", "catt_eo"], value="بدون تشكيل", label="التشكيل"),
83
- gr.Radio(["fastpitch", "mixer128", "mixer80"], value="fastpitch", label="موديل النص→ميل"),
84
- gr.Radio(["hifigan", "vocos", "vocos44"], value="hifigan", label="Vocoder"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  ],
86
  outputs=[
87
- gr.Audio(type="numpy", label="الصوت الناتج"),
88
- gr.Textbox(label="الحالة"),
 
 
 
 
 
 
89
  ],
90
  title="Arabic TTS (ONNX / CPU)",
91
- description="واجهة تحويل النص العربي إلى كلام تعمل على CPU، مع حماية API Key.",
 
 
 
92
  )
93
 
94
- # 🎯 إضافة Middleware للـAPI
95
- demo.app.add_middleware(APIKeyMiddleware)
96
-
97
  if __name__ == "__main__":
98
  demo.launch()
 
1
  import gradio as gr
2
  import numpy as np
 
 
3
  from tts_arabic import tts as arabic_tts
4
 
5
+ # =============================
6
+ # 🔐 إعداد مفتاح الـ API
7
+ # =============================
8
  API_KEY = "nGHjs7oK8jp7OvxZ5dVZdY6JEf3DVwRF"
9
 
10
+ # نموذج vocoder الافتراضي 22.05 kHz حسب tts_arabic
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  SAMPLE_RATE = 22050
12
 
13
+
14
  def generate_tts(
15
+ request: gr.Request, # أول بارامتر: كائن الطلب لمعرفة الـ headers
16
+ text: str,
17
+ speaker: str,
18
+ pace: float,
19
+ denoise: float,
20
+ volume: float,
21
+ vowelizer: str,
22
+ model_id: str,
23
+ vocoder_id: str,
24
  ):
25
+ """
26
+ الدالة الأساسية لتحويل النص إلى صوت.
27
+ تُستخدم من واجهة Gradio ومن أي استدعاء API خارجي.
28
+ """
29
+
30
+ # =============================
31
+ # 🔐 التحقق من الـ API KEY
32
+ # =============================
33
+ headers = request.headers or {}
34
+ referer = headers.get("referer", "") or ""
35
+ host = headers.get("host", "") or ""
36
+ api_key = headers.get("x-api-key")
37
+
38
+ # نعتبر الطلب "خارجي" لو الـ referer لا يحتوي على نفس الـ host
39
+ # (الواجهة من المتصفح يكون الـ referer فيها https://<space>.hf.space)
40
+ is_external = host not in referer
41
+
42
+ if is_external:
43
+ # أي استدعاء خارجي لازم يكون معه x-api-key صحيح
44
+ if api_key != API_KEY:
45
+ # gr.Error تُرجع خطأ واضح في JSON و في الواجهة
46
+ raise gr.Error("Invalid or missing API Key")
47
+
48
+ # =============================
49
+ # ✅ التحقق من صحة النص والمدخلات
50
+ # =============================
51
  text = (text or "").strip()
52
  if not text:
53
  return None, "❌ الرجاء إدخال نص عربي."
54
 
55
+ try:
56
+ pace = float(pace)
57
+ denoise = float(denoise)
58
+ volume = float(volume)
59
+ except ValueError:
60
+ return None, "❌ قيم pace / denoise / volume غير صحيحة."
61
+
62
+ if vowelizer == "بدون تشكيل":
63
+ vowelizer_arg = None
64
+ else:
65
+ vowelizer_arg = vowelizer # مثل: "shakkelha" أو "catt_eo"
66
 
67
  try:
68
+ # =============================
69
+ # 🧠 استدعاء مكتبة tts_arabic
70
+ # =============================
71
  wave = arabic_tts(
72
  text,
73
+ speaker=int(speaker), # 0–3
74
+ pace=pace, # سرعة الكلام
75
+ denoise=denoise, # إزالة الضوضاء في vocoder
76
+ volume=volume, # مستوى الصوت (0–1)
77
+ play=False, # لا نشغّل الصوت داخل السيرفر
78
+ pitch_mul=1.0,
79
+ pitch_add=0.0,
80
+ vowelizer=vowelizer_arg, # موديول التشكيل أو None
81
+ model_id=model_id, # fastpitch / mixer128 / mixer80
82
+ vocoder_id=vocoder_id, # hifigan / vocos / vocos44
83
+ cuda=None, # CPU فقط
84
+ save_to=None, # لا نحفظ ملف هنا
85
  )
86
 
87
+ # wave ممكن يرجع list أو numpy
88
  if isinstance(wave, list):
89
  wave = np.array(wave, dtype=np.float32)
90
+ elif isinstance(wave, np.ndarray):
91
+ wave = wave.astype(np.float32)
92
+ else:
93
+ wave = np.array(wave, dtype=np.float32)
94
+
95
+ # تأكد أن الصوت داخل المدى [-1, 1]
96
+ max_abs = np.max(np.abs(wave)) if wave.size > 0 else 1.0
97
+ if max_abs > 1.0:
98
+ wave = wave / max_abs
99
 
100
  return (SAMPLE_RATE, wave), "�� تم توليد الصوت بنجاح."
101
 
102
  except Exception as e:
103
+ # طباعة الخطأ في اللوجز على Hugging Face ليسهل التشخيص
104
+ print("TTS ERROR:", repr(e))
105
  return None, f"❌ حدث خطأ أثناء التوليد: {e}"
106
 
107
 
108
+ # =============================
109
  # 🎛️ واجهة Gradio
110
+ # =============================
111
 
112
  demo = gr.Interface(
113
  fn=generate_tts,
114
  inputs=[
115
+ gr.Textbox(
116
+ label="النص العربي",
117
+ lines=4,
118
+ placeholder="اكتب هنا الجملة أو الفقرة التي تريد تحويلها إلى صوت...",
119
+ ),
120
+ gr.Dropdown(
121
+ choices=["0", "1", "2", "3"],
122
+ value="1",
123
+ label="المتحدث (Speaker ID)",
124
+ info="جرّب أرقام مختلفة لاختيار صوت مختلف.",
125
+ ),
126
+ gr.Slider(
127
+ minimum=0.6,
128
+ maximum=1.4,
129
+ value=1.0,
130
+ step=0.05,
131
+ label="سرعة الكلام (pace)",
132
+ ),
133
+ gr.Slider(
134
+ minimum=0.0,
135
+ maximum=0.02,
136
+ value=0.005,
137
+ step=0.001,
138
+ label="إزالة الضوضاء (denoise)",
139
+ ),
140
+ gr.Slider(
141
+ minimum=0.4,
142
+ maximum=1.0,
143
+ value=0.9,
144
+ step=0.05,
145
+ label="مستوى الصوت (volume)",
146
+ ),
147
+ gr.Dropdown(
148
+ choices=["بدون تشكيل", "shakkelha", "catt_eo"],
149
+ value="بدون تشكيل",
150
+ label="تشكيل تلقائي للنص (Vowelizer)",
151
+ info="اختَر 'shakkelha' لتحسين النطق إذا كان النص غير مشكّل (أبطأ قليلاً).",
152
+ ),
153
+ gr.Radio(
154
+ choices=["fastpitch", "mixer128", "mixer80"],
155
+ value="fastpitch",
156
+ label="موديل Text→Mel (model_id)",
157
+ ),
158
+ gr.Radio(
159
+ choices=["hifigan", "vocos", "vocos44"],
160
+ value="hifigan",
161
+ label="Vocoder (vocoder_id)",
162
+ ),
163
  ],
164
  outputs=[
165
+ gr.Audio(
166
+ label="الصوت الناتج",
167
+ type="numpy", # Gradio يرجّع (sample_rate, data)
168
+ ),
169
+ gr.Textbox(
170
+ label="الحالة",
171
+ interactive=False,
172
+ ),
173
  ],
174
  title="Arabic TTS (ONNX / CPU)",
175
+ description=(
176
+ "نموذج tts_arabic لتحويل النص العربي إلى كلام على CPU.\n"
177
+ "الـAPI محمية بـ API Key عبر الهيدر x-api-key."
178
+ ),
179
  )
180
 
 
 
 
181
  if __name__ == "__main__":
182
  demo.launch()