Spaces:
Sleeping
Sleeping
Commit
·
39c78ba
1
Parent(s):
ece1c42
Video işleme fonksiyonuna thread güvenliği eklendi. Model kullanımını senkronize etmek için lock mekanizması kullanıldı. Hata yönetimi ve işlem sonuçları için detaylı istatistikler eklendi.
Browse files- main-videopluskazanim.py +42 -15
main-videopluskazanim.py
CHANGED
@@ -37,6 +37,7 @@ import torch
|
|
37 |
import functools
|
38 |
import asyncio
|
39 |
import concurrent.futures
|
|
|
40 |
import kazanim_id_konu_isim_dict_list as kazanimlar
|
41 |
import logging
|
42 |
import whisper
|
@@ -143,8 +144,11 @@ logging.basicConfig(stream=sys.stdout,
|
|
143 |
# HF Space'lerde çok aggressive olmamak için worker sayısını azalttık
|
144 |
executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)
|
145 |
|
|
|
|
|
|
|
146 |
async def process_single_video(file: UploadFile, model, language: str) -> VideoResult:
|
147 |
-
"""Tek bir video dosyasını işle - paralel kullanım için"""
|
148 |
if not file.filename.lower().endswith(('.mp4', '.wav', '.mp3', '.m4a', '.flac')):
|
149 |
return VideoResult(id=file.filename, text="")
|
150 |
|
@@ -155,20 +159,28 @@ async def process_single_video(file: UploadFile, model, language: str) -> VideoR
|
|
155 |
temp_file_path = temp_file.name
|
156 |
|
157 |
def transcribe_sync():
|
158 |
-
"""Senkron transcription - thread pool'da çalışacak -
|
159 |
try:
|
160 |
-
#
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
except Exception as e:
|
170 |
-
print(f"Video işleme hatası ({file.filename}): {e}")
|
171 |
return ""
|
|
|
172 |
finally:
|
173 |
# Geçici dosyayı temizle
|
174 |
if os.path.exists(temp_file_path):
|
@@ -249,23 +261,38 @@ async def transcribe_videos(files: List[UploadFile] = File(...),
|
|
249 |
tasks = [process_single_video(file, model, language) for file in chunk]
|
250 |
chunk_results = await asyncio.gather(*tasks, return_exceptions=True)
|
251 |
|
252 |
-
# Exception'ları handle et
|
|
|
|
|
253 |
for j, result in enumerate(chunk_results):
|
254 |
if isinstance(result, Exception):
|
255 |
print(f"❌ Dosya {chunk[j].filename} işlenirken hata: {result}")
|
256 |
final_results.append(VideoResult(id=chunk[j].filename, text=""))
|
|
|
257 |
else:
|
258 |
final_results.append(result)
|
|
|
|
|
|
|
|
|
|
|
259 |
|
260 |
-
print(f"✅ Chunk {i//chunk_size + 1} tamamlandı!")
|
261 |
|
262 |
# Memory'yi rahatlatmak için küçük bir bekleme (HF Space için)
|
263 |
if i + chunk_size < len(files):
|
264 |
await asyncio.sleep(0.1)
|
265 |
|
266 |
dt = time.time() - t0
|
|
|
|
|
|
|
|
|
|
|
|
|
267 |
print(f"✅ Whisper PARALEL done | took {dt:.2f}s")
|
268 |
-
print(f"🎯
|
|
|
269 |
|
270 |
return WhisperResponse(model=model_name, results=final_results)
|
271 |
|
|
|
37 |
import functools
|
38 |
import asyncio
|
39 |
import concurrent.futures
|
40 |
+
import threading
|
41 |
import kazanim_id_konu_isim_dict_list as kazanimlar
|
42 |
import logging
|
43 |
import whisper
|
|
|
144 |
# HF Space'lerde çok aggressive olmamak için worker sayısını azalttık
|
145 |
executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)
|
146 |
|
147 |
+
# Thread-safe model kullanımı için lock
|
148 |
+
whisper_lock = threading.Lock()
|
149 |
+
|
150 |
async def process_single_video(file: UploadFile, model, language: str) -> VideoResult:
|
151 |
+
"""Tek bir video dosyasını işle - THREAD SAFE paralel kullanım için"""
|
152 |
if not file.filename.lower().endswith(('.mp4', '.wav', '.mp3', '.m4a', '.flac')):
|
153 |
return VideoResult(id=file.filename, text="")
|
154 |
|
|
|
159 |
temp_file_path = temp_file.name
|
160 |
|
161 |
def transcribe_sync():
|
162 |
+
"""Senkron transcription - thread pool'da çalışacak - THREAD SAFE"""
|
163 |
try:
|
164 |
+
# 🔒 THREAD SAFETY: Model kullanımını serialize et
|
165 |
+
with whisper_lock:
|
166 |
+
print(f"🔄 {file.filename}: Model kullanımı başlıyor...")
|
167 |
+
result = model.transcribe(
|
168 |
+
temp_file_path,
|
169 |
+
language=language.lower(),
|
170 |
+
verbose=False
|
171 |
+
)
|
172 |
+
text = result['text'].strip()
|
173 |
+
|
174 |
+
# Model çıktısının bir kısmını logla (debug için)
|
175 |
+
preview = text[:150] + "..." if len(text) > 150 else text
|
176 |
+
print(f"📝 {file.filename}: {preview}")
|
177 |
+
|
178 |
+
return text
|
179 |
+
|
180 |
except Exception as e:
|
181 |
+
print(f"❌ Video işleme hatası ({file.filename}): {e}")
|
182 |
return ""
|
183 |
+
|
184 |
finally:
|
185 |
# Geçici dosyayı temizle
|
186 |
if os.path.exists(temp_file_path):
|
|
|
261 |
tasks = [process_single_video(file, model, language) for file in chunk]
|
262 |
chunk_results = await asyncio.gather(*tasks, return_exceptions=True)
|
263 |
|
264 |
+
# Exception'ları handle et + SUCCESS/ERROR COUNT
|
265 |
+
success_count = 0
|
266 |
+
error_count = 0
|
267 |
for j, result in enumerate(chunk_results):
|
268 |
if isinstance(result, Exception):
|
269 |
print(f"❌ Dosya {chunk[j].filename} işlenirken hata: {result}")
|
270 |
final_results.append(VideoResult(id=chunk[j].filename, text=""))
|
271 |
+
error_count += 1
|
272 |
else:
|
273 |
final_results.append(result)
|
274 |
+
# Başarılı sayısı = boş olmayan text'ler
|
275 |
+
if result.text.strip():
|
276 |
+
success_count += 1
|
277 |
+
else:
|
278 |
+
error_count += 1
|
279 |
|
280 |
+
print(f"✅ Chunk {i//chunk_size + 1} tamamlandı! ✅{success_count} ❌{error_count}")
|
281 |
|
282 |
# Memory'yi rahatlatmak için küçük bir bekleme (HF Space için)
|
283 |
if i + chunk_size < len(files):
|
284 |
await asyncio.sleep(0.1)
|
285 |
|
286 |
dt = time.time() - t0
|
287 |
+
|
288 |
+
# Final istatistikler
|
289 |
+
total_success = len([r for r in final_results if r.text.strip()])
|
290 |
+
total_failed = len(final_results) - total_success
|
291 |
+
success_rate = (total_success / len(final_results) * 100) if final_results else 0
|
292 |
+
|
293 |
print(f"✅ Whisper PARALEL done | took {dt:.2f}s")
|
294 |
+
print(f"🎯 SONUÇ: {len(final_results)} video | ✅{total_success} başarılı | ❌{total_failed} hatalı | 📊{success_rate:.1f}% başarı oranı")
|
295 |
+
print(f"⚡ Hız: {len(final_results)/dt:.1f} video/saniye (chunk_size={chunk_size})")
|
296 |
|
297 |
return WhisperResponse(model=model_name, results=final_results)
|
298 |
|