Update app.py
Browse files
app.py
CHANGED
|
@@ -10,6 +10,7 @@ import logging
|
|
| 10 |
import random
|
| 11 |
import base64
|
| 12 |
import atexit
|
|
|
|
| 13 |
from datetime import datetime, timedelta
|
| 14 |
from itertools import cycle
|
| 15 |
from flask import Flask, request, jsonify, render_template, send_file
|
|
@@ -186,7 +187,8 @@ def generate_podcast_in_background(task_id, system_prompt, safety_settings):
|
|
| 186 |
if not raw_text: raise ValueError("بدون پاسخ از مدل هوش مصنوعی")
|
| 187 |
|
| 188 |
json_string = None
|
| 189 |
-
match = re.search(r"```json\s*(\{.*?\})\s*
|
|
|
|
| 190 |
if match: json_string = match.group(1)
|
| 191 |
else:
|
| 192 |
s_idx = raw_text.find('{')
|
|
@@ -291,20 +293,41 @@ Dialogue rules: No stage directions like [laugh], (sigh). Just spoken words."""
|
|
| 291 |
|
| 292 |
combined_audio = AudioSegment.empty()
|
| 293 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
for index, turn in enumerate(script_turns):
|
| 295 |
speaker_id = turn.get("speaker_id")
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
idx, audio_seg = call_worker(index, payload)
|
| 300 |
|
| 301 |
-
|
| 302 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
|
| 309 |
# 3. میکس و ذخیره فایل
|
| 310 |
with tasks_lock:
|
|
|
|
| 10 |
import random
|
| 11 |
import base64
|
| 12 |
import atexit
|
| 13 |
+
import concurrent.futures
|
| 14 |
from datetime import datetime, timedelta
|
| 15 |
from itertools import cycle
|
| 16 |
from flask import Flask, request, jsonify, render_template, send_file
|
|
|
|
| 187 |
if not raw_text: raise ValueError("بدون پاسخ از مدل هوش مصنوعی")
|
| 188 |
|
| 189 |
json_string = None
|
| 190 |
+
match = re.search(r"```json\s*(\{.*?\})\s*
|
| 191 |
+
```", raw_text, re.DOTALL)
|
| 192 |
if match: json_string = match.group(1)
|
| 193 |
else:
|
| 194 |
s_idx = raw_text.find('{')
|
|
|
|
| 293 |
|
| 294 |
combined_audio = AudioSegment.empty()
|
| 295 |
|
| 296 |
+
valid_speaker_ids = [s['id'] for s in speakers]
|
| 297 |
+
default_speaker_id = speakers[0]['id'] if speakers else "Charon"
|
| 298 |
+
|
| 299 |
+
payloads = []
|
| 300 |
for index, turn in enumerate(script_turns):
|
| 301 |
speaker_id = turn.get("speaker_id")
|
| 302 |
+
# بررسی صحت شناسه گوینده، اگر معتبر نبود گوینده اول انتخاب میشود
|
| 303 |
+
if speaker_id not in valid_speaker_ids:
|
| 304 |
+
speaker_id = default_speaker_id
|
|
|
|
| 305 |
|
| 306 |
+
dialogue = turn.get("dialogue")
|
| 307 |
+
payloads.append((index, {"text": dialogue, "speaker": speaker_id, "temperature": 0.9, "is_custom": False}))
|
| 308 |
+
|
| 309 |
+
audio_segments = [None] * total_turns
|
| 310 |
+
|
| 311 |
+
# ارسال همزمان تمام درخواستهای صدا به کارگرها
|
| 312 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=min(20, total_turns)) as executor:
|
| 313 |
+
futures = {executor.submit(call_worker, idx, payload): idx for idx, payload in payloads}
|
| 314 |
+
completed_count = 0
|
| 315 |
+
for future in concurrent.futures.as_completed(futures):
|
| 316 |
+
idx = futures[future]
|
| 317 |
+
res_idx, audio_seg = future.result()
|
| 318 |
|
| 319 |
+
if not audio_seg:
|
| 320 |
+
raise ValueError(f"خطا در تولید صدای نوبت {idx+1} از سرورهای پردازش صدا")
|
| 321 |
+
|
| 322 |
+
audio_segments[idx] = audio_seg
|
| 323 |
+
completed_count += 1
|
| 324 |
+
|
| 325 |
+
with tasks_lock:
|
| 326 |
+
tasks[task_id]['progress'] = f'در حال تولید صدا ({completed_count} از {total_turns} تکمیل شده)'
|
| 327 |
+
|
| 328 |
+
# چسباندن فایلها به یکدیگر بر اساس ترتیب
|
| 329 |
+
for seg in audio_segments:
|
| 330 |
+
combined_audio += seg
|
| 331 |
|
| 332 |
# 3. میکس و ذخیره فایل
|
| 333 |
with tasks_lock:
|