suprimedev commited on
Commit
901e3e9
·
verified ·
1 Parent(s): f25fdc1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -53
app.py CHANGED
@@ -16,48 +16,54 @@ from fastapi.responses import JSONResponse
16
 
17
  warnings.filterwarnings("ignore")
18
 
19
- # ذخیره‌سازی نتایج
20
  results_cache = {}
21
  cache_lock = threading.Lock()
22
 
23
  # FastAPI instance برای API endpoints
24
  app = FastAPI()
25
 
26
- # تابع برای پاکسازی cache قدیمی
27
  def cleanup_old_cache():
28
  while True:
29
  time.sleep(3600) # هر ساعت
30
  with cache_lock:
31
  current_time = datetime.now()
32
  keys_to_remove = []
33
- for key, value in results_cache.items():
34
- if current_time - value['timestamp'] > timedelta(hours=24):
35
- keys_to_remove.append(key)
36
- for key in keys_to_remove:
37
- del results_cache[key]
 
 
 
 
 
 
38
  if keys_to_remove:
39
- print(f"[CACHE] {len(keys_to_remove)} نتیجه قدیمی پاک شد.")
40
 
41
  cleanup_thread = threading.Thread(target=cleanup_old_cache, daemon=True)
42
  cleanup_thread.start()
43
 
44
- def get_cache_key(video_url, language):
45
- """ایجاد کلید یکتا برای cache"""
46
  return hashlib.md5(f"{video_url}_{language}".encode()).hexdigest()
47
 
48
- def save_result_to_cache(cache_key, video_url, language, mp3_path, text, status_msg, processing=False):
49
- """ذخیره نتیجه در cache"""
50
- # کپی فایل MP3 به مکان دائمی
51
  cache_mp3_path = None
52
  if mp3_path and os.path.exists(mp3_path):
53
- cache_mp3_path = f"cache_{cache_key}.mp3"
54
  shutil.copy2(mp3_path, cache_mp3_path)
55
 
56
  with cache_lock:
