File size: 8,337 Bytes
0513bad
 
 
02eb251
 
bb27d06
87fc8c1
071b666
02eb251
071b666
 
 
f9b22e5
f76769c
0513bad
02eb251
 
 
 
0513bad
02eb251
fb9756e
28c9a1a
 
 
02eb251
fb9756e
14e4ceb
87fc8c1
fb9756e
 
 
0513bad
943023c
02eb251
bb27d06
02eb251
 
 
cd2255e
02eb251
 
 
 
cd2255e
02eb251
0513bad
02eb251
 
 
 
071b666
02eb251
 
 
 
 
 
 
 
 
 
 
071b666
e3c7954
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f9b22e5
 
e3c7954
 
 
22a0d15
f9b22e5
 
 
 
 
e3c7954
 
 
f9b22e5
 
22a0d15
f9b22e5
 
22a0d15
02eb251
f9b22e5
f76769c
 
 
 
071b666
f9b22e5
e3c7954
f9b22e5
f76769c
bdb0415
 
0513bad
f9b22e5
e3c7954
f76769c
f9b22e5
 
 
 
bdb0415
02eb251
f9b22e5
e3c7954
bdb0415
f9b22e5
bdb0415
0513bad
071b666
f9b22e5
 
22a0d15
071b666
02eb251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65c26ef
 
02eb251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65c26ef
 
 
 
 
4a14d8c
65c26ef
 
 
 
 
 
 
 
 
 
 
22a0d15
65c26ef
02eb251
 
22a0d15
 
02eb251
 
 
 
 
 
 
0513bad
02eb251
0513bad
02eb251
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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)