Spaces:
Sleeping
Sleeping
| import os | |
| import tempfile | |
| import warnings | |
| import traceback | |
| import fitz # PyMuPDF | |
| from ebooklib import epub | |
| from bs4 import BeautifulSoup | |
| import gradio as gr | |
| import torch | |
| # Coqui TTS lisans onayı istemini atlamak için ortam değişkenini ayarla. | |
| os.environ['COQUI_TOS_AGREED'] = '1' | |
| from TTS.api import TTS | |
| # Hataları ve uyarıları gizle | |
| warnings.filterwarnings("ignore") | |
| print("📚 Kütüphaneler ve modüller başarıyla yüklendi!") | |
| # Cihaz (GPU/CPU) kontrolü | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| print(f"🖥️ Uygulama `{device.upper()}` üzerinde çalışacak.") | |
| # TTS modelini yükle | |
| model_type = "none" | |
| tts_model = None | |
| print("🤖 Yüksek kaliteli XTTS v2 modeli yükleniyor... (Bu işlem birkaç dakika sürebilir)") | |
| try: | |
| # Sadece yüksek kaliteli, çok dilli xtts_v2 modelini yüklemeyi dene. | |
| tts_model = TTS("tts_models/multilingual/multi-dataset/xtts_v2", progress_bar=True).to(device) | |
| model_type = "xtts" | |
| print("✅ Yüksek kaliteli XTTS v2 modeli başarıyla yüklendi!") | |
| except Exception as e: | |
| # Eğer model yüklenemezse, hata ver ve uygulamayı başlatma. | |
| print(f"❌ Kritik Hata: XTTS v2 modeli yüklenemedi. Hata: {e}") | |
| traceback.print_exc() | |
| print("💡 Bellek yetersizliği veya sürüm uyumsuzluğu gibi bir sorun olabilir. Space loglarını ve donanım ayarlarını kontrol edin.") | |
| def extract_text_from_file(file_obj): | |
| """Verilen dosya nesnesinden (PDF, TXT, EPUB) metin içeriğini çıkarır.""" | |
| if file_obj is None: | |
| return "⚠️ Lütfen bir dosya seçin." | |
| try: | |
| file_path = file_obj.name | |
| ext = os.path.splitext(file_path)[1].lower() | |
| text = "" | |
| print(f"📄 '{os.path.basename(file_path)}' adlı dosya işleniyor...") | |
| if ext == ".pdf": | |
| with fitz.open(file_path) as doc: | |
| for page in doc: | |
| text += page.get_text("text") + " " | |
| elif ext == ".txt": | |
| encodings = ['utf-8', 'utf-8-sig', 'windows-1254', 'iso-8859-9'] | |
| for encoding in encodings: | |
| try: | |
| with open(file_path, 'r', encoding=encoding) as f: | |
| text = f.read() | |
| print(f"✅ Metin dosyası '{encoding}' kodlaması ile okundu.") | |
| break | |
| except UnicodeDecodeError: | |
| continue | |
| elif ext == ".epub": | |
| book = epub.read_epub(file_path) | |
| for item in book.get_items_of_type(epub.EpubHtml): | |
| soup = BeautifulSoup(item.get_content(), "html.parser") | |
| text += soup.get_text() + " " | |
| else: | |
| return f"⚠️ Desteklenmeyen dosya türü: '{ext}'. Lütfen PDF, TXT veya EPUB formatında bir dosya yükleyin." | |
| cleaned_text = ' '.join(text.split()) | |
| if not cleaned_text: | |
| return "⚠️ Dosya boş veya metin içeriği okunamadı." | |
| print(f"✅ Dosyadan {len(cleaned_text)} karakter metin çıkarıldı.") | |
| return cleaned_text | |
| except Exception as e: | |
| print(f"❌ Dosya okuma hatası: {e}") | |
| traceback.print_exc() | |
| return f"⚠️ Dosya işlenirken bir hata oluştu: {str(e)}" | |
| def synthesize_audio(text_to_process): | |
| """Verilen metni seslendirerek bir WAV dosyası oluşturur.""" | |
| if not text_to_process or len(text_to_process.strip()) < 5: | |
| return "⚠️ Seslendirme için en az 5 karakterlik anlamlı bir metin girin.", None | |
| if tts_model is None: | |
| return "⚠️ TTS modeli yüklenemediği için seslendirme yapılamıyor.", None | |
| try: | |
| max_chars = 1500 | |
| if len(text_to_process) > max_chars: | |
| print(f"✂️ Metin çok uzun, ilk {max_chars} karaktere kırpıldı.") | |
| text_to_process = text_to_process[:max_chars] | |
| print(f"🎙️ Ses sentezi başlıyor... (Model: {model_type.upper()}, Karakter: {len(text_to_process)})") | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file: | |
| output_path = tmp_file.name | |
| # --- YENİ VE DOĞRU DÜZELTME --- | |
| # Önceki 'speaker_manager' denemesi yanlıştı çünkü 'TTS' nesnesinde böyle bir özellik yok. | |
| # Orijinal hata, 'speaker' parametresinin eksik olduğunu belirtiyordu. | |
| # Şimdi bu parametreyi, modelin içinde yer alan varsayılan bir konuşmacı adıyla doğrudan sağlıyoruz. | |
| tts_model.tts_to_file( | |
| text=text_to_process, | |
| file_path=output_path, | |
| speaker="Claribel Dervla", # Doğrudan varsayılan konuşmacıyı belirtiyoruz | |
| language="tr" | |
| ) | |
| print(f"✅ Ses dosyası başarıyla oluşturuldu: {output_path}") | |
| return f"✅ Ses oluşturuldu ({len(text_to_process)} karakter)", output_path | |
| except Exception as e: | |
| print(f"❌ Ses oluşturma sırasında kritik hata: {e}") | |
| traceback.print_exc() | |
| return f"⚠️ Ses oluşturma hatası: {str(e)}", None | |
| def process_file_and_speak(file_obj): | |
| if file_obj is None: | |
| return "⚠️ Lütfen bir dosya seçin.", None, None | |
| extracted_text = extract_text_from_file(file_obj) | |
| if extracted_text.startswith("⚠️"): | |
| return extracted_text, extracted_text, None | |
| status, audio_path = synthesize_audio(extracted_text) | |
| display_text = extracted_text | |
| if len(display_text) > 500: | |
| display_text = display_text[:500] + "..." | |
| return status, display_text, audio_path | |
| def process_text_and_speak(text_input): | |
| status, audio_path = synthesize_audio(text_input) | |
| return status, audio_path | |
| def create_ui(): | |
| with gr.Blocks( | |
| title="🔊 Türkçe Kitap Seslendirici", | |
| theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), | |
| css=""" | |
| .main-header { | |
| text-align: center; padding: 20px; background: linear-gradient(135deg, #007BFF 0%, #00BFFF 100%); | |
| color: white; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); | |
| } | |
| .main-header h1 { font-size: 2.5em; } .main-header p { font-size: 1.1em; opacity: 0.9; } | |
| .gr-button { min-width: 150px; } footer { display: none !important; } | |
| """ | |
| ) as app: | |
| gr.HTML(f""" | |
| <div class="main-header"> | |
| <h1>🔊 Türkçe Kitap Seslendirici</h1> | |
| <p>Yüklenen Model: <strong>{model_type.upper()}</strong> | Çalışan Cihaz: <strong>{device.upper()}</strong></p> | |
| </div> | |
| """) | |
| with gr.Tabs(): | |
| with gr.TabItem("📁 Dosyadan Seslendir"): | |
| with gr.Row(variant="panel"): | |
| with gr.Column(scale=1): | |
| file_input = gr.File(label="PDF, TXT veya EPUB Dosyası Yükle", file_types=[".pdf", ".txt", ".epub"]) | |
| file_btn = gr.Button("🔊 Dosyayı Seslendir", variant="primary", scale=1) | |
| with gr.Column(scale=2): | |
| file_status = gr.Textbox(label="📊 İşlem Durumu", interactive=False) | |
| file_text = gr.Textbox(label="📝 Dosyadan Çıkarılan Metin (Önizleme)", lines=8, interactive=False) | |
| file_audio = gr.Audio(label="🎵 Oluşturulan Ses", type="filepath") | |
| with gr.TabItem("✍️ Metinden Seslendir"): | |
| with gr.Row(variant="panel"): | |
| with gr.Column(scale=2): | |
| text_input = gr.Textbox( | |
| label="Seslendirilecek Metni Buraya Yazın", lines=10, placeholder="Merhaba dünya...", | |
| value="Yapay zeka ve ses sentezi teknolojileri her geçen gün gelişiyor. Bu da Türkçe için harika bir gelişme.") | |
| with gr.Column(scale=1): | |
| text_btn = gr.Button("🔊 Metni Seslendir", variant="primary") | |
| text_status = gr.Textbox(label="📊 İşlem Durumu", interactive=False) | |
| text_audio = gr.Audio(label="🎵 Oluşturulan Ses", type="filepath") | |
| file_btn.click(fn=process_file_and_speak, inputs=[file_input], outputs=[file_status, file_text, file_audio]) | |
| text_btn.click(fn=process_text_and_speak, inputs=[text_input], outputs=[text_status, text_audio]) | |
| gr.Markdown(""" | |
| --- | |
| ### 💡 İpuçları ve Bilgiler | |
| - **Model:** Sadece yüksek kaliteli `XTTS` modeli kullanılmaktadır. CPU üzerinde ses üretimi biraz zaman alabilir. | |
| - **Karakter Sınırı:** Performans için metinler ilk 1500 karakter ile sınırlandırılmıştır. | |
| """) | |
| return app | |
| if __name__ == "__main__": | |
| if model_type != "none": | |
| app = create_ui() | |
| app.launch() | |
| else: | |
| with gr.Blocks() as error_app: | |
| gr.Markdown(""" | |
| # ❌ Uygulama Başlatılamadı | |
| Yüksek kaliteli TTS (XTTS v2) modeli yüklenemedi. | |
| Lütfen Space loglarını kontrol edin veya daha sonra tekrar deneyin. | |
| """) | |
| error_app.launch() | |