Hamed744 commited on
Commit
6ddd177
·
verified ·
1 Parent(s): 4a4b4c1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +7 -20
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py - نسخه کامل و بهینه‌سازی شده برای پایداری بالا
2
 
3
  import os
4
  import sys
@@ -25,12 +25,9 @@ except ImportError:
25
 
26
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
27
 
28
- # --- START: بخش جدید برای مدیریت بهینه Client ها ---
29
- GEMINI_CLIENTS_CACHE = {} # یک دیکشنری برای کش کردن client ها
30
- CLIENT_CACHE_LOCK = threading.Lock() # یک قفل برای دسترسی امن به کش
31
- # --- END: بخش جدید ---
32
 
33
- # --- منطق مدیریت API Key ---
34
  ALL_API_KEYS: list[str] = []
35
  NEXT_KEY_INDEX: int = 0
36
  KEY_LOCK: threading.Lock = threading.Lock()
@@ -48,6 +45,10 @@ def get_next_api_key_and_client():
48
  """
49
  تغییر اصلی: این تابع هم کلید و هم یک client کش‌شده یا جدید را برمی‌گرداند.
50
  """
 
 
 
 
51
  with KEY_LOCK:
52
  if not ALL_API_KEYS:
53
  return None, None, -1
@@ -57,13 +58,10 @@ def get_next_api_key_and_client():
57
  key_display_index = current_index + 1
58
  NEXT_KEY_INDEX += 1
59
 
60
- # حالا که کلید را داریم، client مربوط به آن را از کش دریافت می‌کنیم
61
  with CLIENT_CACHE_LOCK:
62
  if key_to_use in GEMINI_CLIENTS_CACHE:
63
- # اگر client در کش بود، همان را برمی‌گردانیم
64
  client = GEMINI_CLIENTS_CACHE[key_to_use]
65
  else:
66
- # اگر نبود، یکی جدید می‌سازیم و در کش ذخیره می‌کنیم
67
  logging.info(f"Creating new Gemini client for key ending in ...{key_to_use[-4:]}")
68
  client = genai.Client(api_key=key_to_use)
69
  GEMINI_CLIENTS_CACHE[key_to_use] = client
@@ -75,7 +73,6 @@ FIXED_MODEL_NAME = "gemini-2.5-flash-preview-tts"
75
  DEFAULT_MAX_CHUNK_SIZE = 3800
76
  DEFAULT_SLEEP_BETWEEN_REQUESTS = 8
77
 
78
- # ... (توابع کمکی دیگر مثل save_binary_file, convert_to_wav و ... بدون تغییر اینجا قرار می‌گیرند) ...
79
  def save_binary_file(file_name, data):
80
  try:
81
  with open(file_name, "wb") as f: f.write(data)
@@ -128,22 +125,17 @@ def merge_audio_files_func(file_paths, output_path):
128
  combined.export(output_path, format="wav")
129
  return True
130
  except Exception as e: logging.error(f"❌ خطا در ادغام فایل‌های صوتی: {e}"); return False
131
- # ... (پایان توابع کمکی) ...
132
-
133
 
134
- # --- منطق اصلی تولید صدا (با استفاده از Client کش شده) ---
135
  def generate_audio_chunk_with_retry(chunk_text, prompt_text, voice, temp, session_id):
136
  if not ALL_API_KEYS: raise Exception("هیچ کلید API برای پردازش در دسترس نیست.")
137
 
138
  for _ in range(len(ALL_API_KEYS)):
139
- # تغییر اصلی: دریافت همزمان کلید و client
140
  selected_api_key, client, key_idx_display = get_next_api_key_and_client()
141
  if not client:
142
  break
143
 
144
  logging.info(f"[{session_id}] ⚙️ تلاش برای تولید قطعه با کلید API شماره {key_idx_display}")
145
  try:
146
- # دیگر نیازی به ساخت client جدید نیست!
147
  final_text = f'"{prompt_text}"\n{chunk_text}' if prompt_text and prompt_text.strip() else chunk_text
148
  contents = [types.Content(role="user", parts=[types.Part.from_text(text=final_text)])]
