Spaces:
Running
Running
import os | |
import tempfile | |
import json | |
import time | |
import gradio as gr | |
import spacy | |
import subprocess | |
from preprocessing import clean_audio | |
from asr import transcribe_file | |
from diarization import diarize_segments | |
from privacy import MedicalPrivacyProcessor | |
from config import settings | |
from typing import Tuple, Dict | |
from pydub import AudioSegment | |
# HuggingFace token'ını ayarla | |
HF_TOKEN = os.getenv("HF_TOKEN", "") | |
if not HF_TOKEN: | |
print("Warning: HF_TOKEN not set!") | |
def load_spacy_model(): | |
"""Load SpaCy model with graceful fallback to blank model""" | |
import spacy | |
from config import settings | |
try: | |
# Önce tam modeli yüklemeyi dene | |
return spacy.load(settings.SPACY_MODEL) | |
except OSError: | |
# Model yüklenemezse blank model kullan | |
print(f"[warning] SpaCy model '{settings.SPACY_MODEL}' yüklenemedi; fallback olarak blank('tr') kullanılıyor.") | |
return spacy.blank("tr") | |
# SpaCy modelini yükle | |
nlp = load_spacy_model() | |
# Yardım metni | |
usage_tips = """ | |
## Kullanım İpuçları | |
1. **Dosya formatı**: WAV formatında ses dosyaları en iyi sonuçları verir. | |
2. **Ses kalitesi**: Gürültüsüz ortamlarda kaydedilen sesler daha iyi sonuç verir. | |
3. **Konuşmacı ayrımı**: Konuşmacı sayısı arttıkça tanıma doğruluğu düşebilir. | |
4. **Hata durumlarında**: Sistem hata verirse, ses dosyasının formatını ve boyutunu kontrol edin. | |
## Pediatrik Uzmanlar İçin | |
Sistem, çocuk hastalıkları, aşılar, ilaçlar ve muayene terimleri içeren | |
geniş bir tıbbi terim sözlüğü kullanır. Bu sayede pediatri vizitelerindeki | |
terminolojinin doğru transkribe edilmesini sağlar. | |
""" | |
# CSS stilleri | |
css = """ | |
.container {padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);} | |
.result-text {margin-top: 10px; padding: 15px; background: #f8f9fa; border-radius: 5px; white-space: pre-wrap;} | |
.speaker {font-weight: bold; color: #1a5fb4;} | |
.timestamp {color: #666; font-size: 0.9em;} | |
.success {color: green; font-weight: bold;} | |
.error {color: red; font-weight: bold;} | |
.footer {margin-top: 50px; text-align: center; color: #666; font-size: 0.9em;} | |
.tips {background: #e7f5ff; padding: 15px; border-radius: 5px; margin-top: 20px;} | |
""" | |
def enhance_audio(audio: AudioSegment) -> AudioSegment: | |
"""Ses kalitesini iyileştir""" | |
# Basit ses iyileştirme: normalize et | |
return audio.normalize() | |
def diarize_speakers(audio_path: str) -> list: | |
"""Konuşmacıları ayır""" | |
# TODO: Gerçek diarization implementasyonu | |
return [] | |
def transcribe_audio(audio_path: str, diarization: list = None) -> Dict: | |
"""Ses dosyasını metne çevir""" | |
# TODO: Gerçek transkripsiyon implementasyonu | |
return { | |
"text": "Örnek transkripsiyon metni", | |
"segments": [] | |
} | |
def anonymize_personal_info(result: Dict) -> Dict: | |
"""Kişisel bilgileri anonimleştir""" | |
# TODO: Gerçek anonimleştirme implementasyonu | |
return result | |
def process_audio( | |
audio_path: str, | |
diarize: bool = True, | |
enhance: bool = True, | |
anonymize: bool = True | |
) -> str: | |
""" | |
Ses dosyasını işleyip transkripsiyon yapar. | |
Args: | |
audio_path: Ses dosyasının yolu | |
diarize: Konuşmacı ayrımı yapılsın mı? | |
enhance: Ses iyileştirme yapılsın mı? | |
anonymize: Kişisel veriler anonimleştirilsin mi? | |
Returns: | |
str: Transkripsiyon metni | |
""" | |
if not audio_path: | |
return "Lütfen bir ses dosyası yükleyin." | |
try: | |
# Ses dosyasını WAV formatına çevir | |
base, ext = os.path.splitext(audio_path) | |
wav_path = base + ".wav" | |
audio = AudioSegment.from_file(audio_path) | |
# Ses iyileştirme | |
if enhance: | |
audio = enhance_audio(audio) | |
audio.export(wav_path, format="wav") | |
else: | |
audio.export(wav_path, format="wav") | |
# Konuşmacı ayrımı | |
if diarize: | |
diarization = diarize_speakers(wav_path) | |
else: | |
diarization = None | |
# Transkripsiyon | |
transcript = transcribe_file(wav_path) | |
# Anonimleştirme | |
if anonymize: | |
transcript = anonymize_personal_info({"text": transcript})["text"] | |
return transcript | |
except Exception as e: | |
error_msg = f"İşlem sırasında bir hata oluştu: {str(e)}" | |
print(error_msg) | |
return error_msg | |
# Ana arayüz | |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="blue"), css=css) as demo: | |
gr.HTML(f""" | |
<div style="text-align: center; max-height: 150px; margin-bottom: 30px"> | |
<h1>Türkçe Pediatrik Konuşma Tanıma Sistemi</h1> | |
<p>Çocuk doktorları için geliştirilmiş, pediatri alanına özel tıbbi terminoloji tanıma özellikli transkripsiyon sistemi</p> | |
</div> | |
""") | |
with gr.Row(): | |
with gr.Column(scale=1): | |
audio_input = gr.Audio( | |
label="Ses Dosyası Yükleyin veya Kaydedin", | |
type="filepath", | |
elem_classes="container" | |
) | |
with gr.Group(): | |
with gr.Row(): | |
diarize = gr.Checkbox(value=True, label="Konuşmacı Ayrımı") | |
enhance = gr.Checkbox(value=True, label="Ses İyileştirme") | |
with gr.Row(): | |
anonymize = gr.Checkbox(value=True, label="Kişisel Verileri Anonimleştir") | |
clear_btn = gr.Button("Temizle", variant="secondary") | |
# Transkribe Et butonunu başta pasif yap | |
process_btn = gr.Button("Transkribe Et", variant="primary", interactive=False) | |
gr.HTML('<div class="tips"><b>💡 İpucu:</b> En iyi sonuçlar için gürültüsüz ortamlarda kayıt yapın.</div>') | |
with gr.Column(scale=2, elem_classes="container"): | |
with gr.Tabs(): | |
with gr.TabItem("Konuşma Metni"): | |
result_text = gr.Markdown(label="Transkripsiyon Sonucu", elem_classes="result-text") | |
with gr.TabItem("Kullanım Kılavuzu"): | |
gr.Markdown(usage_tips) | |
status = gr.Markdown("Sistem hazır.") | |
# Uyarı mesajı | |
gr.HTML(""" | |
<div style="background-color: #fff3cd; color: #856404; padding: 15px; margin: 15px 0; border-radius: 5px; border: 1px solid #ffeeba;"> | |
<h3>⚠️ Önemli Gizlilik Uyarısı</h3> | |
<p> | |
Bu demo uygulaması <strong>yalnızca eğitim amaçlıdır</strong> ve gerçek hasta verilerinin işlenmesi için tasarlanmamıştır. | |
Lütfen hasta bilgisi içeren ses kayıtlarını yüklemeyin. Sistemde paylaşılan ses kayıtları üçüncü şahıslar tarafından erişilebilir | |
ve gizlilik/güvenlik garantisi yoktur. | |
</p> | |
<p> | |
Bu aracı kullanarak, yüklediğiniz verilerin <a href="https://huggingface.co/terms-of-service" target="_blank">Hugging Face Kullanım Koşulları</a>'na | |
uygun olduğunu kabul etmiş olursunuz. | |
</p> | |
</div> | |
""") | |
# Gizlilik onay kutusu | |
privacy_agreement = gr.Checkbox(label="Gizlilik koşullarını okudum ve kabul ediyorum", value=False) | |
# Onay kutusu ile butonu bağla | |
def toggle_process_button(checked: bool): | |
return gr.update(interactive=checked) | |
privacy_agreement.change( | |
fn=toggle_process_button, | |
inputs=privacy_agreement, | |
outputs=process_btn | |
) | |
# Process tuşuna tıklanınca çalışan orijinal fonksiyon | |
process_btn.click( | |
fn=process_audio, | |
inputs=[audio_input, diarize, enhance, anonymize], | |
outputs=result_text | |
) | |
clear_btn.click( | |
lambda: (None, "Sistem hazır."), | |
outputs=[audio_input, status] | |
) | |
gr.HTML(""" | |
<div class="footer"> | |
<p>© 2023 Türkçe Pediatrik Konuşma Tanıma Sistemi | Çocuk doktorları için geliştirilmiştir.</p> | |
</div> | |
""") | |
# Hugging Face Spaces için gerekli | |
if __name__ == "__main__": | |
demo.queue().launch(server_name="0.0.0.0", server_port=7860, share=False) |