'my uvicorn server '
import os
import shutil
import sys
import threading
import time

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=UserWarning)

current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)
sys.path.append(os.path.join(current_dir, "indextts"))

import gradio as gr
from indextts.utils.webui_utils import next_page, prev_page
from indextts.infer import IndexTTS
from tools.i18n.i18n import I18nAuto

i18n = I18nAuto(language="zh_CN")
MODE = 'local'
tts = IndexTTS(model_dir="checkpoints", cfg_path="checkpoints/config.yaml")

os.makedirs("outputs/tasks", exist_ok=True)
os.makedirs("prompts", exist_ok=True)


def gen_single(prompt, text, infer_mode, progress=gr.Progress()):
    output_path = None
    if not output_path:
        output_path = os.path.join("outputs", f"spk_{int(time.time())}.wav")
    # set gradio progress
    tts.gr_progress = progress
    if infer_mode == "ordinary reasoning":
        output = tts.infer(prompt, text, output_path)  # 普通推理
    else:
        output = tts.infer_fast(prompt, text, output_path)  # 批次推理
    return gr.update(value=output, visible=True)


def update_prompt_audio():
    update_button = gr.update(interactive=True)
    return update_button


with gr.Blocks() as demo:
    mutex = threading.Lock()
    gr.HTML('''
    <h2><center>IndexTTS: Fast As Grits TTS</h2>

<p align="center">
<a href='meep.com'><img src='https://iconduck.com/api/v2/vectors/vctraz6uhm2x/media/png/256/download'></a>
    ''')
    with gr.Tab("音频生成"):
        with gr.Row():
            os.makedirs("prompts", exist_ok=True)
            prompt_audio = gr.Audio(
                label="Please upload reference audio",
                key="prompt_audio",
                sources=["upload", "microphone"],
                type="filepath"
            )
            prompt_list = os.listdir("prompts")
            default = ''
            if prompt_list:
                default = prompt_list[0]
            with gr.Column():
                input_text_single = gr.TextArea(
                    label="Please enter target text",
                    key="input_text_single"
                )
                infer_mode = gr.Radio(
                    choices=["ordinary reasoning", "batch inference"],
                    label="Select inference mode（batch inference：More suitable for long sentences，Double the performance）",
                    value="ordinary reasoning"
                )
                gen_button = gr.Button("Generate speech", key="gen_button", interactive=True)
            output_audio = gr.Audio(label="Generate results", visible=True, key="output_audio")

    prompt_audio.upload(
        update_prompt_audio,
        inputs=[],
        outputs=[gen_button]
    )

    gen_button.click(
        gen_single,
        inputs=[prompt_audio, input_text_single, infer_mode],
        outputs=[output_audio]
    )

# ----------------------------------------------
# Expose Gradio as ASGI app for uvicorn
# ----------------------------------------------
app = demo

if __name__ == "__main__":
    import uvicorn

    # Use Gradio Blocks' `serve` method to get ASGI app or directly `app` is a Blocks object which acts as ASGI app.
    # Since Gradio 3.32+, Blocks is itself ASGI compatible:
    # So uvicorn can run it directly like this:

    uvicorn.run(app, host="127.0.0.1", port=7860)

'my c# script'
string targetText = "Hello, this is a test.";
string inferMode = "ordinary reasoning";  // or "batch inference"
private static readonly string GradioServerUrl = "http://127.0.0.1:7860/run/predict";

public void DebugMeNShit()
{
    GenerateSpeech(RefAudioFile, "Fast as tits.", inferMode);
}

static async Task<string> GenerateSpeech(string audioFilePath, string inputText, string inferMode)
{
    using HttpClient client = new();

    // Read audio file bytes and convert to base64 string
    byte[] audioBytes = await File.ReadAllBytesAsync(audioFilePath);
    string audioBase64 = Convert.ToBase64String(audioBytes);

    var json = new
    {
        data = new object[]
        {
        "data:audio/wav;base64," + audioBase64,
        inputText,
        inferMode
        },
        fn_index = 0
    };

    var jsonString = System.Text.Json.JsonSerializer.Serialize(json);

    using var content = new StringContent(jsonString);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

    var response = await client.PostAsync(GradioServerUrl, content);

    if (!response.IsSuccessStatusCode)
    {
        throw new Exception($"Server returned status code {response.StatusCode}");
    }

    var responseJson = await response.Content.ReadAsStringAsync();

    using var doc = System.Text.Json.JsonDocument.Parse(responseJson);
    var root = doc.RootElement;

    var dataArr = root.GetProperty("data");

    if (dataArr.GetArrayLength() == 0)
        throw new Exception("Empty response data.");

    var generatedAudioPathOrUrl = dataArr[0].GetString();

    return generatedAudioPathOrUrl;
}

'errors occured'
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\Users\DjZaN\miniconda3\envs\index-tts\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 403, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "C:\Users\DjZaN\miniconda3\envs\index-tts\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\DjZaN\miniconda3\envs\index-tts\lib\site-packages\uvicorn\middleware\asgi2.py", line 14, in __call__
    instance = self.app(scope)
TypeError: 'dict' object is not callable
INFO:     127.0.0.1:53160 - "POST /run/predict HTTP/1.1" 500 Internal Server Error