149
  config = types.GenerateContentConfig(temperature=temp, response_modalities=["audio"],
@@ -156,17 +148,14 @@ def generate_audio_chunk_with_retry(chunk_text, prompt_text, voice, temp, sessio
156
  return response.candidates[0].content.parts[0].inline_data
157
  except Exception as e:
158
  logging.error(f"[{session_id}] ❌ خطا در تولید قطعه با کلید شماره {key_idx_display}: {e}.")
159
- # اگر خطا مربوط به احراز هویت بود، client را از کش حذف می‌کنیم تا دفعه بعد دوباره ساخته شود
160
  if "authentication" in str(e).lower():
161
  with CLIENT_CACHE_LOCK:
162
  if selected_api_key in GEMINI_CLIENTS_CACHE:
163
  del GEMINI_CLIENTS_CACHE[selected_api_key]
164
  logging.warning(f"Client for key ...{selected_api_key[-4:]} removed from cache due to auth error.")
165
-
166
  return None
167
 
168
  def core_generate_audio(text_input, prompt_input, selected_voice, temperature_val, session_id):
169
- # این تابع بدون تغییر باقی می‌ماند
170
  logging.info(f"[{session_id}] 🚀 شروع فرآیند تولید صدا.")
171
  temp_dir = f"temp_{session_id}"
172
  os.makedirs(temp_dir, exist_ok=True)
@@ -207,10 +196,8 @@ def core_generate_audio(text_input, prompt_input, selected_voice, temperature_va
207
  if os.path.exists(temp_dir):
208
  shutil.rmtree(temp_dir)
209
 
210
- # --- اجرای کدهای اولیه برنامه ---
211
  _init_api_keys()
212
 
213
- # --- تعریف اپلیکیشن FastAPI ---
214
  app = FastAPI(title="Alpha TTS Worker API")
215
 
216
  class TTSRequest(BaseModel):
 
1
+ # app.py - نسخه کامل و بهینه‌سازی شده برای پایداری بالا (با اصلاح نهایی)
2
 
3
  import os
4
  import sys
 
25
 
26
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
27
 
28
+ GEMINI_CLIENTS_CACHE = {}
29
+ CLIENT_CACHE_LOCK = threading.Lock()
 
 
30
 
 
31
  ALL_API_KEYS: list[str] = []
32
  NEXT_KEY_INDEX: int = 0
33
  KEY_LOCK: threading.Lock = threading.Lock()
 
45
  """
46
  تغییر اصلی: این تابع هم کلید و هم یک client کش‌شده یا جدید را برمی‌گرداند.
47
  """
48
+ # --- START: خط اصلاح شده اینجاست ---
49
+ global NEXT_KEY_INDEX
50
+ # --- END: خط اصلاح شده ---
51
+
52
  with KEY_LOCK:
53
  if not ALL_API_KEYS:
54
  return None, None, -1
 
58
  key_display_index = current_index + 1
59
  NEXT_KEY_INDEX += 1
60
 
 
61
  with CLIENT_CACHE_LOCK:
62
  if key_to_use in GEMINI_CLIENTS_CACHE:
 
63
  client = GEMINI_CLIENTS_CACHE[key_to_use]
64
  else:
 
65
  logging.info(f"Creating new Gemini client for key ending in ...{key_to_use[-4:]}")
66
  client = genai.Client(api_key=key_to_use)
67
  GEMINI_CLIENTS_CACHE[key_to_use] = client
 
73
  DEFAULT_MAX_CHUNK_SIZE = 3800
74
  DEFAULT_SLEEP_BETWEEN_REQUESTS = 8
75
 
 
76
  def save_binary_file(file_name, data):
77
  try:
78
  with open(file_name, "wb") as f: f.write(data)
 
125
  combined.export(output_path, format="wav")
126
  return True
127
  except Exception as e: logging.error(f"❌ خطا در ادغام فایل‌های صوتی: {e}"); return False
 
 
128
 
 
129
  def generate_audio_chunk_with_retry(chunk_text, prompt_text, voice, temp, session_id):
130
  if not ALL_API_KEYS: raise Exception("هیچ کلید API برای پردازش در دسترس نیست.")
131
 
132
  for _ in range(len(ALL_API_KEYS)):
 
133
  selected_api_key, client, key_idx_display = get_next_api_key_and_client()
134
  if not client:
135
  break
136
 
137
  logging.info(f"[{session_id}] ⚙️ تلاش برای تولید قطعه با کلید API شماره {key_idx_display}")
138
  try:
 
139
  final_text = f'"{prompt_text}"\n{chunk_text}' if prompt_text and prompt_text.strip() else chunk_text
140
  contents = [types.Content(role="user", parts=[types.Part.from_text(text=final_text)])]
141
  config = types.GenerateContentConfig(temperature=temp, response_modalities=["audio"],
 
148
  return response.candidates[0].content.parts[0].inline_data
149
  except Exception as e:
150
  logging.error(f"[{session_id}] ❌ خطا در تولید قطعه با کلید شماره {key_idx_display}: {e}.")
 
151
  if "authentication" in str(e).lower():
152
  with CLIENT_CACHE_LOCK:
153
  if selected_api_key in GEMINI_CLIENTS_CACHE:
154
  del GEMINI_CLIENTS_CACHE[selected_api_key]
155
  logging.warning(f"Client for key ...{selected_api_key[-4:]} removed from cache due to auth error.")
 
156
  return None
157
 
158
  def core_generate_audio(text_input, prompt_input, selected_voice, temperature_val, session_id):
 
159
  logging.info(f"[{session_id}] 🚀 شروع فرآیند تولید صدا.")
160
  temp_dir = f"temp_{session_id}"
161
  os.makedirs(temp_dir, exist_ok=True)
 
196
  if os.path.exists(temp_dir):
197
  shutil.rmtree(temp_dir)
198
 
 
199
  _init_api_keys()
200
 
 
201
  app = FastAPI(title="Alpha TTS Worker API")
202
 
203
  class TTSRequest(BaseModel):