| """Werea-TSS Hugging Face Space arayuzu. |
| |
| SPDX-License-Identifier: MIT |
| """ |
|
|
| from __future__ import annotations |
|
|
| import os |
|
|
| os.environ.setdefault("GRADIO_ANALYTICS_ENABLED", "False") |
|
|
| import gradio as gr |
|
|
| from werea_tss import MAX_CHARACTERS, QUALITY_MODES, engine_version, synthesize |
|
|
|
|
| CSS = """ |
| :root { color-scheme: dark; } |
| .gradio-container { |
| --werea-pink: #ff488b; |
| --werea-ink: #09090b; |
| --werea-panel: #111115; |
| --werea-line: rgba(255,255,255,.11); |
| max-width: 1180px !important; |
| margin: 0 auto !important; |
| color: #f6f6f7 !important; |
| background: |
| radial-gradient(circle at 92% 2%, rgba(255,72,139,.16), transparent 31rem), |
| radial-gradient(circle at 0% 65%, rgba(255,72,139,.07), transparent 28rem), |
| var(--werea-ink) !important; |
| font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important; |
| } |
| .main { background: transparent !important; } |
| #werea-hero { padding: 32px 4px 14px; } |
| .werea-nav { display:flex; align-items:center; justify-content:space-between; gap:20px; margin-bottom:64px; } |
| .werea-wordmark { color:#fff; font-weight:700; font-size:27px; letter-spacing:-1.6px; } |
| .werea-badge { border:1px solid rgba(255,72,139,.45); color:#ff8fb8; border-radius:999px; padding:7px 11px; font-size:12px; letter-spacing:.08em; text-transform:uppercase; } |
| .werea-kicker { color:var(--werea-pink); text-transform:uppercase; letter-spacing:.13em; font-size:12px; font-weight:700; } |
| .werea-title { max-width:850px; margin:14px 0 16px; font-weight:550 !important; line-height:.95 !important; letter-spacing:-.065em !important; font-size:clamp(48px,9vw,106px) !important; } |
| .werea-title span { color:var(--werea-pink); } |
| .werea-lead { color:#aaaab2 !important; font-size:clamp(17px,2vw,22px) !important; line-height:1.45 !important; max-width:700px; margin:0 0 28px; } |
| .werea-pills { display:flex; flex-wrap:wrap; gap:8px; } |
| .werea-pill { border:1px solid var(--werea-line); border-radius:999px; padding:8px 12px; color:#c7c7cd; font-size:13px; background:rgba(255,255,255,.025); } |
| #studio { border:1px solid var(--werea-line) !important; border-radius:22px !important; padding:18px !important; background:rgba(17,17,21,.88) !important; box-shadow:0 28px 90px rgba(0,0,0,.32); } |
| #studio textarea { min-height:218px !important; font-size:18px !important; line-height:1.6 !important; background:#0d0d10 !important; color:#f6f6f7 !important; } |
| #studio .form { border-color:var(--werea-line) !important; background:#0d0d10 !important; } |
| #generate { min-height:50px; font-weight:700; background:var(--werea-pink) !important; border-color:var(--werea-pink) !important; color:#18030b !important; box-shadow:none !important; } |
| #generate:hover { filter:brightness(1.08); } |
| #clear { min-height:50px; } |
| #status { min-height:30px; color:#bdbdc5; background:transparent !important; border:0 !important; padding:10px 0 0 !important; } |
| #status p { color:#c7c7cd !important; } |
| .werea-section-title { margin:48px 0 8px; font-size:24px; letter-spacing:-.03em; } |
| .werea-note { color:#92929c; font-size:14px; line-height:1.65; } |
| .werea-footer { border-top:1px solid var(--werea-line); margin-top:48px; padding:24px 0 10px; color:#777781; font-size:12px; display:flex; justify-content:space-between; flex-wrap:wrap; gap:10px; } |
| footer { display:none !important; } |
| @media (max-width: 700px) { |
| #werea-hero { padding-top:18px; } |
| .werea-nav { margin-bottom:42px; } |
| #studio { padding:12px !important; border-radius:16px !important; } |
| } |
| """ |
|
|
| HEAD = """ |
| <meta name="theme-color" content="#09090b"> |
| <meta name="description" content="Werea-TSS — açık, şeffaf ve tamamen Türkçe ses sentezi."> |
| """ |
|
|
| HERO = """ |
| <section id="werea-hero"> |
| <div class="werea-nav"> |
| <div class="werea-wordmark">werea</div> |
| <div class="werea-badge">TSS · Açık beta</div> |
| </div> |
| <div class="werea-kicker">Türkçe Ses Sentezi</div> |
| <h1 class="werea-title">Metni sese.<br><span>Açıkça.</span></h1> |
| <p class="werea-lead">Türkçe metninizi Werea'nın 183 milyon parametreli açık modeliyle doğal bir 48 kHz WAV dosyasına dönüştürün. Ses klonlama yok, hesap yok, kalıcı metin kaydı yok.</p> |
| <div class="werea-pills"> |
| <span class="werea-pill">%100 Türkçe arayüz</span> |
| <span class="werea-pill">183M gerçek model</span> |
| <span class="werea-pill">48 kHz çıktı</span> |
| <span class="werea-pill">Apache-2.0 ağırlık</span> |
| <span class="werea-pill">Ses klonlamaz</span> |
| </div> |
| </section> |
| """ |
|
|
| INFO = """ |
| ### Şeffaflık notu |
| |
| Bu sürüm, **Werea-co/Werea-TSS** adlı 183,2M parametreli neural modeli kullanır. Model Apache-2.0 FreyaTTS-small tabanından, Werea'nın özgün Türkçe metinleri ve sabit tohumla üretilmiş sentetik öğretmen sesleriyle fine-tune edilmiştir. İzinsiz gerçek kişi kaydı kullanılmamıştır. Çıktı sentetiktir ve gerçek insan kaydı gibi sunulmamalıdır. |
| |
| ### Sorumlu kullanım |
| |
| Dolandırıcılık, kimliğe bürünme, taciz, izinsiz otomatik arama, yanıltıcı haber veya sentetik sesi gerçek kayıt gibi gösterme amacıyla kullanmayın. Hassas ya da kamuya açık içerikleri yayımlamadan önce bir insan tarafından dinleyip doğrulayın. |
| |
| ### Gizlilik özeti |
| |
| Metin yalnızca ses üretmek için bellekte işlenir. Uygulama metni veritabanına yazmaz ve içerik analitiği çalıştırmaz. Oluşturulan geçici ses dosyaları düzenli olarak temizlenir. Barındırma sağlayıcısı Hugging Face kendi güvenlik ve işletim kayıtlarını işleyebilir; ayrıntılar depo içindeki `GIZLILIK.md` belgesindedir. |
| """ |
|
|
|
|
| def generate(text: str, quality: str): |
| try: |
| return synthesize(text, quality) |
| except ValueError as error: |
| raise gr.Error(str(error), duration=5) from error |
| except RuntimeError as error: |
| raise gr.Error(str(error), duration=5) from error |
|
|
|
|
| theme = gr.themes.Base( |
| primary_hue="pink", |
| neutral_hue="zinc", |
| radius_size="lg", |
| font=["Inter", "ui-sans-serif", "system-ui", "sans-serif"], |
| ).set( |
| body_background_fill="#09090b", |
| body_background_fill_dark="#09090b", |
| block_background_fill="#111115", |
| block_background_fill_dark="#111115", |
| block_border_color="rgba(255,255,255,.11)", |
| block_border_color_dark="rgba(255,255,255,.11)", |
| button_primary_background_fill="#ff488b", |
| button_primary_background_fill_dark="#ff488b", |
| ) |
|
|
| with gr.Blocks( |
| title="Werea-TSS · Türkçe Ses Sentezi", |
| delete_cache=(900, 3600), |
| fill_width=True, |
| ) as demo: |
| gr.HTML(HERO) |
|
|
| with gr.Group(elem_id="studio"): |
| with gr.Row(equal_height=False): |
| with gr.Column(scale=7, min_width=320): |
| text = gr.Textbox( |
| label="Seslendirilecek metin", |
| placeholder="Bugün yeni bir fikri seslendirelim…", |
| lines=8, |
| max_lines=16, |
| max_length=MAX_CHARACTERS, |
| autofocus=True, |
| info=f"En fazla {MAX_CHARACTERS:,} karakter".replace(",", "."), |
| ) |
| with gr.Row(): |
| generate_button = gr.Button("Sesi üret", variant="primary", elem_id="generate") |
| clear_button = gr.Button("Temizle", variant="secondary", elem_id="clear") |
| with gr.Column(scale=4, min_width=280): |
| quality = gr.Dropdown( |
| choices=list(QUALITY_MODES), |
| value="Dengeli", |
| label="Üretim kalitesi", |
| info="Yüksek kalite daha uzun sürebilir.", |
| ) |
| audio = gr.Audio( |
| label="Üretilen ses", |
| type="filepath", |
| format="wav", |
| buttons=["download"], |
| editable=False, |
| ) |
| status = gr.Markdown("Metninizi yazın ve **Sesi üret** düğmesine basın.", elem_id="status") |
|
|
| gr.HTML('<h2 class="werea-section-title">Başlamak için örnekler</h2>') |
| gr.Examples( |
| examples=[ |
| ["Merhaba! Burası Werea Türkçe Ses Sentezi. Yazdığınız metni kendi açık modelimizle sese dönüştürüyoruz."], |
| ["İstanbul'da bugün hava serin. Yanınıza ince bir ceket almayı unutmayın."], |
| ["Bir fikrin değeri, onu ne kadar açık anlattığınızla büyür."], |
| ], |
| inputs=[text], |
| cache_examples=False, |
| label="Örnekler", |
| ) |
|
|
| with gr.Accordion("Kaynak, lisans ve gizlilik", open=False): |
| gr.Markdown(INFO) |
|
|
| gr.HTML( |
| f'<div class="werea-footer"><span>werea · Türkçe Ses Sentezi</span>' |
| f'<span>{engine_version()} · MIT uygulama kodu · Apache-2.0 model</span></div>' |
| ) |
|
|
| generate_event = generate_button.click( |
| fn=generate, |
| inputs=[text, quality], |
| outputs=[audio, status], |
| concurrency_limit=1, |
| concurrency_id="synthesis", |
| api_name="turkce_ses_uret", |
| ) |
| text.submit( |
| fn=generate, |
| inputs=[text, quality], |
| outputs=[audio, status], |
| concurrency_limit=1, |
| concurrency_id="synthesis", |
| api_name=False, |
| ) |
| clear_button.click( |
| fn=lambda: ("", None, "Metninizi yazın ve **Sesi üret** düğmesine basın."), |
| outputs=[text, audio, status], |
| queue=False, |
| api_name=False, |
| ) |
|
|
| demo.queue(max_size=12, default_concurrency_limit=1) |
|
|
| if __name__ == "__main__": |
| demo.launch(show_error=False, theme=theme, css=CSS, head=HEAD) |
|
|