CoolFace
Apppublic

svjack/IndexTTS-2-Demo

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
0likes
webui.py426 linesDownload Raw Back to root
1 2'''3pip install protobuf==3.20.04pip uninstall torch torchvision torchaudio5pip install -U torch torchvision torchaudio6 7'''8 9'''10import os11from gradio_client import Client, handle_file12from shutil import copy213 14# 初始化Gradio客户端15client = Client("http://localhost:7860/")16 17# 请替换为您准备好的参考音频文件路径18reference_audio = '马正阳英文念白_vocals.wav' 19 20# 莎士比亚名言列表(英文原文),这里只是示例,您可以自行增删21shakespeare_quotes = [22    "To be, or not to be: that is the question.",23    "All the world's a stage, and all the men and women merely players.",24    "There is nothing either good or bad, but thinking makes it so.",25    "The course of true love never did run smooth.",26    "Love is blind and lovers cannot see the pretty follies that themselves commit.",27    "All that glisters is not gold.",28    "Brevity is the soul of wit.",29    "What's in a name? That which we call a rose by any other word would smell as sweet.",30    "Sweet are the uses of adversity.",31    "Cowards die many times before their deaths; The valiant never taste of death but once."32]33 34# 输出目录,确保此目录存在35output_dir = 'MaZhengYang_IndexTTS2_Shakespeare_Audio'36os.makedirs(output_dir, exist_ok=True)37 38for index, quote_text in enumerate(shakespeare_quotes):39    try:40        print(f"Processing {index+1}/{len(shakespeare_quotes)}: {quote_text[:50]}...")41 42        # 调用Gradio API进行语音合成43        result = client.predict(44            emo_control_method="Same as the voice reference",45            prompt=handle_file(reference_audio), # 使用您提供的参考音频46            text=quote_text, # 填入当前要合成的名言英文原文47            emo_ref_path=None,48            emo_weight=0.8,49            vec1=0,50            vec2=0,51            vec3=0,52            vec4=0,53            vec5=0,54            vec6=0,55            vec7=0,56            vec8=0,57            emo_text="",58            emo_random=False,59            max_text_tokens_per_sentence=120,60            param_16=True,61            param_17=0.8,62            param_18=30,63            param_19=0.8,64            param_20=0,65            param_21=3,66            param_22=10,67            param_23=1500,68            api_name="/gen_single"69        )70 71        # 假设返回的result是一个字典,且音频文件路径在result["value"]中72        generated_audio_path = result["value"]73        74        # 生成序列号,例如 000001, 000002, ...75        sequence_number = str(index + 1).zfill(6)76        new_audio_filename = f"{sequence_number}.wav"77        new_audio_path = os.path.join(output_dir, new_audio_filename)78 79        # 复制并重命名音频文件80        copy2(generated_audio_path, new_audio_path)81        print(f"Audio saved to: {new_audio_path}")82 83        # 创建同名的.txt文件并写入英文名言84        txt_filename = f"{sequence_number}.txt"85        txt_path = os.path.join(output_dir, txt_filename)86        with open(txt_path, 'w', encoding='utf-8') as f:87            f.write(quote_text)88        print(f"Text file saved to: {txt_path}")89 90    except Exception as e:91        print(f"Error processing quote '{quote_text}': {e}")92 93print("All processing completed!")94 95'''96 97import json98import logging99import spaces100import os101import sys102import threading103import time104 105import warnings106 107import pandas as pd108 109warnings.filterwarnings("ignore", category=FutureWarning)110warnings.filterwarnings("ignore", category=UserWarning)111 112current_dir = os.path.dirname(os.path.abspath(__file__))113sys.path.append(current_dir)114sys.path.append(os.path.join(current_dir, "indextts"))115 116import argparse117parser = argparse.ArgumentParser(description="IndexTTS WebUI")118parser.add_argument("--verbose", action="store_true", default=False, help="Enable verbose mode")119parser.add_argument("--port", type=int, default=7860, help="Port to run the web UI on")120parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to run the web UI on")121parser.add_argument("--model_dir", type=str, default="checkpoints", help="Model checkpoints directory")122parser.add_argument("--is_fp16", action="store_true", default=False, help="Fp16 infer")123cmd_args = parser.parse_args()124 125from tools.download_files import download_model_from_huggingface126download_model_from_huggingface(os.path.join(current_dir,"checkpoints"),127                                os.path.join(current_dir, "checkpoints","hf_cache"))128 129import gradio as gr130from indextts import infer131from indextts.infer_v2 import IndexTTS2132from tools.i18n.i18n import I18nAuto133from modelscope.hub import api134 135i18n = I18nAuto(language="Auto")136MODE = 'local'137tts = IndexTTS2(model_dir=cmd_args.model_dir,138                cfg_path=os.path.join(cmd_args.model_dir, "config.yaml"),139                is_fp16=False,use_cuda_kernel=False)140 141# 支持的语言列表142LANGUAGES = {143    "中文": "zh_CN",144    "English": "en_US"145}146EMO_CHOICES = [i18n("与音色参考音频相同"),147                i18n("使用情感参考音频"),148                i18n("使用情感向量控制"),149                i18n("使用情感描述文本控制")]150os.makedirs("outputs/tasks",exist_ok=True)151os.makedirs("prompts",exist_ok=True)152 153MAX_LENGTH_TO_USE_SPEED = 70154with open("examples/cases.jsonl", "r", encoding="utf-8") as f:155    example_cases = []156    for line in f:157        line = line.strip()158        if not line:159            continue160        example = json.loads(line)161        if example.get("emo_audio",None):162            emo_audio_path = os.path.join("examples",example["emo_audio"])163        else:164            emo_audio_path = None165        example_cases.append([os.path.join("examples", example.get("prompt_audio", "sample_prompt.wav")),166                              EMO_CHOICES[example.get("emo_mode",0)],167                              example.get("text"),168                             emo_audio_path,169                             example.get("emo_weight",1.0),170                             example.get("emo_text",""),171                             example.get("emo_vec_1",0),172                             example.get("emo_vec_2",0),173                             example.get("emo_vec_3",0),174                             example.get("emo_vec_4",0),175                             example.get("emo_vec_5",0),176                             example.get("emo_vec_6",0),177                             example.get("emo_vec_7",0),178                             example.get("emo_vec_8",0)]179                             )180 181@spaces.GPU182def gen_single(emo_control_method,prompt, text,183               emo_ref_path, emo_weight,184               vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8,185               emo_text,emo_random,186               max_text_tokens_per_sentence=120,187                *args, progress=gr.Progress()):188    output_path = None189    if not output_path:190        output_path = os.path.join("outputs", f"spk_{int(time.time())}.wav")191    # set gradio progress192    tts.gr_progress = progress193    do_sample, top_p, top_k, temperature, \194        length_penalty, num_beams, repetition_penalty, max_mel_tokens = args195    kwargs = {196        "do_sample": bool(do_sample),197        "top_p": float(top_p),198        "top_k": int(top_k) if int(top_k) > 0 else None,199        "temperature": float(temperature),200        "length_penalty": float(length_penalty),201        "num_beams": num_beams,202        "repetition_penalty": float(repetition_penalty),203        "max_mel_tokens": int(max_mel_tokens),204        # "typical_sampling": bool(typical_sampling),205        # "typical_mass": float(typical_mass),206    }207    if type(emo_control_method) is not int:208        emo_control_method = emo_control_method.value209    if emo_control_method == 0:210        emo_ref_path = None211        emo_weight = 1.0212    if emo_control_method == 1:213        emo_weight = emo_weight214    if emo_control_method == 2:215        vec = [vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8]216        vec_sum = sum([vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8])217        if vec_sum > 1.5:218            gr.Warning(i18n("情感向量之和不能超过1.5,请调整后重试。"))219            return220    else:221        vec = None222 223    print(f"Emo control mode:{emo_control_method},vec:{vec}")224    output = tts.infer(spk_audio_prompt=prompt, text=text,225                       output_path=output_path,226                       emo_audio_prompt=emo_ref_path, emo_alpha=emo_weight,227                       emo_vector=vec,228                       use_emo_text=(emo_control_method==3), emo_text=emo_text,use_random=emo_random,229                       verbose=cmd_args.verbose,230                       max_text_tokens_per_sentence=int(max_text_tokens_per_sentence),231                       **kwargs)232    return gr.update(value=output,visible=True)233 234def update_prompt_audio():235    update_button = gr.update(interactive=True)236    return update_button237 238with gr.Blocks(title="IndexTTS Demo") as demo:239    mutex = threading.Lock()240    gr.HTML('''241    <h2><center>IndexTTS2: A Breakthrough in Emotionally Expressive and Duration-Controlled Auto-Regressive Zero-Shot Text-to-Speech</h2>242<p align="center">243<a href='https://arxiv.org/abs/2506.21619'><img src='https://img.shields.io/badge/ArXiv-2506.21619-red'></a>244</p>245    ''')246    with gr.Tab(i18n("音频生成")):247        with gr.Row():248            os.makedirs("prompts",exist_ok=True)249            prompt_audio = gr.Audio(label=i18n("音色参考音频"),key="prompt_audio",250                                    sources=["upload","microphone"],type="filepath")251            prompt_list = os.listdir("prompts")252            default = ''253            if prompt_list:254                default = prompt_list[0]255            with gr.Column():256                input_text_single = gr.TextArea(label=i18n("文本"),key="input_text_single", placeholder=i18n("请输入目标文本"), info=f"{i18n('当前模型版本')}{tts.model_version or '1.0'}")257                gen_button = gr.Button(i18n("生成语音"), key="gen_button",interactive=True)258            output_audio = gr.Audio(label=i18n("生成结果"), visible=True,key="output_audio")259        with gr.Accordion(i18n("功能设置")):260            # 情感控制选项部分261            with gr.Row():262                emo_control_method = gr.Radio(263                    choices=EMO_CHOICES,264                    type="index",265                    value=EMO_CHOICES[0],label=i18n("情感控制方式"))266        # 情感参考音频部分267        with gr.Group(visible=False) as emotion_reference_group:268            with gr.Row():269                emo_upload = gr.Audio(label=i18n("上传情感参考音频"), type="filepath")270 271            with gr.Row():272                emo_weight = gr.Slider(label=i18n("情感权重"), minimum=0.0, maximum=1.6, value=0.8, step=0.01)273 274        # 情感随机采样275        with gr.Row():276            emo_random = gr.Checkbox(label=i18n("情感随机采样"),value=False,visible=False)277 278        # 情感向量控制部分279        with gr.Group(visible=False) as emotion_vector_group:280            with gr.Row():281                with gr.Column():282                    vec1 = gr.Slider(label=i18n("喜"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)283                    vec2 = gr.Slider(label=i18n("怒"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)284                    vec3 = gr.Slider(label=i18n("哀"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)285                    vec4 = gr.Slider(label=i18n("惧"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)286                with gr.Column():287                    vec5 = gr.Slider(label=i18n("厌恶"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)288                    vec6 = gr.Slider(label=i18n("低落"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)289                    vec7 = gr.Slider(label=i18n("惊喜"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)290                    vec8 = gr.Slider(label=i18n("平静"), minimum=0.0, maximum=1.4, value=0.0, step=0.05)291 292        with gr.Group(visible=False) as emo_text_group:293            with gr.Row():294                emo_text = gr.Textbox(label=i18n("情感描述文本"), placeholder=i18n("请输入情感描述文本"), value="", info=i18n("例如:高兴,愤怒,悲伤等"))295 296        with gr.Accordion(i18n("高级生成参数设置"), open=False):297            with gr.Row():298                with gr.Column(scale=1):299                    gr.Markdown(f"**{i18n('GPT2 采样设置')}** _{i18n('参数会影响音频多样性和生成速度详见')}[Generation strategies](https://huggingface.co/docs/transformers/main/en/generation_strategies)_")300                    with gr.Row():301                        do_sample = gr.Checkbox(label="do_sample", value=True, info="是否进行采样")302                        temperature = gr.Slider(label="temperature", minimum=0.1, maximum=2.0, value=0.8, step=0.1)303                    with gr.Row():304                        top_p = gr.Slider(label="top_p", minimum=0.0, maximum=1.0, value=0.8, step=0.01)305                        top_k = gr.Slider(label="top_k", minimum=0, maximum=100, value=30, step=1)306                        num_beams = gr.Slider(label="num_beams", value=3, minimum=1, maximum=10, step=1)307                    with gr.Row():308                        repetition_penalty = gr.Number(label="repetition_penalty", precision=None, value=10.0, minimum=0.1, maximum=20.0, step=0.1)309                        length_penalty = gr.Number(label="length_penalty", precision=None, value=0.0, minimum=-2.0, maximum=2.0, step=0.1)310                    max_mel_tokens = gr.Slider(label="max_mel_tokens", value=1500, minimum=50, maximum=tts.cfg.gpt.max_mel_tokens, step=10, info="生成Token最大数量,过小导致音频被截断", key="max_mel_tokens")311                    # with gr.Row():312                    #     typical_sampling = gr.Checkbox(label="typical_sampling", value=False, info="不建议使用")313                    #     typical_mass = gr.Slider(label="typical_mass", value=0.9, minimum=0.0, maximum=1.0, step=0.1)314                with gr.Column(scale=2):315                    gr.Markdown(f'**{i18n("分句设置")}** _{i18n("参数会影响音频质量和生成速度")}_')316                    with gr.Row():317                        max_text_tokens_per_sentence = gr.Slider(318                            label=i18n("分句最大Token数"), value=120, minimum=20, maximum=tts.cfg.gpt.max_text_tokens, step=2, key="max_text_tokens_per_sentence",319                            info=i18n("建议80~200之间,值越大,分句越长;值越小,分句越碎;过小过大都可能导致音频质量不高"),320                        )321                    with gr.Accordion(i18n("预览分句结果"), open=True) as sentences_settings:322                        sentences_preview = gr.Dataframe(323                            headers=[i18n("序号"), i18n("分句内容"), i18n("Token数")],324                            key="sentences_preview",325                            wrap=True,326                        )327            advanced_params = [328                do_sample, top_p, top_k, temperature,329                length_penalty, num_beams, repetition_penalty, max_mel_tokens,330                # typical_sampling, typical_mass,331            ]332        333        if len(example_cases) > 0:334            gr.Examples(335                examples=example_cases,336                examples_per_page=20,337                inputs=[prompt_audio,338                        emo_control_method,339                        input_text_single,340                        emo_upload,341                        emo_weight,342                        emo_text,343                        vec1,vec2,vec3,vec4,vec5,vec6,vec7,vec8]344            )345 346    def on_input_text_change(text, max_tokens_per_sentence):347        if text and len(text) > 0:348            text_tokens_list = tts.tokenizer.tokenize(text)349 350            sentences = tts.tokenizer.split_sentences(text_tokens_list, max_tokens_per_sentence=int(max_tokens_per_sentence))351            data = []352            for i, s in enumerate(sentences):353                sentence_str = ''.join(s)354                tokens_count = len(s)355                data.append([i, sentence_str, tokens_count])356            return {357                sentences_preview: gr.update(value=data, visible=True, type="array"),358            }359        else:360            df = pd.DataFrame([], columns=[i18n("序号"), i18n("分句内容"), i18n("Token数")])361            return {362                sentences_preview: gr.update(value=df),363            }364    def on_method_select(emo_control_method):365        if emo_control_method == 1:366            return (gr.update(visible=True),367                    gr.update(visible=False),368                    gr.update(visible=False),369                    gr.update(visible=False)370                    )371        elif emo_control_method == 2:372            return (gr.update(visible=False),373                    gr.update(visible=True),374                    gr.update(visible=True),375                    gr.update(visible=False)376                    )377        elif emo_control_method == 3:378            return (gr.update(visible=False),379                    gr.update(visible=True),380                    gr.update(visible=False),381                    gr.update(visible=True)382                    )383        else:384            return (gr.update(visible=False),385                    gr.update(visible=False),386                    gr.update(visible=False),387                    gr.update(visible=False)388                    )389 390    emo_control_method.select(on_method_select,391        inputs=[emo_control_method],392        outputs=[emotion_reference_group,393                 emo_random,394                 emotion_vector_group,395                 emo_text_group]396    )397 398    input_text_single.change(399        on_input_text_change,400        inputs=[input_text_single, max_text_tokens_per_sentence],401        outputs=[sentences_preview]402    )403    max_text_tokens_per_sentence.change(404        on_input_text_change,405        inputs=[input_text_single, max_text_tokens_per_sentence],406        outputs=[sentences_preview]407    )408    prompt_audio.upload(update_prompt_audio,409                         inputs=[],410                         outputs=[gen_button])411 412    gen_button.click(gen_single,413                     inputs=[emo_control_method,prompt_audio, input_text_single, emo_upload, emo_weight,414                            vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8,415                             emo_text,emo_random,416                             max_text_tokens_per_sentence,417                             *advanced_params,418                     ],419                     outputs=[output_audio])420 421 422 423if __name__ == "__main__":424    demo.queue(20)425    demo.launch(server_name="0.0.0.0", server_port=7860, share = True)426