Write me a C# Unity class that fully integrates into this uvicorn server, I don't want it to be a Unity editor script, but I want to be able to change things in the inspector of the script nicely. Please and thank you.

import os
import sys
import subprocess
import re
import platform
import torch
import logging
import yt_dlp
import json
import copy
import spaces
from fastapi import FastAPI, UploadFile, File, Form, BackgroundTasks, HTTPException
from fastapi.responses import FileResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional, List
from audio_separator.separator import Separator
import uvicorn
import assets.themes.loadThemes as loadThemes
from assets.i18n.i18n import I18nAuto
from assets.presence.discord_presence import RPCManager, track_presence

i18n = I18nAuto()

now_dir = os.getcwd()
sys.path.append(now_dir)
config_file = os.path.join(now_dir, "assets", "config.json")
models_dir = "./models"
out_dir = "./outputs"

device = "cuda" if torch.cuda.is_available() else "cpu"
use_autocast = device == "cuda"

if os.path.isdir("env"):
    if platform.system() == "Windows":
        python_location = ".\\env\\python.exe"
    elif platform.system() == "Linux":
        python_location = "env/bin/python"
else:
    python_location = None

#=======================#
#     DEMUCS Models     #
#=======================#
demucs_models = [
    'htdemucs_ft.yaml',
    'htdemucs_6s.yaml',
    'htdemucs.yaml',
    'hdemucs_mmi.yaml',
]

output_format = [
    'wav',
    'flac',
    'mp3',
    'ogg',
    'opus',
    'm4a',
    'aiff',
    'ac3'
]

extensions = (".wav", ".flac", ".mp3", ".ogg", ".opus", ".m4a", ".aiff", ".ac3")

def load_config_presence():
    with open(config_file, "r", encoding="utf8") as file:
        config = json.load(file)
        return config.get("discord_presence", False)

def initialize_presence():
    if load_config_presence():
        RPCManager.start_presence()

initialize_presence()

def read_main_config():
    try:
        with open(config_file, "r", encoding="utf8") as f:
            return json.load(f)
    except Exception as e:
        print(f"Error reading main config file '{config_file}': {e}")
        return {}

def write_main_config(data):
    try:
        with open(config_file, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=2)
    except Exception as e:
        print(f"Error writing to main config file '{config_file}': {e}")

def load_settings_from_file(filepath):
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        print(f"Error reading settings file '{filepath}': {e}")
        return None

def get_initial_settings():
    main_config = read_main_config()
    load_custom = main_config.get('load_custom_settings', False)

    settings_to_load = {}
    default_settings_file = os.path.join(now_dir, "assets", "default_settings.json")
    custom_settings_file = os.path.join(now_dir, "assets", "custom_settings.json")
    default_settings = load_settings_from_file(default_settings_file)

    if load_custom:
        custom_settings = load_settings_from_file(custom_settings_file)
        if custom_settings:
            settings_to_load = copy.deepcopy(default_settings)
            for section, params in custom_settings.items():
                if section in settings_to_load:
                    for key, value in params.items():
                        settings_to_load[section][key] = value
                else:
                    settings_to_load[section] = params
        else:
            settings_to_load = default_settings
    else:
        settings_to_load = default_settings

    return settings_to_load

initial_settings = get_initial_settings()

app = FastAPI(title="🎵 UVR5 UI 🎵")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class DemucsSeparationParams(BaseModel):
    model: str
    out_format: str
    shifts: int = 2
    segment_size: int = 40
    segments_enabled: bool = True
    overlap: float = 0.25
    batch_size: int = 1
    norm_thresh: float = 0.9
    amp_thresh: float = 0.7

found_files = []
logs = []

@track_presence("Performing Demucs Separation")
@spaces.GPU(duration=60)
def separator_worker(audio_path: str, params: DemucsSeparationParams):
    model_path = os.path.join(models_dir, params.model)
    if not os.path.exists(model_path):
        print(f"Model {params.model} not found, first usage will download model.")

    separator = Separator(
        log_level=logging.WARNING,
        model_file_dir=models_dir,
        output_dir=out_dir,
        output_format=params.out_format,
        use_autocast=use_autocast,
        normalization_threshold=params.norm_thresh,
        amplification_threshold=params.amp_thresh,
        demucs_params={
            "batch_size": params.batch_size,
            "segment_size": params.segment_size,
            "shifts": params.shifts,
            "overlap": params.overlap,
            "segments_enabled": params.segments_enabled,
        }
    )

    separator.load_model(model_filename=params.model)
    separation = separator.separate(audio_path)
    stems = [os.path.join(out_dir, file_name) for file_name in separation]

    # For convenience, return a dictionary with keys stem1..stem6 or None if not applicable
    results = {}
    if params.model == "htdemucs_6s.yaml":
        for i in range(6):
            results[f"stem{i+1}"] = stems[i] if i < len(stems) else None
    else:
        for i in range(4):
            results[f"stem{i+1}"] = stems[i] if i < len(stems) else None
        results["stem5"] = None
        results["stem6"] = None
    return results