57
- results_cache[cache_key] = {
58
  'timestamp': datetime.now(),
59
  'mp3_path': cache_mp3_path,
60
- 'text': text,
61
  'status_msg': status_msg,
62
  'video_url': video_url,
63
  'language': language,
@@ -65,53 +71,45 @@ def save_result_to_cache(cache_key, video_url, language, mp3_path, text, status_
65
  'completed': not processing and (text is not None or status_msg.startswith("خطا"))
66
  }
67
 
68
- print(f"[CACHE] نتیجه ذخیره شد: {cache_key} (processing: {processing})")
69
 
70
- def get_result_from_cache(cache_key):
71
- """دریافت نتیجه از cache"""
72
  with cache_lock:
73
- if cache_key in results_cache:
74
- result = results_cache[cache_key]
75
- print(f"[CACHE] نتیجه یافت شد: {cache_key}")
76
  return result
77
  return None
78
 
79
  def convert_to_mp3_and_transcribe_wrapper(video_url, language):
80
- """Wrapper function که cache_key را در ابتدا برمی‌گرداند"""
81
  if not video_url:
82
  return None, None, "لینک ویدیو را وارد کنید.", None
83
 
84
- # ایجاد cache key
85
- cache_key = get_cache_key(video_url, language)
86
 
87
  # چک کردن cache
88
- cached_result = get_result_from_cache(cache_key)
89
  if cached_result and cached_result['completed']:
90
  return (cached_result['mp3_path'],
91
  cached_result['text'],
92
  f"[از حافظ��] {cached_result['status_msg']}",
93
- cache_key)
94
 
95
  # اگر در حال پردازش است
96
  if cached_result and cached_result['processing']:
97
- return None, None, "در حال پردازش... لطفاً صبر کنید.", cache_key
98
 
99
  # ثبت شروع پردازش
100
- save_result_to_cache(cache_key, video_url, language, None, None, "در حال پردازش...", processing=True)
101
 
102
- # پردازش در background
103
- def process_async():
104
- try:
105
- mp3_path, text, status_msg = convert_to_mp3_and_transcribe(video_url, language)
106
- save_result_to_cache(cache_key, video_url, language, mp3_path, text, status_msg, processing=False)
107
- except Exception as e:
108
- save_result_to_cache(cache_key, video_url, language, None, None, f"خطا: {str(e)}", processing=False)
109
-
110
- # شروع پردازش (برای سادگی، همینجا انجام می‌دهیم - در production باید async باشد)
111
  mp3_path, text, status_msg = convert_to_mp3_and_transcribe(video_url, language)
112
- save_result_to_cache(cache_key, video_url, language, mp3_path, text, status_msg, processing=False)
113
 
114
- return mp3_path, text, status_msg, cache_key
115
 
116
  def convert_to_mp3_and_transcribe(video_url, language):
117
  """تابع اصلی پردازش (بدون cache)"""
@@ -276,29 +274,44 @@ def transcribe_audio(mp3_path, progress, language, chunk_length_ms=60000, overla
276
 
277
  return final_text, ""
278
 
279
- # API endpoint
280
- @app.get("/api/check_result/{cache_key}")
281
- async def check_result_api(cache_key: str):
282
- """API endpoint برای بررسی وضعیت نتیجه"""
283
- result = get_result_from_cache(cache_key)
284
 
285
  if not result:
286
- return JSONResponse({"status": 0, "message": "Not found"})
287
 
288
  if result['processing']:
289
- return JSONResponse({"status": 0, "message": "Processing"})
290
 
291
  if result['completed']:
292
  return JSONResponse({
293
  "status": 1,
294
- "text": result['text'],
295
- "mp3_available": result['mp3_path'] is not None,
296
- "status_message": result['status_msg']
 
 
297
  })
298
 
299
  return JSONResponse({"status": 0, "message": "Unknown status"})
300
 
301
- # رابط Gradio
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  iface = gr.Interface(
303
  fn=convert_to_mp3_and_transcribe_wrapper,
304
  inputs=[
@@ -316,9 +329,9 @@ iface = gr.Interface(
316
  gr.File(label="دانلود MP3"),
317
  gr.Textbox(label="متن استخراج‌شده", lines=10),
318
  gr.Textbox(label="وضعیت"),
319
- gr.Textbox(label="Cache Key", visible=True)
320
  ],
321
- title="تبدیل ویدیو به MP3 و متن",
322
  examples=[
323
  ["https://www.youtube.com/watch?v=5qap5aO4i9A", "fa-IR"],
324
  ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "en-US"]
 
16
 
17
  warnings.filterwarnings("ignore")
18
 
19
+ # ذخیره‌سازی نتایج (متن همیشه ذخیره می‌شود)
20
  results_cache = {}
21
  cache_lock = threading.Lock()
22
 
23
  # FastAPI instance برای API endpoints
24
  app = FastAPI()
25
 
26
+ # تابع برای پاکسازی cache قدیمی (بهبود: فقط event_idهای کامل‌شده و قدیمی را پاک کن)
27
  def cleanup_old_cache():
28
  while True:
29
  time.sleep(3600) # هر ساعت
30
  with cache_lock:
31
  current_time = datetime.now()
32
  keys_to_remove = []
33
+ for event_id, value in results_cache.items():
34
+ if value['completed'] and (current_time - value['timestamp'] > timedelta(hours=24)):
35
+ keys_to_remove.append(event_id)
36
+ # پاک کردن فایل MP3 اگر وجود دارد
37
+ if value['mp3_path'] and os.path.exists(value['mp3_path']):
38
+ try:
39
+ os.remove(value['mp3_path'])
40
+ except:
41
+ pass
42
+ for event_id in keys_to_remove:
43
+ del results_cache[event_id]
44
  if keys_to_remove:
45
+ print(f"[CACHE] {len(keys_to_remove)} event_id قدیمی پاک شد.")
46
 
47
  cleanup_thread = threading.Thread(target=cleanup_old_cache, daemon=True)
48
  cleanup_thread.start()
49
 
50
+ def get_event_id(video_url, language):
51
+ """ایجاد event_id یکتا بلاً cache_key)"""
52
  return hashlib.md5(f"{video_url}_{language}".encode()).hexdigest()
53
 
54
+ def save_result_to_cache(event_id, video_url, language, mp3_path, text, status_msg, processing=False):
55
+ """ذخیره نتیجه در cache (متن همیشه ذخیره می‌شود)"""
56
+ # کپی فایل MP3 به مکان دائمی اگر موجود باشد
57
  cache_mp3_path = None
58
  if mp3_path and os.path.exists(mp3_path):
59
+ cache_mp3_path = f"cache_{event_id}.mp3"
60
  shutil.copy2(mp3_path, cache_mp3_path)
61
 
62
  with cache_lock:
63
+ results_cache[event_id] = {
64
  'timestamp': datetime.now(),
65
  'mp3_path': cache_mp3_path,
66
+ 'text': text, # متن همیشه ذخیره می‌شود (حتی اگر None باشد)
67
  'status_msg': status_msg,
68
  'video_url': video_url,
69
  'language': language,
 
71
  'completed': not processing and (text is not None or status_msg.startswith("خطا"))
72
  }
73
 
74
+ print(f"[CACHE] نتیجه ذخیره شد: {event_id} (processing: {processing}, text_length: {len(text) if text else 0})")
75
 
76
+ def get_result_from_cache(event_id):
77
+ """دریافت نتیجه از cache با event_id"""
78
  with cache_lock:
79
+ if event_id in results_cache:
80
+ result = results_cache[event_id]
81
+ print(f"[CACHE] نتیجه یافت شد: {event_id}")
82
  return result
83
  return None
84
 
85
  def convert_to_mp3_and_transcribe_wrapper(video_url, language):
86
+ """Wrapper function که event_id را در ابتدا برمی‌گرداند"""
87
  if not video_url:
88
  return None, None, "لینک ویدیو را وارد کنید.", None
89
 
90
+ # ایجاد event_id
91
+ event_id = get_event_id(video_url, language)
92
 
93
  # چک کردن cache
94
+ cached_result = get_result_from_cache(event_id)
95
  if cached_result and cached_result['completed']:
96
  return (cached_result['mp3_path'],
97
  cached_result['text'],
98
  f"[از حافظ��] {cached_result['status_msg']}",
99
+ event_id)
100
 
101
  # اگر در حال پردازش است
102
  if cached_result and cached_result['processing']:
103
+ return None, None, "در حال پردازش... لطفاً صبر کنید.", event_id
104
 
105
  # ثبت شروع پردازش
106
+ save_result_to_cache(event_id, video_url, language, None, None, "در حال پردازش...", processing=True)
107
 
108
+ # پردازش در background (برای سادگی، همینجا انجام می‌دهیم - در production async کنید)
 
 
 
 
 
 
 
 
109
  mp3_path, text, status_msg = convert_to_mp3_and_transcribe(video_url, language)
110
+ save_result_to_cache(event_id, video_url, language, mp3_path, text, status_msg, processing=False)
111
 
112
+ return mp3_path, text, status_msg, event_id
113
 
114
  def convert_to_mp3_and_transcribe(video_url, language):
115
  """تابع اصلی پردازش (بدون cache)"""
 
274
 
275
  return final_text, ""
276
 
277
+ # API endpoints (بهبود: event_id به جای cache_key، و endpoint جدید برای لیست)
278
+ @app.get("/api/check_result/{event_id}")
279
+ async def check_result_api(event_id: str):
280
+ """API endpoint برای بررسی وضعیت نتیجه با event_id (متن اگر کامل شده برگردانده می‌شود)"""
281
+ result = get_result_from_cache(event_id)
282
 
283
  if not result:
284
+ return JSONResponse({"status": 0, "message": "Event ID not found"})
285
 
286
  if result['processing']:
287
+ return JSONResponse({"status": 0, "message": "Processing..."})
288
 
289
  if result['completed']:
290
  return JSONResponse({
291
  "status": 1,
292
+ "event_id": event_id,
293
+ "text": result['text'], # متن استخراج‌شده همیشه برگردانده می‌شود
294
+ "mp3_available": result['mp3_path'] is not None and os.path.exists(result['mp3_path']),
295
+ "status_message": result['status_msg'],
296
+ "timestamp": result['timestamp'].isoformat()
297
  })
298
 
299
  return JSONResponse({"status": 0, "message": "Unknown status"})
300
 
301
+ @app.get("/api/list_events")
302
+ async def list_events_api(limit: int = 10):
303
+ """API endpoint جدید: لیست event_idهای اخیر (برای مدیریت)"""
304
+ with cache_lock:
305
+ recent_events = sorted(
306
+ [(eid, data['timestamp']) for eid, data in results_cache.items() if data['completed']],
307
+ key=lambda x: x[1],
308
+ reverse=True
309
+ )[:limit]
310
+ return JSONResponse({
311
+ "events": [{"event_id": eid, "timestamp": ts.isoformat()} for eid, ts in recent_events]
312
+ })
313
+
314
+ # رابط Gradio (بهبود: event_id برجسته‌تر)
315
  iface = gr.Interface(
316
  fn=convert_to_mp3_and_transcribe_wrapper,
317
  inputs=[
 
329
  gr.File(label="دانلود MP3"),
330
  gr.Textbox(label="متن استخراج‌شده", lines=10),
331
  gr.Textbox(label="وضعیت"),
332
+ gr.Textbox(label="Event ID (برای استعلام API)", visible=True, info="این ID را برای چک کردن نتیجه از API استفاده کنید: /api/check_result/{event_id}")
333
  ],
334
+ title="تبدیل ویدیو به MP3 و متن (با ذخیره event_id)",
335
  examples=[
336
  ["https://www.youtube.com/watch?v=5qap5aO4i9A", "fa-IR"],
337
  ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "en-US"]