DriiftKing commited on
Commit
fc11dc9
·
verified ·
1 Parent(s): 9bdf8df

add app.py (AudioSR CPU + motyw Lektora)

Browse files
Files changed (1) hide show
  1. app.py +132 -0
app.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """AudioSR — wzbogacanie krótkich próbek głosu (HF Space, CPU/DARMOWY). UI w kolorystyce
2
+ Lektor AI (ciemny + cyan #00ffff). Pole do wrzucenia próbki → odtwarzacz + pobieranie WAV.
3
+
4
+ Działa bez PRO (CPU basic). UWAGA: na darmowym CPU 1 klip ≈ ~2 min (to dyfuzja).
5
+ Domyślnie model „basic", 24 kroki (sprawdzone do Twojego głosu — patrz sr_dataset.py)."""
6
+ import os
7
+ import tempfile
8
+ import numpy as np
9
+ import soundfile as sf
10
+ import gradio as gr
11
+ import torch
12
+ from audiosr import build_model, super_resolution
13
+
14
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
15
+ OUTPUT_SR = 48000
16
+ _CACHE = {}
17
+
18
+
19
+ def _model(model_name: str):
20
+ if model_name not in _CACHE:
21
+ _CACHE[model_name] = build_model(model_name=model_name, device=DEVICE)
22
+ return _CACHE[model_name]
23
+
24
+
25
+ def enhance(audio_path, model_name, ddim_steps, guidance_scale, seed):
26
+ if not audio_path:
27
+ raise gr.Error("Najpierw wrzuć plik audio.")
28
+ seed = int(seed or 0)
29
+ if seed == 0:
30
+ seed = int.from_bytes(os.urandom(4), "big") % (2 ** 31)
31
+ wav = super_resolution(
32
+ _model(model_name), audio_path,
33
+ seed=seed, guidance_scale=float(guidance_scale),
34
+ ddim_steps=int(ddim_steps), latent_t_per_second=12.8,
35
+ )
36
+ wav = np.asarray(wav).squeeze()
37
+ if wav.ndim > 1:
38
+ wav = wav.T
39
+ # przytnij padding AudioSR (zaokrągla do 5.12 s + cisza) do długości wejścia
40
+ info = sf.info(audio_path)
41
+ exp = int(round(info.frames / info.samplerate * OUTPUT_SR))
42
+ if exp and wav.shape[0] > exp:
43
+ wav = wav[:exp]
44
+ # wyrównaj poziom (RMS) do oryginału — AudioSR normalizuje per-call
45
+ src, _ = sf.read(audio_path, dtype="float32")
46
+ if getattr(src, "ndim", 1) > 1:
47
+ src = src.mean(axis=1)
48
+ r_in = float(np.sqrt((src ** 2).mean())) + 1e-9
49
+ r_out = float(np.sqrt((wav ** 2).mean())) + 1e-9
50
+ wav = wav * (r_in / r_out)
51
+ peak = float(np.abs(wav).max()) or 1.0
52
+ if peak > 0.99:
53
+ wav = wav / peak * 0.99
54
+ # zapis do pliku — żeby był odtwarzacz I pobieranie czystego WAV
55
+ base = os.path.splitext(os.path.basename(audio_path))[0]
56
+ out_path = os.path.join(tempfile.gettempdir(), f"{base}_48k.wav")
57
+ sf.write(out_path, wav.astype(np.float32), OUTPUT_SR)
58
+ return out_path, gr.DownloadButton(value=out_path, interactive=True)
59
+
60
+
61
+ # ── Motyw Lektor AI (ciemny + cyan) ──────────────────────────────────────────
62
+ CYAN, PANEL, BG, BG2, TXT, MUTED, BORDER = (
63
+ "#00ffff", "#0a0a0f", "#0d0d14", "#15151e", "#cfcfe0", "#8a8aa0", "#222230")
64
+
65
+ CSS = f"""
66
+ .gradio-container, .gradio-container .dark, body {{
67
+ background:{PANEL} !important; color:{TXT} !important;
68
+ font-family:'Segoe UI', system-ui, -apple-system, sans-serif !important;
69
+ }}
70
+ .gradio-container {{ max-width:920px !important; margin:0 auto !important; }}
71
+ #lk-menu {{
72
+ display:flex; align-items:center; gap:14px;
73
+ padding:14px 18px; margin:0 0 16px 0; border-radius:12px;
74
+ background:linear-gradient(180deg,{BG2},{BG});
75
+ border:1px solid {BORDER}; border-bottom:2px solid {CYAN};
76
+ box-shadow:0 10px 28px -16px {CYAN};
77
+ }}
78
+ #lk-menu .lk-title {{ font-size:20px; font-weight:700; letter-spacing:.4px; color:{TXT}; line-height:1.1; }}
79
+ #lk-menu .lk-title b {{ color:{CYAN}; text-shadow:0 0 10px rgba(0,255,255,.45); }}
80
+ #lk-menu .lk-sub {{ font-size:12px; color:{MUTED}; margin-top:2px; }}
81
+ .block, .form, .gr-box, fieldset, .gr-panel, .panel {{
82
+ background:{BG} !important; border:1px solid {BORDER} !important; border-radius:10px !important;
83
+ }}
84
+ label, label span, .gr-input-label, span[data-testid="block-info"] {{ color:{MUTED} !important; }}
85
+ input, textarea, select, .gr-text-input {{
86
+ background:{BG2} !important; color:{TXT} !important; border:1px solid {BORDER} !important;
87
+ }}
88
+ input:focus, textarea:focus, select:focus {{ border-color:{CYAN} !important; box-shadow:0 0 0 1px {CYAN} !important; }}
89
+ input[type=range] {{ accent-color:{CYAN} !important; }}
90
+ .gr-button-primary, button.primary, .primary {{
91
+ background:{CYAN} !important; color:#06141c !important; border:none !important;
92
+ font-weight:700 !important; letter-spacing:.6px !important;
93
+ }}
94
+ .gr-button-primary:hover, button.primary:hover {{ box-shadow:0 0 16px rgba(0,255,255,.55) !important; }}
95
+ .gr-button-secondary, button.secondary {{
96
+ background:transparent !important; color:{CYAN} !important; border:1px solid {CYAN} !important;
97
+ }}
98
+ .gradio-container a {{ color:{CYAN} !important; }}
99
+ footer {{ display:none !important; }}
100
+ """
101
+
102
+ ICON = (f"<svg width='30' height='30' viewBox='0 0 24 24' fill='none' stroke='{CYAN}' "
103
+ f"stroke-width='2.2' stroke-linecap='round'>"
104
+ f"<line x1='4' y1='15' x2='4' y2='9'/><line x1='9' y1='19' x2='9' y2='5'/>"
105
+ f"<line x1='14' y1='16' x2='14' y2='8'/><line x1='19' y1='13' x2='19' y2='11'/></svg>")
106
+ MENU = (f"<div id='lk-menu'>{ICON}<div>"
107
+ f"<div class='lk-title'>Audio<b>SR</b> · Lektor AI</div>"
108
+ f"<div class='lk-sub'>Wzbogacanie pr��bek głosu — super-rozdzielczość do 48 kHz</div>"
109
+ f"</div></div>")
110
+
111
+ with gr.Blocks(title="AudioSR · Lektor AI", css=CSS, theme=gr.themes.Base()) as demo:
112
+ gr.HTML(MENU)
113
+ with gr.Row():
114
+ with gr.Column(scale=1):
115
+ audio = gr.Audio(sources=["upload", "microphone"], type="filepath",
116
+ label="Próbka głosu — wrzuć plik (krótki klip)")
117
+ model = gr.Radio(["basic", "speech"], value="basic",
118
+ label="Model (basic = sprawdzony do Twojego głosu)")
119
+ steps = gr.Slider(10, 100, value=24, step=1, label="DDIM steps (24 = jakość/czas)")
120
+ guid = gr.Slider(1.0, 10.0, value=3.5, step=0.5, label="Guidance scale")
121
+ seed = gr.Number(value=0, label="Seed (0 = losowy)")
122
+ btn = gr.Button("WZBOGAĆ", variant="primary")
123
+ with gr.Column(scale=1):
124
+ out = gr.Audio(type="filepath", label="Wzbogacone — 48 kHz (odtwarzacz)", interactive=False)
125
+ dl = gr.DownloadButton("Pobierz WAV (48 kHz)", variant="secondary", interactive=False)
126
+ gr.HTML(f"<div style='color:{MUTED};font-size:12px;margin-top:6px'>"
127
+ f"Na darmowym CPU 1 klip ≈ 2 min (dyfuzja). Model „basic”, padding przycięty, "
128
+ f"poziom wyrównany do oryginału.</div>")
129
+ btn.click(enhance, [audio, model, steps, guid, seed], [out, dl])
130
+
131
+ if __name__ == "__main__":
132
+ demo.queue(max_size=8).launch()