CoolFace
Apppublic

kwau/sovits-isla

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
app.py1513 linesDownload Raw Back to root
1import ast2import base643import datetime4import glob5import json6import logging7import multiprocessing8import os9import re10import requests11import shutil12import subprocess13import sys14import traceback15import zipfile16from itertools import chain17from pathlib import Path18 19import gradio as gr20import librosa21import numpy as np22import soundfile as sf23import torch24import yaml25 26from auto_slicer import AutoSlicer27from compress_model import removeOptimizer28from inference.infer_tool_webui import Svc29from onnx_export import main as onnx_export30from sami import SAMIService31from tts_voices import SUPPORTED_LANGUAGES32from utils import mix_model33 34os.environ["PATH"] += os.pathsep + os.path.join(os.getcwd(), "ffmpeg", "bin")35 36logging.getLogger('numba').setLevel(logging.WARNING)37logging.getLogger('markdown_it').setLevel(logging.WARNING)38logging.getLogger('urllib3').setLevel(logging.WARNING)39logging.getLogger('matplotlib').setLevel(logging.WARNING)40 41# Some directories42workdir = "logs/44k"43second_dir = "models"44diff_second_dir = "models/diffusion"45diff_workdir = "logs/44k/diffusion"46config_dir = "configs/"47dataset_dir = "dataset/44k"48raw_path = "dataset_raw"49raw_wavs_path = "raw"50models_backup_path = 'models_backup'51root_dir = "checkpoints"52default_settings_file = "settings.yaml"53current_mode = ""54# Some global variables55debug = False56precheck_ok = False57model = None58sovits_params = {}59diff_params = {}60# Some dicts for mapping61MODEL_TYPE = {62    "vec768l12": 768,63    "vec256l9": 256,64    "hubertsoft": 256,65    "whisper-ppg": 1024,66    "cnhubertlarge": 1024,67    "dphubert": 768,68    "wavlmbase+": 768,69    "whisper-ppg-large": 128070}71ENCODER_PRETRAIN = {72    "vec256l9": "pretrain/checkpoint_best_legacy_500.pt",73    "vec768l12": "pretrain/checkpoint_best_legacy_500.pt",74    "hubertsoft": "pretrain/hubert-soft-0d54a1f4.pt",75    "whisper-ppg": "pretrain/medium.pt",76    "cnhubertlarge": "pretrain/chinese-hubert-large-fairseq-ckpt.pt",77    "dphubert": "pretrain/DPHuBERT-sp0.75.pth",78    "wavlmbase+": "pretrain/WavLM-Base+.pt",79    "whisper-ppg-large": "pretrain/large-v2.pt"80}81 82 83class Config:84    def __init__(self, path, type):85        self.path = path86        self.type = type87    88    def read(self):89        if self.type == "json":90            with open(self.path, 'r') as f:91                return json.load(f)92        if self.type == "yaml":93            with open(self.path, 'r') as f:94                return yaml.safe_load(f)95    96    def save(self, content):97        if self.type == "json":98            with open(self.path, 'w') as f:99                json.dump(content, f, indent=4)100        if self.type == "yaml":101            with open(self.path, 'w') as f:102                yaml.safe_dump(content, f, default_flow_style=False, sort_keys=False)103 104 105class ReleasePacker:106    def __init__(self, speaker, model):107        self.speaker = speaker108        self.model = model109        self.output_path = os.path.join("release_packs", f"{speaker}_release.zip")110        self.file_list = []111 112    def remove_temp(self, path):113        for filename in os.listdir(path):114            file_path = os.path.join(path, filename)115            if os.path.isfile(file_path) and not filename.endswith(".zip"):116                os.remove(file_path)117            elif os.path.isdir(file_path):118                shutil.rmtree(file_path, ignore_errors=True)119 120    def add_file(self, file_paths):121        self.file_list.extend(file_paths)122    123    def spk_to_dict(self):124        spk_string = self.speaker.replace(',', ',')125        spk_string = spk_string.replace(' ', '')126        _spk = spk_string.split(',')127        return {_spk: index for index, _spk in enumerate(_spk)}128 129    def generate_config(self, diff_model, config_origin):130        _config_origin = Config(os.path.join(config_read_dir, config_origin), "json")131        _template = Config("release_packs/config_template.json", "json")132        _d_template = Config("release_packs/diffusion_template.yaml", "yaml")133        orig_config = _config_origin.read()134        config_template = _template.read()135        diff_config_template = _d_template.read()136        spk_dict = self.spk_to_dict()137        _net = torch.load(os.path.join(ckpt_read_dir, self.model), map_location='cpu')138        emb_dim, model_dim = _net['model'].get('emb_g.weight', torch.empty(0, 0)).size()139        vol_emb = _net['model'].get('emb_vol.weight')140        if vol_emb is not None:141            config_template["train"]["vol_aug"] = config_template["model"]["vol_embedding"] = True142        #Keep the spk_dict length same as emb_dim143        if emb_dim > len(spk_dict):144            for i in range(emb_dim - len(spk_dict)):145                spk_dict[f"spk{i}"] = len(spk_dict)146        if emb_dim < len(spk_dict):147            for i in range(len(spk_dict) - emb_dim):148                spk_dict.popitem()149        self.speaker = ','.join(spk_dict.keys())150        config_template['model']['ssl_dim'] = config_template["model"]["filter_channels"] = config_template["model"]["gin_channels"] = model_dim151        config_template['model']['n_speakers'] = diff_config_template['model']['n_spk'] = emb_dim152        config_template['spk'] = diff_config_template['spk'] = spk_dict153        encoder = [k for k, v in MODEL_TYPE.items() if v == model_dim]154        if orig_config['model']['speech_encoder'] in encoder:155            config_template['model']['speech_encoder'] = orig_config['model']['speech_encoder']156        else:157            raise Exception("Config is not compatible with the model")158        159        if diff_model != "no_diff":160            _diff = torch.load(os.path.join(diff_read_dir, diff_model), map_location='cpu')161            _, diff_dim = _diff["model"].get("unit_embed.weight", torch.empty(0, 0)).size()162            if diff_dim == 256:163                diff_config_template['data']['encoder'] = 'hubertsoft'164                diff_config_template['data']['encoder_out_channels'] = 256165            elif diff_dim == 768:166                diff_config_template['data']['encoder'] = 'vec768l12'167                diff_config_template['data']['encoder_out_channels'] = 768168            elif diff_dim == 1024:169                diff_config_template['data']['encoder'] = 'whisper-ppg'170                diff_config_template['data']['encoder_out_channels'] = 1024171 172        with open("release_packs/install.txt", 'w') as f:173            f.write(str(self.file_list) + '#' + str(self.speaker))174 175        _template.save(config_template)176        _d_template.save(diff_config_template)177 178    def unpack(self, zip_file):179        with zipfile.ZipFile(zip_file, 'r') as zipf:180            zipf.extractall("release_packs")181 182    def formatted_install(self, install_txt):183        with open(install_txt, 'r') as f:184            content = f.read()185        file_list, speaker = content.split('#')186        self.speaker = speaker187        file_list = ast.literal_eval(file_list)188        self.file_list = file_list189        for _, target_path in self.file_list:190            if target_path != "install.txt" and target_path != "":191                shutil.move(os.path.join("release_packs", target_path), target_path)192        self.remove_temp("release_packs")193        return self.speaker194 195    def pack(self):196        with zipfile.ZipFile(self.output_path, 'w', zipfile.ZIP_DEFLATED) as zipf:197            for file_path, target_path in self.file_list:198                if os.path.isfile(file_path):199                    zipf.write(file_path, arcname=target_path)200 201 202def debug_change():203    global debug204    debug = debug_button.value205 206def get_default_settings():207    global sovits_params, diff_params, second_dir_enable208    config_file = Config(default_settings_file, "yaml")209    default_settings = config_file.read()210    sovits_params = default_settings['sovits_params']211    diff_params = default_settings['diff_params']212    webui_settings = default_settings['webui_settings']213    second_dir_enable = webui_settings['second_dir']214    return sovits_params, diff_params, second_dir_enable215 216def webui_change(read_second_dir):217    global second_dir_enable218    config_file = Config(default_settings_file, "yaml")219    default_settings = config_file.read()220    second_dir_enable = default_settings['webui_settings']['second_dir'] = read_second_dir221    config_file.save(default_settings)222 223def get_current_mode():224    global current_mode225    current_mode = "当前模式:独立目录模式,将从'./models/'读取模型文件" if second_dir_enable else "当前模式:工作目录模式,将从'./logs/44k'读取模型文件" 226    return current_mode227 228def save_default_settings(log_interval,eval_interval,keep_ckpts,batch_size,learning_rate,amp_dtype,all_in_mem,num_workers,cache_all_data,cache_device,diff_amp_dtype,diff_batch_size,diff_lr,diff_interval_log,diff_interval_val,diff_force_save,diff_k_step_max):229    config_file = Config(default_settings_file, "yaml")230    default_settings = config_file.read()231    default_settings['sovits_params']['log_interval'] = int(log_interval)232    default_settings['sovits_params']['eval_interval'] = int(eval_interval)233    default_settings['sovits_params']['keep_ckpts'] = int(keep_ckpts)234    default_settings['sovits_params']['batch_size'] = int(batch_size)235    default_settings['sovits_params']['learning_rate'] = float(learning_rate)236    default_settings['sovits_params']['amp_dtype'] = str(amp_dtype)237    default_settings['sovits_params']['all_in_mem'] = all_in_mem238    default_settings['diff_params']['num_workers'] = int(num_workers)239    default_settings['diff_params']['cache_all_data'] = cache_all_data240    default_settings['diff_params']['cache_device'] = str(cache_device)241    default_settings['diff_params']['amp_dtype'] = str(diff_amp_dtype)242    default_settings['diff_params']['diff_batch_size'] = int(diff_batch_size)243    default_settings['diff_params']['diff_lr'] = float(diff_lr)244    default_settings['diff_params']['diff_interval_log'] = int(diff_interval_log)245    default_settings['diff_params']['diff_interval_val'] = int(diff_interval_val)246    default_settings['diff_params']['diff_force_save'] = int(diff_force_save)247    default_settings['diff_params']['diff_k_step_max'] = diff_k_step_max248    config_file.save(default_settings)249    return "成功保存默认配置"250 251def get_model_info(choice_ckpt):252    pthfile = os.path.join(ckpt_read_dir, choice_ckpt)253    net = torch.load(pthfile, map_location=torch.device('cpu')) #cpu load to avoid using gpu memory254    spk_emb = net["model"].get("emb_g.weight")255    if spk_emb is None:256        return "所选模型缺少emb_g.weight,你可能选择了一个底模"257    _layer = spk_emb.size(1)258    encoder = [k for k, v in MODEL_TYPE.items() if v == _layer] #通过维度对应编码器259    encoder.sort()260    if encoder == ["hubertsoft", "vec256l9"]:261        encoder = ["vec256l9 / hubertsoft"]262    if encoder == ["cnhubertlarge", "whisper-ppg"]:263        encoder = ["whisper-ppg / cnhubertlarge"]264    if encoder == ["dphubert", "vec768l12", "wavlmbase+"]:265        encoder = ["vec768l12 / dphubert / wavlmbase+"]266    return encoder[0]267    268def load_json_encoder(config_choice, choice_ckpt):269    if config_choice == "no_config":270        return "未启用自动加载,请手动选择配置文件"271    if choice_ckpt == "no_model":272        return "请先选择模型"273    config_file = Config(os.path.join(config_read_dir, config_choice), "json")274    config = config_file.read()275    try:276        #比对配置文件中的模型维度与该encoder的实际维度是否对应,防止古神语277        config_encoder = config["model"].get("speech_encoder", "no_encoder")278        config_dim = config["model"]["ssl_dim"]279        #旧版配置文件自动匹配280        if config_encoder == "no_encoder":281            config_encoder = config["model"]["speech_encoder"] = "vec256l9" if config_dim == 256 else "vec768l12"282            config_file.save(config)283        correct_dim = MODEL_TYPE.get(config_encoder, "unknown")284        if config_dim != correct_dim:285            return "配置文件中的编码器与模型维度不匹配"286        return config_encoder287    except Exception as e:288        return f"出错了: {e}"289        290def auto_load(choice_ckpt):291    global second_dir_enable292    model_output_msg = get_model_info(choice_ckpt)293    json_output_msg = config_choice = ""294    choice_ckpt_name, _ = os.path.splitext(choice_ckpt)295    if second_dir_enable:296        all_config = [json for json in os.listdir(second_dir) if json.endswith(".json")]297        for config in all_config:298            config_fname, _ = os.path.splitext(config)299            if config_fname == choice_ckpt_name:300                config_choice = config301                json_output_msg = load_json_encoder(config, choice_ckpt)302        if json_output_msg != "":303            return model_output_msg, config_choice, json_output_msg304        else:305            return model_output_msg, "no_config", ""306    else:307        return model_output_msg, "no_config", ""308    309def auto_load_diff(diff_model):310    global second_dir_enable311    if second_dir_enable is False:312        return "no_diff_config"313    all_diff_config = [yaml for yaml in os.listdir(second_dir) if yaml.endswith(".yaml")]314    for config in all_diff_config:315        config_fname, _ = os.path.splitext(config)316        diff_fname, _ = os.path.splitext(diff_model)317        if config_fname == diff_fname:318            return config319    return "no_diff_config"320        321def load_model_func(ckpt_name,cluster_name,config_name,enhance,diff_model_name,diff_config_name,only_diffusion,use_spk_mix,using_device,method,speedup,cl_num):322    global model323    config_path = os.path.join(config_read_dir, config_name) if not only_diffusion else "configs/config.json"324    diff_config_path = os.path.join(config_read_dir, diff_config_name) if diff_config_name != "no_diff_config" else "configs/diffusion.yaml"325    ckpt_path = os.path.join(ckpt_read_dir, ckpt_name)326    cluster_path = os.path.join(ckpt_read_dir, cluster_name)327    diff_model_path = os.path.join(diff_read_dir, diff_model_name)328    k_step_max = 1000329    if not only_diffusion:330        config = Config(config_path, "json").read()331    if diff_model_name != "no_diff":332        _diff = Config(diff_config_path, "yaml")333        _content = _diff.read()334        diff_spk = _content.get('spk', {})335        diff_spk_choice = spk_choice = next(iter(diff_spk), "未检测到音色")336        if not only_diffusion:337            if _content['data'].get('encoder_out_channels') != config["model"].get('ssl_dim'):338                return "扩散模型维度与主模型不匹配,请确保两个模型使用的是同一个编码器", gr.Dropdown.update(choices=[], value=""), 0, None339        _content["infer"]["speedup"] = int(speedup)340        _content["infer"]["method"] = str(method)341        k_step_max = _content["model"].get('k_step_max', 0) if _content["model"].get('k_step_max', 0) != 0 else 1000342        _diff.save(_content)343    if not only_diffusion:344        net = torch.load(ckpt_path, map_location=torch.device('cpu'))345    #读取模型各维度并比对,还有小可爱无视提示硬要加载底模的就返回个未初始张量346        emb_dim, model_dim = net["model"].get("emb_g.weight", torch.empty(0, 0)).size() 347        if emb_dim > config["model"]["n_speakers"]:348            return "模型说话人数量与emb维度不匹配", gr.Dropdown.update(choices=[], value=""), 0, None349        if model_dim != config["model"]["ssl_dim"]: 350            return "配置文件与模型不匹配", gr.Dropdown.update(choices=[], value=""), 0, None351        encoder = config["model"]["speech_encoder"]352        spk_dict = config.get('spk', {})353        spk_choice = next(iter(spk_dict), "未检测到音色")354    else:355        spk_dict = diff_spk356        spk_choice = diff_spk_choice357    fr = cluster_name.endswith(".pkl") #如果是pkl后缀就启用特征检索358    shallow_diffusion = diff_model_name != "no_diff" #加载了扩散模型就启用浅扩散359    device = cuda[using_device] if "CUDA" in using_device else using_device360    model = Svc(ckpt_path,361                    config_path,362                    device=device if device != "Auto" else None,363                    cluster_model_path=cluster_path,364                    nsf_hifigan_enhance=enhance,365                    diffusion_model_path=diff_model_path,366                    diffusion_config_path=diff_config_path,367                    shallow_diffusion=shallow_diffusion,368                    only_diffusion=only_diffusion,369                    spk_mix_enable=use_spk_mix,370                    feature_retrieval=fr)371    spk_list = list(spk_dict.keys())372    if not only_diffusion:373        clip = 25 if encoder == "whisper-ppg" or encoder == "whisper-ppg-large" else cl_num #Whisper必须强制切片25秒374        device_name = torch.cuda.get_device_properties(model.dev).name if "cuda" in str(model.dev) else str(model.dev)375        sovits_msg = f"模型被成功加载到了{device_name}上\n"376    else: 377        clip = cl_num378        sovits_msg = "启用全扩散推理,未加载So-VITS模型\n"379    index_or_kmeans = "特征索引" if fr else "聚类模型"380    clu_load = "未加载" if cluster_name == "no_clu" else cluster_name381    diff_load = "未加载" if diff_model_name == "no_diff" else f"{diff_model_name} | 采样器: {method} | 加速倍数:{int(speedup)} | 最大浅扩散步数:{k_step_max}"382    output_msg = f"{sovits_msg}{index_or_kmeans}:{clu_load}\n扩散模型:{diff_load}"383    return (384        output_msg, 385        gr.Dropdown.update(choices=spk_list, value=spk_choice), 386        clip, 387        gr.Slider.update(value=100 if k_step_max>100 else k_step_max, minimum=speedup, maximum=k_step_max)388    )389 390def model_empty_cache():391    global model392    if model is None:393        return sid.update(choices = [],value=""),"没有模型需要卸载!"394    else:395        model.unload_model()396        model = None397        torch.cuda.empty_cache()398        return sid.update(choices = [],value=""),"模型卸载完毕!"399 400def get_file_options(directory, extension):401    return [file for file in os.listdir(directory) if file.endswith(extension)]402 403def load_options():404    ckpt_list = [file for file in get_file_options(ckpt_read_dir, ".pth") if not file.startswith("D_") or file == "G_0.pth"]405    config_list = get_file_options(config_read_dir, ".json")406    cluster_list = ["no_clu"] + get_file_options(ckpt_read_dir, ".pt") + get_file_options(ckpt_read_dir, ".pkl") # 聚类和特征检索模型407    diff_list = ["no_diff"] + get_file_options(diff_read_dir, ".pt")408    diff_config_list = ["no_diff_config"] + get_file_options(config_read_dir, ".yaml")409    return ckpt_list, config_list, cluster_list, diff_list, diff_config_list410 411def refresh_options():412    global ckpt_read_dir, config_read_dir, diff_read_dir, current_mode413    ckpt_read_dir = second_dir if second_dir_enable else workdir414    config_read_dir = second_dir if second_dir_enable else config_dir415    diff_read_dir = diff_second_dir if second_dir_enable else diff_workdir416    ckpt_list, config_list, cluster_list, diff_list, diff_config_list = load_options()417    current_mode = get_current_mode()418    return (419        choice_ckpt.update(choices=ckpt_list),420        config_choice.update(choices=config_list),421        cluster_choice.update(choices=cluster_list),422        diff_choice.update(choices=diff_list),423        diff_config_choice.update(choices=diff_config_list),424        mode_caption.update(value=f"""{current_mode},可在页面底端切换模式""")425    )426 427def source_change(use_microphone):428    if use_microphone:429        return vc_input3.update(source="microphone")430    else:431        return vc_input3.update(source="upload")432 433def vc_infer(output_format, sid, input_audio, sr, input_audio_path, vc_transform, auto_f0, cluster_ratio, slice_db, noise_scale, pad_seconds, cl_num, lg_num, lgr_num, f0_predictor, enhancer_adaptive_key, cr_threshold, k_step, use_spk_mix, second_encoding, loudness_envelope_adjustment):434    if np.issubdtype(input_audio.dtype, np.integer):435        input_audio = (input_audio / np.iinfo(input_audio.dtype).max).astype(np.float32)436    if len(input_audio.shape) > 1:437        input_audio = librosa.to_mono(input_audio.transpose(1, 0))438    if sr != 44100:439        input_audio = librosa.resample(input_audio, orig_sr=sr, target_sr=44100)440    sf.write("temp.wav", input_audio, 44100, format="wav")441    _audio = model.slice_inference(442        "temp.wav",443        sid,444        vc_transform,445        slice_db,446        cluster_ratio,447        auto_f0,448        noise_scale,449        pad_seconds,450        cl_num,451        lg_num,452        lgr_num,453        f0_predictor,454        enhancer_adaptive_key,455        cr_threshold,456        k_step,457        use_spk_mix,458        second_encoding,459        loudness_envelope_adjustment460    )  461    model.clear_empty()462    if not os.path.exists("results"):463        os.makedirs("results")464    key = "auto" if auto_f0 else f"{int(vc_transform)}key"465    cluster = "_" if cluster_ratio == 0 else f"_{cluster_ratio}_"466    isdiffusion = "sovits_"467    if model.shallow_diffusion:468        isdiffusion = "sovdiff_"469    if model.only_diffusion:470        isdiffusion = "diff_"471    #Gradio上传的filepath因为未知原因会有一个无意义的固定后缀,这里去掉472    truncated_basename = Path(input_audio_path).stem[:-6] if Path(input_audio_path).stem[-6:] == "-0-100" else Path(input_audio_path).stem473    output_file_name = f'{truncated_basename}_{sid}_{key}{cluster}{isdiffusion}{f0_predictor}.{output_format}'474    output_file_path = os.path.join("results", output_file_name)475    if os.path.exists(output_file_path):476        count = 1477        while os.path.exists(output_file_path):478            output_file_name = f'{truncated_basename}_{sid}_{key}{cluster}{isdiffusion}{f0_predictor}_{str(count)}.{output_format}'479            output_file_path = os.path.join("results", output_file_name)480            count += 1  481    sf.write(output_file_path, _audio, model.target_sample, format=output_format)482    return output_file_path483 484def vc_fn(output_format, sid, input_audio, vc_transform, auto_f0, cluster_ratio, slice_db, noise_scale, pad_seconds, cl_num, lg_num, lgr_num, f0_predictor, enhancer_adaptive_key, cr_threshold, k_step, use_spk_mix, second_encoding, loudness_envelope_adjustment, progress=gr.Progress(track_tqdm=True)):485    global model486    try:487        if input_audio is None:488            return "你还没有上传音频", None489        if model is None:490            return "你还没有加载模型", None491        if getattr(model, 'cluster_model', None) is None and model.feature_retrieval is False:492            if cluster_ratio != 0:493                return "你还未加载聚类或特征检索模型,无法启用聚类/特征检索混合比例", None494        audio, sr = sf.read(input_audio)495        output_file_path = vc_infer(output_format, sid, audio, sr, input_audio, vc_transform, auto_f0, cluster_ratio, slice_db, noise_scale, pad_seconds, cl_num, lg_num, lgr_num, f0_predictor, enhancer_adaptive_key, cr_threshold, k_step, use_spk_mix, second_encoding, loudness_envelope_adjustment)496        os.remove("temp.wav")497        return "Success", output_file_path498    except Exception as e:499        if debug:500            traceback.print_exc()501        raise gr.Error(e)502 503def vc_batch_fn(output_format, sid, input_audio_files, vc_transform, auto_f0, cluster_ratio, slice_db, noise_scale, pad_seconds, cl_num, lg_num, lgr_num, f0_predictor, enhancer_adaptive_key, cr_threshold, k_step, use_spk_mix, second_encoding, loudness_envelope_adjustment, progress=gr.Progress()):504    global model505    try:506        if input_audio_files is None or len(input_audio_files) == 0:507            return "你还没有上传音频"508        if model is None:509            return "你还没有加载模型"510        if getattr(model, 'cluster_model', None) is None and model.feature_retrieval is False:511            if cluster_ratio != 0:512                return "你还未加载聚类或特征检索模型,无法启用聚类/特征检索混合比例", None513        _output = []514        for file_obj in progress.tqdm(input_audio_files, desc="Inferencing"):515            print(f"Start processing: {file_obj.name}")516            input_audio_path = file_obj.name517            audio, sr = sf.read(input_audio_path)518            output_file_path = vc_infer(output_format, sid, audio, sr, input_audio_path, vc_transform, auto_f0, cluster_ratio, slice_db, noise_scale, pad_seconds, cl_num, lg_num, lgr_num, f0_predictor, enhancer_adaptive_key, cr_threshold, k_step, use_spk_mix, second_encoding, loudness_envelope_adjustment)519            _output.append(output_file_path)520        return "批量推理完成,音频已经被保存到results文件夹"521    except Exception as e:522        if debug:523            traceback.print_exc()524        raise gr.Error(e)525    526def tts_fn(_text, _gender, _lang, _rate, _volume, output_format, sid, vc_transform, auto_f0,cluster_ratio, slice_db, noise_scale,pad_seconds,cl_num,lg_num,lgr_num,f0_predictor,enhancer_adaptive_key,cr_threshold, k_step,use_spk_mix,second_encoding,loudness_envelope_adjustment,progress=gr.Progress(track_tqdm=True)):527    global model528    try:529        if model is None:530            return "你还没有加载模型", None531        if getattr(model, 'cluster_model', None) is None and model.feature_retrieval is False:532            if cluster_ratio != 0:533                return "你还未加载聚类或特征检索模型,无法启用聚类/特征检索混合比例", None534        _rate = f"+{int(_rate*100)}%" if _rate >= 0 else f"{int(_rate*100)}%"535        _volume = f"+{int(_volume*100)}%" if _volume >= 0 else f"{int(_volume*100)}%"536        if _lang == "Auto":537            _gender = "Male" if _gender == "男" else "Female"538            subprocess.run([r".\workenv\python.exe", "tts.py", _text, _lang, _rate, _volume, _gender])539        else:540            subprocess.run([r".\workenv\python.exe", "tts.py", _text, _lang, _rate, _volume])541        target_sr = 44100542        y, sr = librosa.load("tts.wav")543        resampled_y = librosa.resample(y, orig_sr=sr, target_sr=target_sr)544        sf.write("tts.wav", resampled_y, target_sr, subtype = "PCM_16")545        input_audio = "tts.wav"546        audio, sr = sf.read(input_audio)547        output_file_path = vc_infer(output_format, sid, audio, sr, input_audio, vc_transform, auto_f0, cluster_ratio, slice_db, noise_scale, pad_seconds, cl_num, lg_num, lgr_num, f0_predictor, enhancer_adaptive_key, cr_threshold, k_step, use_spk_mix, second_encoding, loudness_envelope_adjustment)548        #os.remove("tts.wav")549        return "Success", output_file_path550    except Exception as e:551        if debug:552            traceback.print_exc()553        raise gr.Error(e)554 555def load_raw_dirs():556    global precheck_ok557    precheck_ok = False558    allowed_pattern = re.compile(r'^[a-zA-Z0-9_@#$%^&()_+\-=\s\.]*$')559    illegal_files = illegal_dataset = []560    for root, dirs, files in os.walk(raw_path):561        for dir in dirs:562            if not allowed_pattern.match(dir):563                illegal_dataset.append(dir)564        if illegal_dataset:565            return f"数据集文件夹名只能包含数字、字母、下划线,以下文件夹不符合要求,请改名后再试:\n{illegal_dataset}"566        if root != raw_path:  # 只处理子文件夹内的文件567            for file in files:568                if not allowed_pattern.match(file) and file not in illegal_files:569                    illegal_files.append(file)570                if not file.lower().endswith('.wav') and file not in illegal_files:571                    illegal_files.append(file)572    if illegal_files:573        return f"数据集文件名只能包含数字、字母、下划线,且必须是.wav格式,以下文件不符合要求,请改名后再试:\n{illegal_files}"574    spk_dirs = [entry.name for entry in os.scandir(raw_path) if entry.is_dir()]575    if spk_dirs:576        precheck_ok = True577        return spk_dirs578    else:579        return "未找到数据集,请检查dataset_raw文件夹"580    581def dataset_preprocess(encoder, f0_predictor, use_diff, vol_aug, skip_loudnorm, num_processes, tiny_enable):582    if precheck_ok:583        diff_arg = "--use_diff" if use_diff else ""584        vol_aug_arg = "--vol_aug" if vol_aug else ""585        skip_loudnorm_arg = "--skip_loudnorm" if skip_loudnorm else ""586        tiny_arg = "--tiny" if tiny_enable else ""587        preprocess_commands = [588            r".\workenv\python.exe resample.py %s" % (skip_loudnorm_arg),589            r".\workenv\python.exe preprocess_flist_config.py --speech_encoder %s %s %s" % (encoder, vol_aug_arg, tiny_arg),590            r".\workenv\python.exe preprocess_hubert_f0.py --num_processes %s --f0_predictor %s %s" % (num_processes ,f0_predictor, diff_arg)591            ]592        accumulated_output = ""593        #清空dataset594        dataset = os.listdir(dataset_dir)595        if len(dataset) != 0:596            for dir in dataset:597                dataset_spk_dir = os.path.join(dataset_dir, str(dir))598                if os.path.isdir(dataset_spk_dir):599                    shutil.rmtree(dataset_spk_dir)600                    accumulated_output += f"Deleting previous dataset: {dir}\n"601        for command in preprocess_commands:602            try:603                result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, text=True)604                accumulated_output += f"Command: {command}, Using Encoder: {encoder}, Using f0 Predictor: {f0_predictor}\n"605                yield accumulated_output, None606                progress_line = None607                for line in result.stdout:608                    if r"it/s" in line or r"s/it" in line: #防止进度条刷屏609                        progress_line = line610                    else:611                        accumulated_output += line612                    if progress_line is None:613                        yield accumulated_output, None614                    else:615                        yield accumulated_output + progress_line, None616                result.communicate()617            except subprocess.CalledProcessError as e:618                result = e.output619                accumulated_output += f"Error: {result}\n"620                yield accumulated_output, None621            if progress_line is not None:622                accumulated_output += progress_line623            accumulated_output += '-' * 50 + '\n'624            yield accumulated_output, None625            config_path = "configs/config.json"626        with open(config_path, 'r') as f:627            config = json.load(f)628        spk_name = config.get('spk', None)629        yield accumulated_output, gr.Textbox.update(value=spk_name)630    else:631        yield "数据集识别未通过,请先识别数据集并确保没有报错信息", None632 633def regenerate_config(encoder, vol_aug, tiny_enable):634    if precheck_ok is False:635        return "数据集识别未通过,请检查识别结果的报错信息"636    vol_aug_arg = "--vol_aug" if vol_aug else ""637    tiny_arg = "--tiny" if tiny_enable else ""638    cmd = r".\workenv\python.exe preprocess_flist_config.py --speech_encoder %s %s %s" % (encoder, vol_aug_arg, tiny_arg)639    output = ""640    try:641        result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, text=True)642        for line in result.stdout:643            output += line644        output += "Regenerate config file successfully."645    except subprocess.CalledProcessError as e:646        result = e.output647        output += f"Error: {result}\n"648    return output649 650def clear_output():651    return gr.Textbox.update(value="Cleared!>_<")652 653def get_available_encoder():654    current_pretrain = os.listdir("pretrain")655    current_pretrain = [("pretrain/" + model) for model in current_pretrain]656    encoder_list = []657    for encoder, path in ENCODER_PRETRAIN.items():658        if path in current_pretrain:659            encoder_list.append(encoder)660    return encoder_list661 662def config_fn(log_interval, eval_interval, keep_ckpts, batch_size, lr, amp_dtype, all_in_mem, diff_num_workers, diff_cache_all_data, diff_batch_size, diff_lr, diff_interval_log, diff_interval_val, diff_cache_device, diff_amp_dtype, diff_force_save, diff_k_step_max):663    if amp_dtype == "fp16" or amp_dtype == "bf16":664        fp16_run = True665    else:666        fp16_run = False667        amp_dtype = "fp16"668    config_origin = Config("configs/config.json", "json")669    diff_config = Config("configs/diffusion.yaml", "yaml")670    config_data = config_origin.read()671    config_data['train']['log_interval'] = int(log_interval)672    config_data['train']['eval_interval'] = int(eval_interval)673    config_data['train']['keep_ckpts'] = int(keep_ckpts)674    config_data['train']['batch_size'] = int(batch_size)675    config_data['train']['learning_rate'] = float(lr)676    config_data['train']['fp16_run'] = fp16_run677    config_data['train']['half_type'] = str(amp_dtype)678    config_data['train']['all_in_mem'] = all_in_mem679    config_origin.save(config_data)680    diff_config_data = diff_config.read()681    diff_config_data['train']['num_workers'] = int(diff_num_workers)682    diff_config_data['train']['cache_all_data'] = diff_cache_all_data683    diff_config_data['train']['batch_size'] = int(diff_batch_size)684    diff_config_data['train']['lr'] = float(diff_lr)685    diff_config_data['train']['interval_log'] = int(diff_interval_log)686    diff_config_data['train']['interval_val'] = int(diff_interval_val)687    diff_config_data['train']['cache_device'] = str(diff_cache_device)688    diff_config_data['train']['amp_dtype'] = str(diff_amp_dtype)689    diff_config_data['train']['interval_force_save'] = int(diff_force_save)690    diff_config_data['model']['k_step_max'] = 100 if diff_k_step_max else 0691    diff_config.save(diff_config_data)692    return "配置文件写入完成"693 694def check_dataset(dataset_path):695    if not os.listdir(dataset_path):696        return "数据集不存在,请检查dataset文件夹"697    no_npy_pt_files = True698    for root, dirs, files in os.walk(dataset_path):699        for file in files:700            if file.endswith('.npy') or file.endswith('.pt'):701                no_npy_pt_files = False702                break703    if no_npy_pt_files:704        return "数据集中未检测到f0和hubert文件,可能是预处理未完成"705    return None706 707def training(gpu_selection, encoder, tiny_enable):708    if tiny_enable:709        encoder = "vec768l12_tiny"710    config_file = Config("configs/config.json", "json")711    config_data = config_file.read()712    vol_emb = config_data["model"]["vol_embedding"]713    dataset_warn = check_dataset(dataset_dir)714    if dataset_warn is not None:715        return dataset_warn716    PRETRAIN = { 717        "vec256l9": ("D_0.pth", "G_0.pth", "pre_trained_model"),718        "vec768l12": ("D_0.pth", "G_0.pth", "pre_trained_model/768l12/vol_emb" if vol_emb else "pre_trained_model/768l12"),719        "vec768l12_tiny": ("D_0.pth", "G_0.pth", "pre_trained_model/tiny/vec768l12_vol_emb"),720        "hubertsoft": ("D_0.pth", "G_0.pth", "pre_trained_model/hubertsoft"),721        "whisper-ppg": ("D_0.pth", "G_0.pth", "pre_trained_model/whisper-ppg"),722        "cnhubertlarge": ("D_0.pth", "G_0.pth", "pre_trained_model/cnhubertlarge"),723        "dphubert": ("D_0.pth", "G_0.pth", "pre_trained_model/dphubert"),724        "wavlmbase+": ("D_0.pth", "G_0.pth", "pre_trained_model/wavlmbase+"),725        "whisper-ppg-large": ("D_0.pth", "G_0.pth", "pre_trained_model/whisper-ppg-large")726    }727    if encoder not in PRETRAIN:728        return "未知编码器"729    d_0_file, g_0_file, encoder_model_path = PRETRAIN[encoder]730    d_0_path = os.path.join(encoder_model_path, d_0_file)731    g_0_path = os.path.join(encoder_model_path, g_0_file)732    timestamp = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M')733    new_backup_folder = os.path.join(models_backup_path, str(timestamp))734    output_msg = ""735    if os.listdir(workdir) != ['diffusion']:736        os.makedirs(new_backup_folder, exist_ok=True)737        for file in os.listdir(workdir):738            if file != "diffusion":739                shutil.move(os.path.join(workdir, file), os.path.join(new_backup_folder, file))740    if os.path.isfile(g_0_path) and os.path.isfile(d_0_path):741        shutil.copy(d_0_path, os.path.join(workdir, "D_0.pth"))742        shutil.copy(g_0_path, os.path.join(workdir, "G_0.pth"))743        output_msg += f"成功装载预训练模型,编码器:{encoder}\n"744    else:745        output_msg += f"{encoder}的预训练模型不存在,未装载预训练模型\n"746 747    cmd = r"set CUDA_VISIBLE_DEVICES=%s && .\workenv\python.exe train.py -c configs/config.json -m 44k" % (gpu_selection)748    subprocess.Popen(["cmd", "/c", "start", "cmd", "/k", cmd])749    output_msg += "已经在新的终端窗口开始训练,请监看终端窗口的训练日志。在终端中按Ctrl+C可暂停训练。"750    return output_msg751 752def continue_training(gpu_selection, encoder):753    dataset_warn = check_dataset(dataset_dir)754    if dataset_warn is not None:755        return dataset_warn756    if encoder == "":757        return "请先选择预处理对应的编码器"758    all_files = os.listdir(workdir)759    model_files = [f for f in all_files if f.startswith('G_') and f.endswith('.pth')]760    if len(model_files) == 0:761        return "你还没有已开始的训练"762    cmd = r"set CUDA_VISIBLE_DEVICES=%s && .\workenv\python.exe train.py -c configs/config.json -m 44k" % (gpu_selection)763    subprocess.Popen(["cmd", "/c", "start", "cmd", "/k", cmd])764    return "已经在新的终端窗口开始训练,请监看终端窗口的训练日志。在终端中按Ctrl+C可暂停训练。"765 766def kmeans_training(kmeans_gpu):767    if not os.listdir(dataset_dir):768        return "数据集不存在,请检查dataset文件夹"769    cmd = r".\workenv\python.exe cluster/train_cluster.py --gpu" if kmeans_gpu else r".\workenv\python.exe cluster/train_cluster.py"770    subprocess.Popen(["cmd", "/c", "start", "cmd", "/k", cmd])771    return "已经在新的终端窗口开始训练,训练聚类模型不会输出日志,CPU训练一般需要5-10分钟左右"772 773def index_training():774    if not os.listdir(dataset_dir):775        return "数据集不存在,请检查dataset文件夹"776    cmd = r".\workenv\python.exe train_index.py -c configs/config.json"777    subprocess.Popen(["cmd", "/c", "start", "cmd", "/k", cmd])778    return "已经在新的终端窗口开始训练"779 780def diff_training(encoder, k_step_max):781    if not os.listdir(dataset_dir):782        return "数据集不存在,请检查dataset文件夹"783    timestamp = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M')784    new_backup_folder = os.path.join(models_backup_path, "diffusion", str(timestamp))785    if len(os.listdir(diff_workdir)) != 0:786        os.makedirs(new_backup_folder, exist_ok=True)787        for file in os.listdir(diff_workdir):788            shutil.move(os.path.join(diff_workdir, file), os.path.join(new_backup_folder, file))789    DIFF_PRETRAIN = {790        "768-kstepmax100": "pre_trained_model/diffusion/768l12/max100/model_0.pt",791        "vec768l12": "pre_trained_model/diffusion/768l12/model_0.pt",792        "hubertsoft": "pre_trained_model/diffusion/hubertsoft/model_0.pt",793        "whisper-ppg": "pre_trained_model/diffusion/whisper-ppg/model_0.pt"794    }795    if encoder not in DIFF_PRETRAIN:796        return "你所选的编码器暂时不支持训练扩散模型"797    if k_step_max:798        encoder = "768-kstepmax100"799    diff_pretrained_model = DIFF_PRETRAIN[encoder]800    shutil.copy(diff_pretrained_model, os.path.join(diff_workdir, "model_0.pt"))801    subprocess.Popen(["cmd", "/c", "start", "cmd", "/k", r".\workenv\python.exe train_diff.py -c configs/diffusion.yaml"])802    output_message = "已经在新的终端窗口开始训练,请监看终端窗口的训练日志。在终端中按Ctrl+C可暂停训练。"803    if encoder == "768-kstepmax100":804        output_message += "\n正在进行100步深度的浅扩散训练,已加载底模"805    else:806        output_message += f"\n正在进行完整深度的扩散训练,编码器{encoder}"807    return output_message808 809def diff_continue_training(encoder):810    if not os.listdir(dataset_dir):811        return "数据集不存在,请检查dataset文件夹"812    if encoder == "":813        return "请先选择预处理对应的编码器"814    all_files = os.listdir(diff_workdir)815    model_files = [f for f in all_files if f.endswith('.pt')]816    if len(model_files) == 0:817        return "你还没有已开始的训练"818    subprocess.Popen(["cmd", "/c", "start", "cmd", "/k", r".\workenv\python.exe train_diff.py -c configs/diffusion.yaml"])819    return "已经在新的终端窗口开始训练,请监看终端窗口的训练日志。在终端中按Ctrl+C可暂停训练。"820 821def upload_mix_append_file(files,sfiles):822    try:823        if(sfiles is None):824            file_paths = [file.name for file in files]825        else:826            file_paths = [file.name for file in chain(files,sfiles)]827        p = {file:100 for file in file_paths}828        return file_paths,mix_model_output1.update(value=json.dumps(p,indent=2))829    except Exception as e:830        if debug:831            traceback.print_exc()832        raise gr.Error(e)833 834def mix_submit_click(js,mode):835    try:836        assert js.lstrip()!=""837        modes = {"凸组合":0, "线性组合":1}838        mode = modes[mode]839        data = json.loads(js)840        data = list(data.items())841        model_path,mix_rate = zip(*data)842        path = mix_model(model_path,mix_rate,mode)843        return f"成功,文件被保存在了{path}"844    except Exception as e:845        if debug:846            traceback.print_exc()847        raise gr.Error(e)848 849def updata_mix_info(files):850    try:851        if files is None:852            return mix_model_output1.update(value="")853        p = {file.name:100 for file in files}854        return mix_model_output1.update(value=json.dumps(p,indent=2))855    except Exception as e:856        if debug:857            traceback.print_exc()858        raise gr.Error(e)859 860def pth_identify():861    if not os.path.exists(root_dir):862        return f"未找到{root_dir}文件夹,请先创建一个{root_dir}文件夹并按第一步流程操作"863    model_dirs = [d for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))]864    if not model_dirs:865        return f"未在{root_dir}文件夹中找到模型文件夹,请确保每个模型和配置文件都被放置在单独的文件夹中"866    valid_model_dirs = []867    for path in model_dirs:868        pth_files = glob.glob(f"{root_dir}/{path}/*.pth")869        json_files = glob.glob(f"{root_dir}/{path}/*.json")870        if len(pth_files) != 1 or len(json_files) != 1:871            return f"错误: 在{root_dir}/{path}中找到了{len(pth_files)}个.pth文件和{len(json_files)}个.json文件。应当确保每个文件夹内有且只有一个.pth文件和.json文件"872        valid_model_dirs.append(path)873        874    return f"成功识别了{len(valid_model_dirs)}个模型:{valid_model_dirs}"875 876def onnx_export_func():877    model_dirs = [d for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))]878    output_msg = ""879    try:880        for path in model_dirs:881            pth_files = glob.glob(f"{root_dir}/{path}/*.pth")882            json_files = glob.glob(f"{root_dir}/{path}/*.json")883            model_file = Path(pth_files[0]).name884            json_file = Path(json_files[0]).name885            try:886                onnx_export(path, json_file, model_file)887                output_msg += f"成功转换{path}\n"888            except Exception as e:889                output_msg += f"转换{path}时出现错误: {e}\n"890        return output_msg891    except Exception as e:892        if debug:893            traceback.print_exc()894        raise gr.Error(e)895 896def load_raw_audio(audio_path):897    if not os.path.isdir(audio_path):898        return "请输入正确的目录", None899    files = os.listdir(audio_path)900    wav_files = [file for file in files if file.lower().endswith('.wav')]901    if not wav_files:902        return "未在目录中找到.wav音频文件", None903    return "成功加载", wav_files904 905def slicer_fn(input_dir, output_dir, process_method, max_sec, min_sec):906    if output_dir == "":907        return "请先选择输出的文件夹"908    if output_dir == input_dir:909        return "输出目录不能和输入目录相同"910    slicer = AutoSlicer()911    if os.path.exists(output_dir) is not True:912        os.makedirs(output_dir)913    for filename in os.listdir(input_dir):914        if filename.lower().endswith(".wav"):915            slicer.auto_slice(filename, input_dir, output_dir, max_sec)916    if process_method == "丢弃":917        for filename in os.listdir(output_dir):918            if filename.endswith(".wav"):919                filepath = os.path.join(output_dir, filename)920                audio, sr = librosa.load(filepath, sr=None, mono=False)921                if librosa.get_duration(y=audio, sr=sr) < min_sec:922                    os.remove(filepath)923    elif process_method == "将过短音频整合为长音频":924        slicer.merge_short(output_dir, max_sec, min_sec)925    file_count, max_duration, min_duration, orig_duration, final_duration = slicer.slice_count(input_dir, output_dir)926    hrs = int(final_duration / 3600)927    mins = int((final_duration % 3600) / 60)928    sec = format(float(final_duration % 60), '.2f')929    rate = format(100 * (final_duration / orig_duration), '.2f') if orig_duration != 0 else 0930    rate_msg = f"为原始音频时长的{rate}%" if rate != 0 else "因未知问题,无法计算切片时长的占比"931    return f"成功将音频切分为{file_count}条片段,其中最长{max_duration}秒,最短{min_duration}秒,切片后的音频总时长{hrs:02d}小时{mins:02d}分{sec}秒,{rate_msg}"932 933def model_compression(_model, is_fp16):934    if _model == "":935        return "请先选择要压缩的模型"936    else:937        model_path = os.path.join(ckpt_read_dir, _model)938        filename, extension = os.path.splitext(_model)939        output_model_name = f"{filename}_compressed{extension}"940        output_path = os.path.join(ckpt_read_dir, output_model_name)941        removeOptimizer("configs/config.json", model_path, is_fp16, output_path)942        return f"模型已成功被保存在了{output_path}"943    944def pack_autoload(model_to_pack):945    _, config_name, _ = auto_load(model_to_pack)946    if config_name == "no_config":947        return "未找到对应的配置文件,请手动选择", None948    else:949        _config = Config(os.path.join(config_read_dir, config_name), "json")950        _content = _config.read()951        spk_dict = _content["spk"]952        spk_list = ",".join(spk_dict.keys())953        return config_name, spk_list954    955def release_packing(model_to_pack, model_config, speaker, diff_to_pack, cluster_to_pack):956    model_path = diff_path = cluster_path = ""957    basename = os.path.splitext(model_to_pack)[0]958    diff_basename = os.path.splitext(diff_to_pack)[0]959    if model_to_pack == "" or model_config == "" or speaker == "":960        return "存在必选项为空,请检查后重试"961    released_pack = ReleasePacker(speaker, model_to_pack)962    released_pack.remove_temp("release_packs")963    model_path = os.path.join(ckpt_read_dir, model_to_pack)964    config_path = os.path.join(config_read_dir, model_config)965    if os.stat(model_path).st_size > 300000000:966        removeOptimizer(config_path, model_path, False, os.path.join("release_packs", model_to_pack))967        model_path = os.path.join("release_packs", model_to_pack)968    if diff_to_pack != "no_diff":969        diff_path = os.path.join(diff_read_dir, diff_to_pack)970    if cluster_to_pack != "no_cluster":971        cluster_path = os.path.join(ckpt_read_dir, cluster_to_pack)972    shutil.copyfile("configs_template/config_template.json", "release_packs/config_template.json")973    shutil.copyfile("configs_template/diffusion_template.yaml", "release_packs/diffusion_template.yaml")974    files_to_pack = [975        (model_path, f"models/{model_to_pack}"),976        (diff_path, f"models/diffusion/{diff_to_pack}") if diff_to_pack != "no_diff" else ("", ""),977        (cluster_path, f"models/{cluster_to_pack}") if cluster_to_pack != "no_cluster" else ("", ""),978        (f"release_packs/{basename}.json", f"models/{basename}.json"),979        (f"release_packs/{diff_basename}.yaml", f"models/{diff_basename}.yaml") if diff_to_pack != "no_diff" else ("", ""),980        ("release_packs/install.txt", "install.txt")981    ]982    released_pack.add_file(files_to_pack)983    released_pack.generate_config(diff_to_pack, model_config)984    os.rename("release_packs/config_template.json", f"release_packs/{basename}.json")985    os.rename("release_packs/diffusion_template.yaml", f"release_packs/{diff_basename}.yaml")986    released_pack.pack()987    to_remove = [file for file in os.listdir("release_packs") if not file.endswith(".zip")]988    for file in to_remove:989        os.remove(os.path.join("release_packs", file))990    return "打包成功, 请在release_packs目录下查看"991 992def release_install(model_zip_path):993    model_zip = ReleasePacker("", "")994    model_zip.unpack(model_zip_path)995    for file in os.listdir("release_packs"):996        if file.endswith(".txt"):997            install_txt = os.path.join("release_packs", file)998            break999    else:1000        model_zip.remove_temp("release_packs")1001        return "非格式化安装包,无法安装"1002    _spk = model_zip.formatted_install(install_txt)1003    model_zip.remove_temp("release_packs")1004    return f"安装成功,可用说话人{_spk},请启用独立目录模式加载模型"1005 1006def sami_inference(ac_key, s_key, app_key, audio_path, model, use_proxy, port):1007    if ac_key == "" or s_key == "" or app_key == "":1008        return None, "密钥和APP_KEY不能为空"1009    1010    if use_proxy:1011        os.environ['HTTP_PROXY'] = f"http://127.0.0.1:{int(port)}/"1012    1013    sami_service = SAMIService()1014 1015    sami_service.set_ak(ac_key)1016    sami_service.set_sk(s_key)1017 1018    auth_req = {"appkey": app_key, "token_version": 'volc-auth-v1', "expiration": 3600}1019    auth_resp = sami_service.common_json_handler("GetToken", auth_req)1020 1021    try:1022        auth_token = auth_resp["token"]1023    except KeyError as e:1024        if debug:1025            traceback.print_exc()1026        raise gr.Error(e)1027    1028    payload = json.dumps({"model": model})1029    with open(audio_path, "rb") as f:1030        data = f.read()1031        data = base64.b64encode(data).decode('utf-8')1032 1033    req = {1034        "appkey": app_key,1035        "token": auth_token,1036        "namespace": "MusicSourceSeparate",1037        "payload": payload,1038        "data": data1039    }1040 1041    resp = requests.post("https://sami.bytedance.com/api/v1/invoke", json=req)1042 1043    try:1044        sami_resp = resp.json()1045        if resp.status_code != 200:1046            print(sami_resp)1047            sys.exit(1)1048    except Exception as e:1049        if debug:1050            traceback.print_exc()1051        raise gr.Error(e)1052    1053    print("response task_id=%s status_code=%d status_text=%s" % (1054        sami_resp["task_id"], sami_resp["status_code"], sami_resp["status_text"]), end=" ")1055    if "payload" in sami_resp and len(sami_resp["payload"]) > 0:1056        print("payload=%s" % sami_resp["payload"], end=" ")1057    if "data" in sami_resp and len(sami_resp["data"]) > 0:1058        # Save audio data into file1059        data = base64.b64decode(sami_resp["data"])1060        print("data=[%d]bytes" % len(data))1061        with open("output.wav", "wb") as f:1062            f.write(data)1063 1064    if use_proxy:1065        os.environ.pop('HTTP_PROXY')1066 1067    if os.path.isfile("output.wav"):1068        return "output.wav", "Success"1069    else:1070        return None, "出错了"1071    1072 1073#read default params1074sovits_params, diff_params, second_dir_enable = get_default_settings()1075ckpt_read_dir = second_dir if second_dir_enable else workdir1076config_read_dir = second_dir if second_dir_enable else config_dir1077diff_read_dir = diff_second_dir if second_dir_enable else diff_workdir1078current_mode = get_current_mode()1079 1080# create dirs if they don't exist1081dirs_to_check = [1082    workdir,1083    second_dir,1084    diff_workdir,1085    diff_second_dir,1086    dataset_dir,1087]1088for dir in dirs_to_check:1089    if not os.path.exists(dir):1090        os.makedirs(dir)1091 1092# read ckpt list1093ckpt_list, config_list, cluster_list, diff_list, diff_config_list = load_options()1094 1095# read available encoder list1096encoder_list = get_available_encoder()1097 1098#read GPU info1099ngpu=torch.cuda.device_count()1100gpu_infos=[]1101if(torch.cuda.is_available() is False or ngpu==0):1102    if_gpu_ok=False1103else:1104    if_gpu_ok = False1105    for i in range(ngpu):1106        gpu_name=torch.cuda.get_device_name(i)1107        if("MX"in gpu_name):1108            continue1109        if("RTX" in gpu_name.upper() or "10"in gpu_name or "16"in gpu_name or "20"in gpu_name or "30"in gpu_name or "40"in gpu_name or "A50"in gpu_name.upper() or "70"in gpu_name or "80"in gpu_name or "90"in gpu_name or "M4"in gpu_name or"P4"in gpu_name or "T4"in gpu_name or "TITAN"in gpu_name.upper()):#A10#A100#V100#A40#P40#M40#K801110            if_gpu_ok=True#至少有一张能用的N卡1111            gpu_infos.append("%s\t%s"%(i,gpu_name))1112gpu_info="\n".join(gpu_infos)if if_gpu_ok is True and len(gpu_infos)>0 else "很遗憾您这没有能用的显卡来支持您训练"1113gpus="-".join([i[0]for i in gpu_infos])1114 1115#read cuda info for inference1116cuda = {}1117min_vram = 01118if torch.cuda.is_available():1119    for i in range(torch.cuda.device_count()):1120        current_vram = torch.cuda.get_device_properties(i).total_memory1121        min_vram = current_vram if current_vram > min_vram else min_vram1122        device_name = torch.cuda.get_device_properties(i).name1123        cuda[f"CUDA:{i} {device_name}"] = f"cuda:{i}"1124total_vram = round(min_vram * 9.31322575e-10) if min_vram != 0 else 01125auto_batch = total_vram - 2 if total_vram <= 12 and total_vram > 0 else total_vram1126print(f"Current vram: {total_vram} GiB, recommended batch size: {auto_batch}")1127 1128#Check BF16 support1129amp_options = ["fp32", "fp16"]1130if if_gpu_ok:1131    if torch.cuda.is_bf16_supported():1132        amp_options = ["fp32", "fp16", "bf16"] 1133 1134#Get F0 Options1135f0_options = ["crepe","pm","dio","harvest","rmvpe","fcpe"]1136 1137app = gr.Blocks()1138with app:1139    gr.Markdown(value="""1140        ### So-VITS-SVC 4.1-Stable WebUI 推理&训练 v2.3.141141                1142        制作协力:bilibili@麦哲云1143 1144        仅供个人娱乐和非商业用途,禁止用于血腥、暴力、性相关、政治相关内容1145 1146        [使用文档和常见报错解答](https://www.yuque.com/umoubuton/ueupp5)1147 1148        整合包作者:bilibili@羽毛布団 | 技术交流群:742817595 | 交流二群:168254971 | 交流三群:416656175 | 交流四群:9035166071149 1150        """)1151    with gr.Tabs():1152        with gr.TabItem("推理") as inference_tab:1153            mode_caption = gr.Markdown(value=f"""1154                {current_mode},可在页面底端切换模式1155            """)1156            with gr.Row():1157                choice_ckpt = gr.Dropdown(label="模型选择", choices=ckpt_list, value="no_model")1158                model_branch = gr.Textbox(label="模型编码器", placeholder="请先选择模型", interactive=False)1159            with gr.Row():1160                config_choice = gr.Dropdown(label="配置文件", choices=config_list, value="no_config")1161                config_info = gr.Textbox(label="配置文件编码器", placeholder="请选择配置文件")1162            gr.Markdown(value="""**请检查模型和配置文件的编码器是否匹配**""")1163            with gr.Row():1164                diff_choice = gr.Dropdown(label="(可选)选择扩散模型", choices=diff_list, value="no_diff", interactive=True)1165                diff_config_choice = gr.Dropdown(label="扩散模型配置文件", choices=diff_config_list, value="no_diff_config", interactive=True)1166            cluster_choice = gr.Dropdown(label="(可选)选择聚类模型/特征检索模型", choices=cluster_list, value="no_clu")1167            refresh = gr.Button("刷新选项")1168            with gr.Row():1169                enhance = gr.Checkbox(label="是否使用NSF_HIFIGAN增强,该选项对部分训练集少的模型有一定的音质增强效果,但是对训练好的模型有反面效果,默认关闭", value=False)1170                only_diffusion = gr.Checkbox(label="是否使用全扩散推理,开启后将不使用So-VITS模型,仅使用扩散模型进行完整扩散推理,不建议使用", value=False)1171            with gr.Row():1172                diffusion_method = gr.Dropdown(label="扩散模型采样器", choices=["dpm-solver++","dpm-solver","pndm","ddim","unipc"], value="dpm-solver++")1173                diffusion_speedup = gr.Number(label="扩散加速倍数,默认为10倍", value=10)1174            using_device = gr.Dropdown(label="推理设备,默认为自动选择", choices=["Auto",*cuda.keys(),"cpu"], value="Auto")1175            with gr.Row():1176                loadckpt = gr.Button("加载模型", variant="primary")1177                unload = gr.Button("卸载模型", variant="primary")1178            with gr.Row():1179                model_message = gr.Textbox(label="Output Message")1180                sid = gr.Dropdown(label="So-VITS说话人", value="speaker0")1181            1182            inference_tab.select(refresh_options,[],[choice_ckpt,config_choice,cluster_choice,diff_choice,diff_config_choice])1183            choice_ckpt.change(auto_load, [choice_ckpt], [model_branch, config_choice, config_info])  1184            config_choice.change(load_json_encoder, [config_choice, choice_ckpt], [config_info])1185            diff_choice.change(auto_load_diff, [diff_choice], [diff_config_choice])1186            refresh.click(refresh_options,[],[choice_ckpt,config_choice,cluster_choice,diff_choice,diff_config_choice,mode_caption])1187 1188            gr.Markdown(value="""1189                请稍等片刻,模型加载大约需要10秒。后续操作不需要重新加载模型1190                """)1191            with gr.Tabs():1192                with gr.TabItem("单个音频上传"):1193                    vc_input3 = gr.Audio(label="单个音频上传", type="filepath", source="upload")1194                    use_microphone = gr.Checkbox(label="使用麦克风输入")1195                with gr.TabItem("批量音频上传"):1196                    vc_batch_files = gr.Files(label="批量音频上传", file_types=["audio"], file_count="multiple")1197                with gr.TabItem("文字转语音"):1198                    gr.Markdown("""1199                        文字转语音(TTS)说明:使用edge_tts服务生成音频,并转换为So-VITS模型音色。1200                    """)

Showing the first 1,200 of 1513 lines. Download the file for the rest.