CoolFace
Apppublic

SpongeBobFan2002/Zonosz

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py377 linesDownload Raw Back to root
1import os2import shlex3import subprocess4 5subprocess.run(shlex.split("pip install flash-attn  --no-build-isolation"), env=os.environ | {"FLASH_ATTENTION_SKIP_CUDA_BUILD": "TRUE"}, check=True)6subprocess.run(shlex.split("pip install https://github.com/state-spaces/mamba/releases/download/v2.2.4/mamba_ssm-2.2.4+cu12torch2.4cxx11abiFALSE-cp310-cp310-linux_x86_64.whl"), check=True)7subprocess.run(shlex.split("pip install https://github.com/Dao-AILab/causal-conv1d/releases/download/v1.5.0.post8/causal_conv1d-1.5.0.post8+cu12torch2.4cxx11abiFALSE-cp310-cp310-linux_x86_64.whl"), check=True)8 9import spaces10import torch11import torchaudio12import gradio as gr13from os import getenv14 15from zonos.model import Zonos16from zonos.conditioning import make_cond_dict, supported_language_codes17 18device = "cuda"19MODEL_NAMES = ["Zyphra/Zonos-v0.1-transformer", "Zyphra/Zonos-v0.1-hybrid"]20MODELS = {name: Zonos.from_pretrained(name, device=device) for name in MODEL_NAMES}21for model in MODELS.values():22    model.requires_grad_(False).eval()23 24 25def update_ui(model_choice):26    """27    Dynamically show/hide UI elements based on the model's conditioners.28    We do NOT display 'language_id' or 'ctc_loss' even if they exist in the model.29    """30    model = MODELS[model_choice]31    cond_names = [c.name for c in model.prefix_conditioner.conditioners]32    print("Conditioners in this model:", cond_names)33 34    text_update = gr.update(visible=("espeak" in cond_names))35    language_update = gr.update(visible=("espeak" in cond_names))36    speaker_audio_update = gr.update(visible=("speaker" in cond_names))37    prefix_audio_update = gr.update(visible=True)38    emotion1_update = gr.update(visible=("emotion" in cond_names))39    emotion2_update = gr.update(visible=("emotion" in cond_names))40    emotion3_update = gr.update(visible=("emotion" in cond_names))41    emotion4_update = gr.update(visible=("emotion" in cond_names))42    emotion5_update = gr.update(visible=("emotion" in cond_names))43    emotion6_update = gr.update(visible=("emotion" in cond_names))44    emotion7_update = gr.update(visible=("emotion" in cond_names))45    emotion8_update = gr.update(visible=("emotion" in cond_names))46    vq_single_slider_update = gr.update(visible=("vqscore_8" in cond_names))47    fmax_slider_update = gr.update(visible=("fmax" in cond_names))48    pitch_std_slider_update = gr.update(visible=("pitch_std" in cond_names))49    speaking_rate_slider_update = gr.update(visible=("speaking_rate" in cond_names))50    dnsmos_slider_update = gr.update(visible=("dnsmos_ovrl" in cond_names))51    speaker_noised_checkbox_update = gr.update(visible=("speaker_noised" in cond_names))52    unconditional_keys_update = gr.update(53        choices=[name for name in cond_names if name not in ("espeak", "language_id")]54    )55 56    return (57        text_update,58        language_update,59        speaker_audio_update,60        prefix_audio_update,61        emotion1_update,62        emotion2_update,63        emotion3_update,64        emotion4_update,65        emotion5_update,66        emotion6_update,67        emotion7_update,68        emotion8_update,69        vq_single_slider_update,70        fmax_slider_update,71        pitch_std_slider_update,72        speaking_rate_slider_update,73        dnsmos_slider_update,74        speaker_noised_checkbox_update,75        unconditional_keys_update,76    )77 78 79@spaces.GPU(duration=120)80def generate_audio(81    model_choice,82    text,83    language,84    speaker_audio,85    prefix_audio,86    e1,87    e2,88    e3,89    e4,90    e5,91    e6,92    e7,93    e8,94    vq_single,95    fmax,96    pitch_std,97    speaking_rate,98    dnsmos_ovrl,99    speaker_noised,100    cfg_scale,101    min_p,102    seed,103    randomize_seed,104    unconditional_keys,105    progress=gr.Progress(),106):107    """108    Generates audio based on the provided UI parameters.109    We do NOT use language_id or ctc_loss even if the model has them.110    """111    selected_model = MODELS[model_choice]112 113    speaker_noised_bool = bool(speaker_noised)114    fmax = float(fmax)115    pitch_std = float(pitch_std)116    speaking_rate = float(speaking_rate)117    dnsmos_ovrl = float(dnsmos_ovrl)118    cfg_scale = float(cfg_scale)119    min_p = float(min_p)120    seed = int(seed)121    max_new_tokens = 86 * 30122 123    if randomize_seed:124        seed = torch.randint(0, 2**32 - 1, (1,)).item()125    torch.manual_seed(seed)126 127    speaker_embedding = None128    if speaker_audio is not None and "speaker" not in unconditional_keys:129        wav, sr = torchaudio.load(speaker_audio)130        speaker_embedding = selected_model.make_speaker_embedding(wav, sr)131        speaker_embedding = speaker_embedding.to(device, dtype=torch.bfloat16)132 133    audio_prefix_codes = None134    if prefix_audio is not None:135        wav_prefix, sr_prefix = torchaudio.load(prefix_audio)136        wav_prefix = wav_prefix.mean(0, keepdim=True)137        wav_prefix = torchaudio.functional.resample(wav_prefix, sr_prefix, selected_model.autoencoder.sampling_rate)138        wav_prefix = wav_prefix.to(device, dtype=torch.float32)139        with torch.autocast(device, dtype=torch.float32):140            audio_prefix_codes = selected_model.autoencoder.encode(wav_prefix.unsqueeze(0))141 142    emotion_tensor = torch.tensor(list(map(float, [e1, e2, e3, e4, e5, e6, e7, e8])), device=device)143 144    vq_val = float(vq_single)145    vq_tensor = torch.tensor([vq_val] * 8, device=device).unsqueeze(0)146 147    cond_dict = make_cond_dict(148        text=text,149        language=language,150        speaker=speaker_embedding,151        emotion=emotion_tensor,152        vqscore_8=vq_tensor,153        fmax=fmax,154        pitch_std=pitch_std,155        speaking_rate=speaking_rate,156        dnsmos_ovrl=dnsmos_ovrl,157        speaker_noised=speaker_noised_bool,158        device=device,159        unconditional_keys=unconditional_keys,160    )161    conditioning = selected_model.prepare_conditioning(cond_dict)162 163    estimated_generation_duration = 30 * len(text) / 400164    estimated_total_steps = int(estimated_generation_duration * 86)165 166    def update_progress(_frame: torch.Tensor, step: int, _total_steps: int) -> bool:167        progress((step, estimated_total_steps))168        return True169 170    codes = selected_model.generate(171        prefix_conditioning=conditioning,172        audio_prefix_codes=audio_prefix_codes,173        max_new_tokens=max_new_tokens,174        cfg_scale=cfg_scale,175        batch_size=1,176        sampling_params=dict(min_p=min_p),177        callback=update_progress,178    )179 180    wav_out = selected_model.autoencoder.decode(codes).cpu().detach()181    sr_out = selected_model.autoencoder.sampling_rate182    if wav_out.dim() == 2 and wav_out.size(0) > 1:183        wav_out = wav_out[0:1, :]184    return (sr_out, wav_out.squeeze().numpy()), seed185 186 187def build_interface():188    with gr.Blocks(theme='ParityError/Interstellar') as demo:189        gr.Markdown("# Zonos v0.1")190        gr.Markdown("State of the art text-to-speech model [[model]](https://huggingface.co/collections/Zyphra/zonos-v01-67ac661c85e1898670823b4f), [[blog]](https://www.zyphra.com/post/beta-release-of-zonos-v0-1), [[Zyphra Audio (hosted service)]](https://maia.zyphra.com/sign-in?redirect_url=https%3A%2F%2Fmaia.zyphra.com%2Faudio) ")191        with gr.Row():192            with gr.Column():193                text = gr.Textbox(194                    label="Text to Synthesize",195                    value="Zonos uses eSpeak for text to phoneme conversion!",196                    lines=4,197                    max_length=500,  # approximately198                )199                with gr.Row():200                    language = gr.Dropdown(201                        choices=supported_language_codes,202                        value="en-us",203                        label="Language",204                    )205                    model_choice = gr.Dropdown(206                        choices=MODEL_NAMES,207                        value="Zyphra/Zonos-v0.1-transformer",208                        label="Zonos Model Type",209                        info="Select the model variant to use.",210                    )211                speaker_noised_checkbox = gr.Checkbox(212                    label="Denoise Speaker?",213                    value=False214                )215                speaker_audio = gr.Audio(216                    label="Optional Speaker Audio (for cloning)",217                    type="filepath",218                )219                generate_button = gr.Button("Generate Audio")220                221            with gr.Column():222                output_audio = gr.Audio(label="Generated Audio", type="numpy", autoplay=True)223        224        with gr.Accordion("Toggles", open=True):225            gr.Markdown(226                "### Emotion Sliders\n"227                "Warning: The way these sliders work is not intuitive and may require some trial and error to get the desired effect.\n"228                "Certain configurations can cause the model to become unstable. Setting emotion to unconditional may help."229            )230            with gr.Row():231                emotion1 = gr.Slider(0.0, 1.0, 1.0, 0.05, label="Happiness")232                emotion2 = gr.Slider(0.0, 1.0, 0.05, 0.05, label="Sadness")233                emotion3 = gr.Slider(0.0, 1.0, 0.05, 0.05, label="Disgust")234                emotion4 = gr.Slider(0.0, 1.0, 0.05, 0.05, label="Fear")235            with gr.Row():236                emotion5 = gr.Slider(0.0, 1.0, 0.05, 0.05, label="Surprise")237                emotion6 = gr.Slider(0.0, 1.0, 0.05, 0.05, label="Anger")238                emotion7 = gr.Slider(0.0, 1.0, 0.1, 0.05, label="Other")239                emotion8 = gr.Slider(0.0, 1.0, 0.2, 0.05, label="Neutral")240            241            gr.Markdown(242                "### Unconditional Toggles\n"243                "Checking a box will make the model ignore the corresponding conditioning value and make it unconditional.\n"244                'Practically this means the given conditioning feature will be unconstrained and "filled in automatically".'245            )246            with gr.Row():247                unconditional_keys = gr.CheckboxGroup(248                    [249                        "speaker",250                        "emotion",251                        "vqscore_8",252                        "fmax",253                        "pitch_std",254                        "speaking_rate",255                        "dnsmos_ovrl",256                        "speaker_noised",257                    ],258                    value=["emotion"],259                    label="Unconditional Keys",260                )261                    262        with gr.Accordion("Advanced Settings", open=False):263            with gr.Row():264                with gr.Column():265                    gr.Markdown("## Conditioning Parameters")266                    dnsmos_slider = gr.Slider(1.0, 5.0, value=4.0, step=0.1, label="DNSMOS Overall")267                    fmax_slider = gr.Slider(0, 24000, value=24000, step=1, label="Fmax (Hz)")268                    vq_single_slider = gr.Slider(0.5, 0.8, 0.78, 0.01, label="VQ Score")269                    pitch_std_slider = gr.Slider(0.0, 300.0, value=45.0, step=1, label="Pitch Std")270                    speaking_rate_slider = gr.Slider(5.0, 30.0, value=15.0, step=0.5, label="Speaking Rate")271    272                with gr.Column():273                    gr.Markdown("## Generation Parameters")274                    cfg_scale_slider = gr.Slider(1.0, 5.0, 2.0, 0.1, label="CFG Scale")275                    min_p_slider = gr.Slider(0.0, 1.0, 0.15, 0.01, label="Min P")276                    seed_number = gr.Number(label="Seed", value=420, precision=0)277                    randomize_seed_toggle = gr.Checkbox(label="Randomize Seed (before generation)", value=True)278            279            prefix_audio = gr.Audio(280                value="assets/silence_100ms.wav",281                label="Optional Prefix Audio (continue from this audio)",282                type="filepath",283            )284 285        model_choice.change(286            fn=update_ui,287            inputs=[model_choice],288            outputs=[289                text,290                language,291                speaker_audio,292                prefix_audio,293                emotion1,294                emotion2,295                emotion3,296                emotion4,297                emotion5,298                emotion6,299                emotion7,300                emotion8,301                vq_single_slider,302                fmax_slider,303                pitch_std_slider,304                speaking_rate_slider,305                dnsmos_slider,306                speaker_noised_checkbox,307                unconditional_keys,308            ],309        )310 311        # On page load, trigger the same UI refresh312        demo.load(313            fn=update_ui,314            inputs=[model_choice],315            outputs=[316                text,317                language,318                speaker_audio,319                prefix_audio,320                emotion1,321                emotion2,322                emotion3,323                emotion4,324                emotion5,325                emotion6,326                emotion7,327                emotion8,328                vq_single_slider,329                fmax_slider,330                pitch_std_slider,331                speaking_rate_slider,332                dnsmos_slider,333                speaker_noised_checkbox,334                unconditional_keys,335            ],336        )337 338        # Generate audio on button click339        generate_button.click(340            fn=generate_audio,341            inputs=[342                model_choice,343                text,344                language,345                speaker_audio,346                prefix_audio,347                emotion1,348                emotion2,349                emotion3,350                emotion4,351                emotion5,352                emotion6,353                emotion7,354                emotion8,355                vq_single_slider,356                fmax_slider,357                pitch_std_slider,358                speaking_rate_slider,359                dnsmos_slider,360                speaker_noised_checkbox,361                cfg_scale_slider,362                min_p_slider,363                seed_number,364                randomize_seed_toggle,365                unconditional_keys,366            ],367            outputs=[output_audio, seed_number],368        )369 370    return demo371 372 373if __name__ == "__main__":374    demo = build_interface()375    share = getenv("GRADIO_SHARE", "False").lower() in ("true", "1", "t")376    demo.launch(server_name="0.0.0.0", server_port=7860, share=share, ssr_mode=False)377