@app.post("/download_audio/")
async def download_audio_endpoint(url: str = Form(...)):
    output_dir = "ytdl"
    os.makedirs(output_dir, exist_ok=True)

    _ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'wav',
            'preferredquality': '32',
        }],
        'outtmpl': os.path.join(output_dir, '%(title)s.%(ext)s'),
        'postprocessor_args': [
            '-acodec', 'pcm_f32le'
        ],
        'quiet': True,
        'no_warnings': True,
    }

    try:
        with yt_dlp.YoutubeDL(_ydl_opts) as ydl:
            info = ydl.extract_info(url, download=False)
            video_title = info['title']
            ydl.download([url])
            file_path = os.path.join(output_dir, f"{video_title}.wav")
            if os.path.exists(file_path):
                return {"filepath": os.path.abspath(file_path)}
            raise HTTPException(status_code=500, detail="Downloaded file not found")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"yt-dlp error: {e}")

@app.post("/demucs_separate/")
async def demucs_separate_endpoint(
    background_tasks: BackgroundTasks,
    audio: UploadFile = File(...),
    model: str = Form(...),
    out_format: str = Form(...),
    shifts: int = Form(2),
    segment_size: int = Form(40),
    segments_enabled: bool = Form(True),
    overlap: float = Form(0.25),
    batch_size: int = Form(1),
    norm_thresh: float = Form(0.9),
    amp_thresh: float = Form(0.7),
):
    if model not in demucs_models:
        raise HTTPException(status_code=400, detail="Invalid model selection")
    if out_format not in output_format:
        raise HTTPException(status_code=400, detail="Invalid output format")

    audio_location = os.path.join("temp_uploads", audio.filename)
    os.makedirs("temp_uploads", exist_ok=True)
    with open(audio_location, "wb") as f:
        content = await audio.read()
        f.write(content)

    params = DemucsSeparationParams(
        model=model,
        out_format=out_format,
        shifts=shifts,
        segment_size=segment_size,
        segments_enabled=segments_enabled,
        overlap=overlap,
        batch_size=batch_size,
        norm_thresh=norm_thresh,
        amp_thresh=amp_thresh,
    )

    try:
        res = separator_worker(audio_location, params)
        return JSONResponse(content=res)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/demucs_batch/")
@track_presence("Performing Demucs Batch Separation")
@spaces.GPU(duration=60)
async def demucs_batch_endpoint(
    path_input: str = Form(...),
    path_output: str = Form(...),
    model: str = Form(...),
    out_format: str = Form(...),
    shifts: int = Form(2),
    segment_size: int = Form(40),
    segments_enabled: bool = Form(True),
    overlap: float = Form(0.25),
    batch_size: int = Form(1),
    norm_thresh: float = Form(0.9),
    amp_thresh: float = Form(0.7),
):
    if not os.path.isdir(path_input):
        raise HTTPException(status_code=400, detail="Input path does not exist or is not a directory")
    if not os.path.isdir(path_output):
        raise HTTPException(status_code=400, detail="Output path does not exist or is not a directory")

    model_path = os.path.join(models_dir, model)
    if not os.path.exists(model_path):
        print(f"This is the first time the {model} model is being used. Downloading...")

    found_files.clear()
    logs.clear()

    for audio_files in os.listdir(path_input):
        if audio_files.endswith(extensions):
            found_files.append(audio_files)
    total_files = len(found_files)

    if total_files == 0:
        logs.append("No valid audio files.")
        return {"log": "\n".join(logs)}

    logs.append(f"{total_files} audio files found")
    found_files.sort()

    for i, audio_files in enumerate(found_files):
        logs.append(f"Processing file {i+1}/{total_files}: {audio_files}")
        file_path = os.path.join(path_input, audio_files)
        try:
            separator = Separator(
                log_level=logging.WARNING,
                model_file_dir=models_dir,
                output_dir=path_output,
                output_format=out_format,
                use_autocast=use_autocast,
                normalization_threshold=norm_thresh,
                amplification_threshold=amp_thresh,
                demucs_params={
                    "batch_size": batch_size,
                    "segment_size": segment_size,
                    "shifts": shifts,
                    "overlap": overlap,
                    "segments_enabled": segments_enabled,
                }
            )
            separator.load_model(model_filename=model)
            separator.separate(file_path)
            logs.append(f"File: {audio_files} separated!")
        except Exception as e:
            logs.append(f"Failed to separate {audio_files}: {e}")
            raise HTTPException(status_code=500, detail=f"Demucs batch separation failed: {e}")

    logs.append("Processing complete")
    return {"log": "\n".join(logs)}

@app.get("/")
def read_root():
    return {"message": "🎵 UVR5 UI - FastAPI server is running."}

# To run the server via uvicorn if this file is run directly
if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=7860, reload=False)