Jedi09's picture
Update app.py
81d3c4d verified
import gradio as gr
from faster_whisper import WhisperModel
import time
import os
import tempfile
import requests
import traceback
# ==================== CONFIG & MODELS ====================
# 1. WHISPER MODEL (Ses Deşifre - CPU/Local)
MODEL_SIZE = "medium"
model = None
try:
print(f"📥 Whisper {MODEL_SIZE} modeli yükleniyor...")
model = WhisperModel(MODEL_SIZE, device="cpu", compute_type="int8")
print("✅ Whisper Modeli Hazır!")
except Exception as e:
print(f"❌ Whisper Yükleme Hatası: {e}")
model = None
# ==================== AI API FUNCTIONS (Hugging Face Router) ====================
def call_huggingface_api(prompt, api_key):
"""
Hugging Face Serverless Inference API (Router Endpoint).
OpenAI uyumlu chat/completions formatı kullanır.
"""
# Önce environment variable kontrol et, yoksa UI'dan gelen değeri kullan
token = os.environ.get("HF_TOKEN") or api_key
if not token:
return "⚠️ HF Token bulunamadı. Secret olarak veya kutuya girin."
if not token.startswith("hf_"):
return "⚠️ Token 'hf_' ile başlamalıdır."
# Sırayla deneyeceğimiz modeller
models = [
"Qwen/Qwen2.5-72B-Instruct",
"meta-llama/Llama-3.3-70B-Instruct",
"mistralai/Mistral-7B-Instruct-v0.3",
"microsoft/Phi-3-mini-4k-instruct"
]
# Doğru endpoint: /v1/chat/completions
url = "https://router.huggingface.co/v1/chat/completions"
print("=" * 50)
print(f"🔗 API URL: {url}")
secret_source = "ENV" if os.environ.get("HF_TOKEN") else "UI"
print(f"🔑 Token ({secret_source}): {token[:10]}...")
print("=" * 50)
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
for model_id in models:
payload = {
"model": model_id,
"messages": [
{"role": "system", "content": "Sen yardımsever bir Türkçe asistansın."},
{"role": "user", "content": prompt}
],
"max_tokens": 512,
"temperature": 0.3
}
try:
print(f"\n📡 [{model_id}] İstek gönderiliyor...")
response = requests.post(url, headers=headers, json=payload, timeout=90)
print(f"📥 [{model_id}] HTTP Status: {response.status_code}")
if response.status_code == 200:
result = response.json()
print(f"✅ [{model_id}] BAŞARILI!")
if "choices" in result and len(result["choices"]) > 0:
return result["choices"][0]["message"]["content"].strip()
return f"❌ Beklenmedik yanıt: {result}"
elif response.status_code in [503, 529]:
print(f"⚠️ [{model_id}] Model meşgul/yükleniyor...")
continue
elif response.status_code == 404:
print(f"⚠️ [{model_id}] Model bulunamadı")
continue
elif response.status_code == 401:
print(f"❌ [{model_id}] YETKİSİZ! Token kontrol edin.")
print(f" Yanıt: {response.text[:300]}")
return "❌ Token geçersiz. Lütfen 'Fine-grained' token oluşturup 'Inference' yetkisi verin."
elif response.status_code == 422:
print(f"⚠️ [{model_id}] Format hatası: {response.text[:200]}")
continue
else:
error_text = response.text[:300] if len(response.text) > 300 else response.text
print(f"❌ [{model_id}] HATA ({response.status_code}): {error_text}")
continue
except requests.exceptions.Timeout:
print(f"⏰ [{model_id}] Zaman aşımı (90sn)")
continue
except Exception as e:
print(f"💥 [{model_id}] İSTİSNA DETAYI:")
print(f" Hata Tipi: {type(e).__name__}")
print(f" Mesaj: {e}")
print(" Traceback:")
traceback.print_exc()
continue
print("\n" + "=" * 50)
print("❌ TÜM MODELLER BAŞARISIZ!")
print("=" * 50)
return "❌ Tüm modeller başarısız. Token'ınızı kontrol edin veya daha sonra deneyin."
def summarize_with_api(text: str, api_key: str) -> str:
"""Metni özetler."""
if not text or "⚠️" in text:
return "⚠️ Özetlenecek metin yok."
clean_text = text.split("───────────────────────────────────")[0].strip()
prompt = f"Aşağıdaki metni Türkçe olarak maddeler halinde özetle:\n\n{clean_text}"
return call_huggingface_api(prompt, api_key)
def translate_with_api(text: str, target_language: str, api_key: str) -> str:
"""Metni çevirir."""
if not text or "⚠️" in text:
return "⚠️ Çevrilecek metin yok."
clean_text = text.split("───────────────────────────────────")[0].strip()
lang_map = {"İngilizce": "English", "Almanca": "German", "Fransızca": "French", "Türkçe": "Turkish"}
tgt = lang_map.get(target_language, "English")
prompt = f"Translate the following text to {tgt}. Only provide the translation, no extra text.\n\nText:\n{clean_text}"
return call_huggingface_api(prompt, api_key)
# ==================== TRANSCRIPTION (WHISPER - LOCAL) ====================
def transcribe(audio_path: str, progress=gr.Progress()):
if model is None:
yield "❌ Hata: Whisper modeli yüklenemedi.", None
return
if audio_path is None:
yield "⚠️ Lütfen bir ses dosyası yükleyin.", None
return
try:
start_time = time.time()
progress(0, desc="Ses işleniyor...")
segments, info = model.transcribe(
audio_path,
language="tr",
beam_size=1,
vad_filter=True,
word_timestamps=False
)
duration = info.duration
full_text = ""
for segment in segments:
full_text += segment.text + " "
if duration > 0:
prog = min(segment.end / duration, 0.99)
progress(prog, desc=f"Dönüştürülüyor... ({int(segment.end)}/{int(duration)} sn)")
yield full_text.strip(), None
elapsed = time.time() - start_time
final_result = full_text.strip()
if not final_result:
yield "⚠️ Ses anlaşılamadı veya sessiz.", None
return
progress(0.99, desc="Dosya kaydediliyor...")
txt_file = tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8')
txt_file.write(final_result)
txt_file.close()
stats = f"\n\n───────────────────────────────────\n📊 İstatistikler\n• Süre: {duration:.1f} sn\n• İşlem: {elapsed:.1f} sn\n• Hız: {duration/elapsed:.1f}x\n───────────────────────────────────"
yield final_result + stats, txt_file.name
except Exception as e:
yield f"❌ Transkripsiyon Hatası: {str(e)}", None
# ==================== UI (GRADIO) ====================
with gr.Blocks(title="Voice to Text Manager") as demo:
gr.HTML("""
<style>
footer { display: none !important; }
.gradio-container { max-width: 900px !important; margin: auto !important; }
</style>
<div style="text-align: center; padding: 30px; background: linear-gradient(135deg, #6366f1 0%, #a855f7 100%); border-radius: 20px; margin-bottom: 20px; color: white;">
<h1 style="font-size: 2.2rem; margin: 0;">🎙️ Voice to Text Manager</h1>
<p style="opacity: 0.9; font-size: 1.1rem;">1-2 saatlik ses kayıtlarını rahatça deşifre edebilir ve işleyebilirsiniz.</p>
</div>
""")
with gr.Row():
with gr.Column():
audio_input = gr.Audio(label="Ses Dosyası", type="filepath", sources=["upload", "microphone"])
submit_btn = gr.Button("🚀 Deşifre Et", variant="primary", size="lg")
with gr.Row():
with gr.Column():
output_text = gr.Textbox(label="Metin", placeholder="Sonuçlar burada...", lines=10, interactive=False)
download_file = gr.File(label="İndir (.txt)")
gr.HTML("<h3 style='margin-top: 20px; border-bottom: 1px solid #ddd; padding-bottom: 10px;'>☁️ Hugging Face API (Özet & Çeviri)</h3>")
# Secret durumunu kontrol et
hf_secret_loaded = bool(os.environ.get("HF_TOKEN"))
secret_status = "✅ Secret yüklendi (HF_TOKEN)" if hf_secret_loaded else "⚠️ Secret bulunamadı, token girin"
with gr.Row():
api_key_input = gr.Textbox(
label="🔑 HF Token (Opsiyonel - Kendi Tokeninizi Ekleyebilirsiniz)",
placeholder=secret_status,
type="password",
value="" if hf_secret_loaded else None
)
with gr.Tabs():
with gr.TabItem("✨ Özetle"):
summary_btn = gr.Button("📝 Özetle")
summary_output = gr.Textbox(label="Özet", lines=6)
with gr.TabItem("🌍 Çevir"):
with gr.Row():
target_lang = gr.Dropdown(["İngilizce", "Almanca", "Fransızca"], label="Hedef Dil", value="İngilizce")
translate_btn = gr.Button("Çevir")
translate_output = gr.Textbox(label="Çeviri", lines=6)
submit_btn.click(transcribe, inputs=[audio_input], outputs=[output_text, download_file])
summary_btn.click(summarize_with_api, inputs=[output_text, api_key_input], outputs=summary_output)
translate_btn.click(translate_with_api, inputs=[output_text, target_lang, api_key_input], outputs=translate_output)
if __name__ == "__main__":
demo.launch(share=False)