Blue Archive
PREMIUM TEXT-TO-SPEECH SERVICE
import os import sys import logging import torch import utils import commons import gradio as gr from models import SynthesizerTrn from text import text_to_sequence from text.symbols import symbols # Konfigurasi Dasar logging.getLogger('matplotlib').setLevel(logging.WARNING) device = torch.device("cpu") def get_text(text, hps): text_norm = text_to_sequence(text, hps.data.text_cleaners) if hps.data.add_blank: text_norm = commons.intersperse(text_norm, 0) return torch.LongTensor(text_norm) def create_tts_fn(model, hps, speaker_ids): def tts_fn(text, speaker_idx, speed): if not text: return "Teks tidak boleh kosong!", None try: speaker_id = speaker_ids[speaker_idx] stn_tst = get_text(text, hps) with torch.no_grad(): x_tst = stn_tst.unsqueeze(0).to(device) x_tst_lengths = torch.LongTensor([stn_tst.size(0)]).to(device) sid = torch.LongTensor([speaker_id]).to(device) audio = model.infer( x_tst, x_tst_lengths, sid=sid, noise_scale=.667, noise_scale_w=0.8, length_scale=1.0/speed )[0][0,0].data.cpu().float().numpy() return "Berhasil Membuat ✅!", (hps.data.sampling_rate, audio) except Exception as e: return f"Error: {str(e)}", None return tts_fn # --- CSS: MILKY WHITE & PRECISION BLUE --- css = """ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700;800&display=swap'); body, .gradio-container { background-color: #fdfdfd !important; font-family: 'Inter', sans-serif !important; } footer { display: none !important; } /* Header */ .main-header { text-align: center; padding: 20px 0 5px 0; } .main-header h1 { font-weight: 800; color: #1299ff; font-size: 2.4rem; margin: 0; } .main-header p { color: #8a99af; letter-spacing: 2px; font-weight: 600; font-size: 10px; margin-top: 2px; } /* Menghilangkan Shadow & Border Halus pada Input */ .gradio-container .block, .gradio-container .form, .gradio-container input, .gradio-container textarea, .gradio-container .secondary { box-shadow: none !important; border: 1px solid #e2e8f0 !important; background-color: #ffffff !important; } /* --- Label Biru & Putih Susu (Target Semua Label Termasuk Hasil Audio) --- */ .gradio-container .label-wrap span, .gradio-container span.svelte-1gfkn6j, .gradio-container label span { background-color: #e6f4ff !important; color: #1299ff !important; border-radius: 8px !important; padding: 2px 10px !important; box-shadow: none !important; border: none !important; font-weight: 700 !important; font-size: 12px !important; } /* --- Audio Player (Wadah Putih Bersih) --- */ .gradio-container .audio-container { background-color: #ffffff !important; border: 1px solid #e2e8f0 !important; } /* Status Box */ .status-card { background: #ffffff; border: 1px solid #eef2f7; border-radius: 12px; padding: 12px 20px; margin: 0 auto 15px auto; max-width: 380px; } .status-item { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #4a5568; margin: 2px 0; } .dot { height: 6px; width: 6px; background-color: #1299ff; border-radius: 50%; display: inline-block; } /* Character Info Grid */ .char-scroll-box { max-height: 280px; overflow-y: auto; padding: 5px; } .char-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .char-card { background: white; border-left: 4px solid #1299ff; padding: 10px; border-radius: 10px; border-top: 1px solid #f0f4f8; border-right: 1px solid #f0f4f8; border-bottom: 1px solid #f0f4f8; cursor: pointer; transition: all 0.2s; } .char-card:hover { background: #f0f7ff; transform: translateY(-2px); border-color: #0072ff; } .char-name-jp { font-weight: 700; font-size: 13px; color: #1a202c; display: block; } .char-name-en { font-size: 11px; color: #718096; } /* Tombol Generate */ .generate-btn { background: linear-gradient(135deg, #00c6ff 0%, #0072ff 100%) !important; border: none !important; color: white !important; font-weight: 700 !important; border-radius: 12px !important; height: 45px !important; } #custom-img { border-radius: 15px !important; border: 3px solid #fff; } """ if __name__ == '__main__': config_path = "saved_model/config.json" model_path = "saved_model/model.pth" cover_path = "saved_model/cover.png" hps = utils.get_hparams_from_file(config_path) posterior_channels = 80 if ("use_mel_posterior_encoder" in hps.model.keys() and hps.model.use_mel_posterior_encoder) else hps.data.filter_length // 2 + 1 model = SynthesizerTrn( len(symbols), posterior_channels, hps.train.segment_size // hps.data.hop_length, n_speakers=hps.data.n_speakers, **hps.model).to(device) utils.load_checkpoint(model_path, model, None) model.eval() speakers = [name for name in hps.speakers if name != "None"] speaker_ids = [i for i, name in enumerate(hps.speakers) if name != "None"] with gr.Blocks(css=css, theme=gr.themes.Soft()) as app: # Header gr.HTML("""
PREMIUM TEXT-TO-SPEECH SERVICE