diff --git a/AutoCoverTool/online/webui.py b/AutoCoverTool/online/webui.py deleted file mode 100644 index 30ed200..0000000 --- a/AutoCoverTool/online/webui.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -构建唱歌音色转换网页(基于3.0) -要求: -1. 音频上传 -2. 推理 -3. 下载 -""" -import os -import time -import glob -import shutil -import librosa -import soundfile -import gradio as gr -from online.inference_one import inf - -gs_tmp_dir = "/tmp/auto_cover_tool_web" -gs_res_dir = "/data/rsync/jianli.yang/AutoCoverTool/data/online_models" -gs_model_dir = os.path.join(gs_res_dir, 'models') -gs_config_path = os.path.join(gs_res_dir, 'config.json') -gs_models_choices = glob.glob(os.path.join(gs_model_dir, "*/*pth")) -gs_model_list_dropdown = None - - -def svc(audio_data, model_path, tran): - sr, data = audio_data - if os.path.exists(gs_tmp_dir): - shutil.rmtree(gs_tmp_dir) - os.makedirs(gs_tmp_dir) - tmp_path = os.path.join(gs_tmp_dir, "tmp.wav") - soundfile.write(tmp_path, data, sr, format="wav") - - # 重采样到32k - audio, sr = librosa.load(tmp_path, sr=32000, mono=True) - tmp_path = os.path.join(gs_tmp_dir, "tmp_32.wav") - out_path = os.path.join(gs_tmp_dir, "out.wav") - soundfile.write(tmp_path, audio, sr, format="wav") - - # 推理 - print("svc: {}, tran={}".format(model_path, tran)) - st = time.time() - inf(model_path, gs_config_path, tmp_path, out_path, 'prod', tran) - print("input d={}, sp = {}".format(len(audio) / sr, time.time() - st)) - return out_path - - -def model_select(): - files = glob.glob(os.path.join(gs_model_dir, "*/*pth")) - return gs_model_list_dropdown.update(choices=files) - - -def main(): - # header - app = gr.Blocks() - with app: - # 头部介绍 - gr.Markdown(value=""" - ### 唱歌音色转换 - 作者:starmaker音视频 - """) - global gs_model_list_dropdown - gs_model_list_dropdown = gr.Dropdown(choices=gs_models_choices, interactive=True, label="model list") - refresh_btn = gr.Button("refresh_model_list") - refresh_btn.click(fn=model_select, inputs=[], outputs=gs_model_list_dropdown) - - # 音频输入框 - input_audio = gr.inputs.Audio(label="input") - vc_transform = gr.Number(label="变调(整数,可以正负,半音数量,升高八度就是12)", value=0) - gen_btn = gr.Button("generate", variant="primary") - output_audio = gr.outputs.Audio(label="output", type='filepath') - gen_btn.click(fn=svc, inputs=[input_audio, gs_model_list_dropdown, vc_transform], outputs=output_audio) - # 本方法实现同一时刻只有一个程序在服务器端运行 - app.queue(concurrency_count=1, max_size=2044).launch(server_name="0.0.0.0", inbrowser=True, quiet=True, - server_port=7860) - - -if __name__ == '__main__': - main() diff --git a/AutoCoverTool/ref/so_vits_svc/utils.py b/AutoCoverTool/ref/so_vits_svc/utils.py index d7e3c4f..2dadf1a 100644 --- a/AutoCoverTool/ref/so_vits_svc/utils.py +++ b/AutoCoverTool/ref/so_vits_svc/utils.py @@ -1,366 +1,366 @@ import os import glob import re import sys import argparse import logging import json import subprocess import librosa import numpy as np import torchaudio from scipy.io.wavfile import read import torch import torchvision from torch.nn import functional as F from commons import sequence_mask from hubert import hubert_model MATPLOTLIB_FLAG = False logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) logger = logging f0_bin = 256 f0_max = 1100.0 f0_min = 50.0 f0_mel_min = 1127 * np.log(1 + f0_min / 700) f0_mel_max = 1127 * np.log(1 + f0_max / 700) def f0_to_coarse(f0): """ 将f0按照Log10的级别进行区分,最后归一化到[1-255] 之间 :param f0: :return: """ is_torch = isinstance(f0, torch.Tensor) f0_mel = 1127 * (1 + f0 / 700).log() if is_torch else 1127 * np.log(1 + f0 / 700) f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - f0_mel_min) * (f0_bin - 2) / (f0_mel_max - f0_mel_min) + 1 f0_mel[f0_mel <= 1] = 1 f0_mel[f0_mel > f0_bin - 1] = f0_bin - 1 # np.rint() 四舍五入取整 f0_coarse = (f0_mel + 0.5).long() if is_torch else np.rint(f0_mel).astype(np.int) assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, (f0_coarse.max(), f0_coarse.min()) return f0_coarse def get_hubert_model(rank=None): - hubert_soft = hubert_model.hubert_soft("data/models/hubert-soft-0d54a1f4.pt") + hubert_soft = hubert_model.hubert_soft("/data/prod/so_vits_models/models/hubert-soft-0d54a1f4.pt") if rank is not None: hubert_soft = hubert_soft.cuda(rank) return hubert_soft def get_hubert_content(hmodel, y=None, path=None): if path is not None: source, sr = torchaudio.load(path) source = torchaudio.functional.resample(source, sr, 16000) if len(source.shape) == 2 and source.shape[1] >= 2: source = torch.mean(source, dim=0).unsqueeze(0) else: source = y source = source.unsqueeze(0) with torch.inference_mode(): units = hmodel.units(source) return units.transpose(1, 2) def get_content(cmodel, y): with torch.no_grad(): c = cmodel.extract_features(y.squeeze(1))[0] c = c.transpose(1, 2) return c def transform(mel, height): # 68-92 # r = np.random.random() # rate = r * 0.3 + 0.85 # 0.85-1.15 # height = int(mel.size(-2) * rate) tgt = torchvision.transforms.functional.resize(mel, (height, mel.size(-1))) if height >= mel.size(-2): return tgt[:, :mel.size(-2), :] else: silence = tgt[:, -1:, :].repeat(1, mel.size(-2) - height, 1) silence += torch.randn_like(silence) / 10 return torch.cat((tgt, silence), 1) def stretch(mel, width): # 0.5-2 return torchvision.transforms.functional.resize(mel, (mel.size(-2), width)) def load_checkpoint(checkpoint_path, model, optimizer=None): assert os.path.isfile(checkpoint_path) checkpoint_dict = torch.load(checkpoint_path, map_location='cpu') iteration = checkpoint_dict['iteration'] learning_rate = checkpoint_dict['learning_rate'] if iteration is None: iteration = 1 if learning_rate is None: learning_rate = 0.0002 if optimizer is not None and checkpoint_dict['optimizer'] is not None: optimizer.load_state_dict(checkpoint_dict['optimizer']) saved_state_dict = checkpoint_dict['model'] if hasattr(model, 'module'): state_dict = model.module.state_dict() else: state_dict = model.state_dict() new_state_dict = {} for k, v in state_dict.items(): try: new_state_dict[k] = saved_state_dict[k] except: logger.info("%s is not in the checkpoint" % k) new_state_dict[k] = v if hasattr(model, 'module'): model.module.load_state_dict(new_state_dict) else: model.load_state_dict(new_state_dict) logger.info("Loaded checkpoint '{}' (iteration {})".format( checkpoint_path, iteration)) return model, optimizer, learning_rate, iteration def save_checkpoint(model, optimizer, learning_rate, iteration, checkpoint_path): logger.info("Saving model and optimizer state at iteration {} to {}".format( iteration, checkpoint_path)) if hasattr(model, 'module'): state_dict = model.module.state_dict() else: state_dict = model.state_dict() torch.save({'model': state_dict, 'iteration': iteration, 'optimizer': optimizer.state_dict(), 'learning_rate': learning_rate}, checkpoint_path) clean_ckpt = False if clean_ckpt: clean_checkpoints(path_to_models='logs/32k/', n_ckpts_to_keep=3, sort_by_time=True) def clean_checkpoints(path_to_models='logs/48k/', n_ckpts_to_keep=2, sort_by_time=True): """Freeing up space by deleting saved ckpts Arguments: path_to_models -- Path to the model directory n_ckpts_to_keep -- Number of ckpts to keep, excluding G_0.pth and D_0.pth sort_by_time -- True -> chronologically delete ckpts False -> lexicographically delete ckpts """ ckpts_files = [f for f in os.listdir(path_to_models) if os.path.isfile(os.path.join(path_to_models, f))] name_key = (lambda _f: int(re.compile('._(\d+)\.pth').match(_f).group(1))) time_key = (lambda _f: os.path.getmtime(os.path.join(path_to_models, _f))) sort_key = time_key if sort_by_time else name_key x_sorted = lambda _x: sorted([f for f in ckpts_files if f.startswith(_x) and not f.endswith('_0.pth')], key=sort_key) to_del = [os.path.join(path_to_models, fn) for fn in (x_sorted('G')[:-n_ckpts_to_keep] + x_sorted('D')[:-n_ckpts_to_keep])] del_info = lambda fn: logger.info(f".. Free up space by deleting ckpt {fn}") del_routine = lambda x: [os.remove(x), del_info(x)] rs = [del_routine(fn) for fn in to_del] def summarize(writer, global_step, scalars={}, histograms={}, images={}, audios={}, audio_sampling_rate=22050): for k, v in scalars.items(): writer.add_scalar(k, v, global_step) for k, v in histograms.items(): writer.add_histogram(k, v, global_step) for k, v in images.items(): writer.add_image(k, v, global_step, dataformats='HWC') for k, v in audios.items(): writer.add_audio(k, v, global_step, audio_sampling_rate) def latest_checkpoint_path(dir_path, regex="G_*.pth"): f_list = glob.glob(os.path.join(dir_path, regex)) f_list.sort(key=lambda f: int("".join(filter(str.isdigit, f)))) x = f_list[-1] print(x) return x def plot_spectrogram_to_numpy(spectrogram): global MATPLOTLIB_FLAG if not MATPLOTLIB_FLAG: import matplotlib matplotlib.use("Agg") MATPLOTLIB_FLAG = True mpl_logger = logging.getLogger('matplotlib') mpl_logger.setLevel(logging.WARNING) import matplotlib.pylab as plt import numpy as np fig, ax = plt.subplots(figsize=(10, 2)) im = ax.imshow(spectrogram, aspect="auto", origin="lower", interpolation='none') plt.colorbar(im, ax=ax) plt.xlabel("Frames") plt.ylabel("Channels") plt.tight_layout() fig.canvas.draw() data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='') data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,)) plt.close() return data def plot_alignment_to_numpy(alignment, info=None): global MATPLOTLIB_FLAG if not MATPLOTLIB_FLAG: import matplotlib matplotlib.use("Agg") MATPLOTLIB_FLAG = True mpl_logger = logging.getLogger('matplotlib') mpl_logger.setLevel(logging.WARNING) import matplotlib.pylab as plt import numpy as np fig, ax = plt.subplots(figsize=(6, 4)) im = ax.imshow(alignment.transpose(), aspect='auto', origin='lower', interpolation='none') fig.colorbar(im, ax=ax) xlabel = 'Decoder timestep' if info is not None: xlabel += '\n\n' + info plt.xlabel(xlabel) plt.ylabel('Encoder timestep') plt.tight_layout() fig.canvas.draw() data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='') data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,)) plt.close() return data def load_wav_to_torch(full_path): sampling_rate, data = read(full_path) return torch.FloatTensor(data.astype(np.float32)), sampling_rate def load_filepaths_and_text(filename, split="|"): with open(filename, encoding='utf-8') as f: filepaths_and_text = [line.strip().split(split) for line in f] return filepaths_and_text def get_hparams(init=True): parser = argparse.ArgumentParser() parser.add_argument('-c', '--config', type=str, default="./configs/base.json", help='JSON file for configuration') parser.add_argument('-m', '--model', type=str, required=True, help='Model name') parser.add_argument('-l', '--logs', type=str, required=True, help='log Name') args = parser.parse_args() model_dir = os.path.join(args.logs, args.model) if not os.path.exists(model_dir): os.makedirs(model_dir) config_path = args.config config_save_path = os.path.join(model_dir, "config.json") if init: with open(config_path, "r") as f: data = f.read() with open(config_save_path, "w") as f: f.write(data) else: with open(config_save_path, "r") as f: data = f.read() config = json.loads(data) hparams = HParams(**config) hparams.model_dir = model_dir return hparams def get_hparams_from_dir(model_dir): config_save_path = os.path.join(model_dir, "config.json") with open(config_save_path, "r") as f: data = f.read() config = json.loads(data) hparams = HParams(**config) hparams.model_dir = model_dir return hparams def get_hparams_from_file(config_path): with open(config_path, "r") as f: data = f.read() config = json.loads(data) hparams = HParams(**config) return hparams def check_git_hash(model_dir): source_dir = os.path.dirname(os.path.realpath(__file__)) if not os.path.exists(os.path.join(source_dir, ".git")): logger.warn("{} is not a git repository, therefore hash value comparison will be ignored.".format( source_dir )) return cur_hash = subprocess.getoutput("git rev-parse HEAD") path = os.path.join(model_dir, "githash") if os.path.exists(path): saved_hash = open(path).read() if saved_hash != cur_hash: logger.warn("git hash values are different. {}(saved) != {}(current)".format( saved_hash[:8], cur_hash[:8])) else: open(path, "w").write(cur_hash) def get_logger(model_dir, filename="train.log"): global logger logger = logging.getLogger(os.path.basename(model_dir)) logger.setLevel(logging.DEBUG) formatter = logging.Formatter("%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s") if not os.path.exists(model_dir): os.makedirs(model_dir) h = logging.FileHandler(os.path.join(model_dir, filename)) h.setLevel(logging.DEBUG) h.setFormatter(formatter) logger.addHandler(h) return logger class HParams(): def __init__(self, **kwargs): for k, v in kwargs.items(): if type(v) == dict: v = HParams(**v) self[k] = v def keys(self): return self.__dict__.keys() def items(self): return self.__dict__.items() def values(self): return self.__dict__.values() def __len__(self): return len(self.__dict__) def __getitem__(self, key): return getattr(self, key) def __setitem__(self, key, value): return setattr(self, key, value) def __contains__(self, key): return key in self.__dict__ def __repr__(self): return self.__dict__.__repr__() diff --git a/AutoCoverTool/ref/speaker_feature_extractor/adaptive_voice_conversion/spk_compare1.py b/AutoCoverTool/ref/speaker_feature_extractor/adaptive_voice_conversion/spk_compare1.py index 17d57de..2df9740 100755 --- a/AutoCoverTool/ref/speaker_feature_extractor/adaptive_voice_conversion/spk_compare1.py +++ b/AutoCoverTool/ref/speaker_feature_extractor/adaptive_voice_conversion/spk_compare1.py @@ -1,180 +1,188 @@ import torch import numpy as np import sys import os import torch.nn as nn import torch.nn.functional as F import yaml import pickle from adaptive_voice_conversion.model import AE from adaptive_voice_conversion.utils import * from functools import reduce import json from collections import defaultdict from torch.utils.data import Dataset from torch.utils.data import TensorDataset from torch.utils.data import DataLoader from argparse import ArgumentParser, Namespace from scipy.io.wavfile import write import random from adaptive_voice_conversion.preprocess.tacotron.utils import melspectrogram2wav from adaptive_voice_conversion.preprocess.tacotron.utils import get_spectrograms import librosa class Inferencer(object): def __init__(self, config, args): # config store the value of hyperparameters, turn to attr by AttrDict self.config = config print(config) # args store other information self.args = args print(self.args) # init the model with config self.build_model() # load model self.load_model() with open(self.args.attr, 'rb') as f: self.attr = pickle.load(f) def load_model(self): # print(f'Load model from {self.args.model}') self.model.load_state_dict(torch.load(f'{self.args.model}')) return def build_model(self): # create model, discriminator, optimizers self.model = cc(AE(self.config)) # print(self.model) self.model.eval() return def utt_make_frames(self, x): frame_size = self.config['data_loader']['frame_size'] remains = x.size(0) % frame_size if remains != 0: x = F.pad(x, (0, remains)) out = x.view(1, x.size(0) // frame_size, frame_size * x.size(1)).transpose(1, 2) return out def inference_one_utterance(self, x, x_cond): x = self.utt_make_frames(x) x_cond = self.utt_make_frames(x_cond) dec, spk_emb = self.model.inference(x, x_cond) print('@@@@spk_emb.size', spk_emb.shape) dec = dec.transpose(1, 2).squeeze(0) dec = dec.detach().cpu().numpy() dec = self.denormalize(dec) wav_data = melspectrogram2wav(dec) return wav_data, dec, spk_emb def get_emb(self, x): x = self.utt_make_frames(x) return self.model.get_speaker_embeddings(x) def denormalize(self, x): m, s = self.attr['mean'], self.attr['std'] ret = x * s + m return ret def normalize(self, x): m, s = self.attr['mean'], self.attr['std'] ret = (x - m) / s return ret def write_wav_to_file(self, wav_data, output_path): write(output_path, rate=self.args.sample_rate, data=wav_data) return def inference_from_path(self, target_wav): self.args.target = target_wav src_mel, _ = get_spectrograms(self.args.source) tar_mel, _ = get_spectrograms(self.args.target) src_mel = torch.from_numpy(self.normalize(src_mel)).cuda() tar_mel = torch.from_numpy(self.normalize(tar_mel)).cuda() conv_wav, conv_mel, spk_emb = self.inference_one_utterance(src_mel, tar_mel) # self.write_wav_to_file(conv_wav, self.args.output) return spk_emb def inference_from_path_v1(self, target_wav): tar_mel, _ = get_spectrograms(target_wav) tar_mel = torch.from_numpy(self.normalize(tar_mel)).cuda() with torch.no_grad(): spk_emb = self.get_emb(tar_mel) return spk_emb +class CurArgs: + def __init__(self, attr, config, model): + self.sample_rate = 24000 + self.attr = attr + self.config = config + self.model = model + + def infer_load(): - parser = ArgumentParser() - parser.add_argument('-attr', '-a', help='attr file path') - parser.add_argument('-config', '-c', help='config file path') - parser.add_argument('-model', '-m', help='model path') - parser.add_argument('-source', '-s', help='source wav path') - parser.add_argument('-target', '-t', help='target wav path') - parser.add_argument('-output', '-o', help='output wav path') - parser.add_argument('-sample_rate', '-sr', help='sample rate', default=24000, type=int) - args = parser.parse_args() + # parser = ArgumentParser() + # parser.add_argument('-attr', '-a', help='attr file path') + # parser.add_argument('-config', '-c', help='config file path') + # parser.add_argument('-model', '-m', help='model path') + # parser.add_argument('-source', '-s', help='source wav path') + # parser.add_argument('-target', '-t', help='target wav path') + # parser.add_argument('-output', '-o', help='output wav path') + # parser.add_argument('-sample_rate', '-sr', help='sample rate', default=24000, type=int) + # args = parser.parse_args() base_dir = os.path.dirname(__file__) - args.attr = os.path.join(base_dir, 'premodes/attr.pkl') - args.config = os.path.join(base_dir, 'config.yaml') - args.model = os.path.join(base_dir, 'premodes/vctk_model.ckpt') - + attr = os.path.join(base_dir, 'premodes/attr.pkl') + config = os.path.join(base_dir, 'config.yaml') + model = os.path.join(base_dir, 'premodes/vctk_model.ckpt') + args = CurArgs(attr, config, model) # load config file - print('args.config: ', args.config) + # print('args.config: ', args.config) with open(args.config) as f: config = yaml.load(f, Loader=yaml.FullLoader) inferencer = Inferencer(config=config, args=args) return inferencer def infer_main(inferencer, target_wav_name): spk_emb = inferencer.inference_from_path_v1(target_wav_name).detach().cpu().numpy().squeeze() return spk_emb def l2_norm(s1, s2): norm = np.sum(s1 * s2, -1) return norm def cos_distance(s1, s2, eps=1e-8): s1_s2_norm = l2_norm(s1, s2) s2_s2_norm = l2_norm(s2, s2) s1_s1_norm = l2_norm(s1, s1) print('s1_s1_norm: ', s1_s1_norm) print('s1_s2_norm: ', s1_s2_norm) print('s2_s2_norm: ', s2_s2_norm) loss = s1_s2_norm / (np.sqrt(s2_s2_norm * s1_s1_norm) + eps) return loss def similarity_pro(inferencer, wav_name1, wav_name2): spk_emb1 = infer_main(inferencer, wav_name1) spk_emb2 = infer_main(inferencer, wav_name2) # print('spk_emb1 size: ',spk_emb1.shape) pro = cos_distance(spk_emb1, spk_emb2) # print("probability size is :", pro.shape) return pro if __name__ == '__main__': inferencer = infer_load() wav_name1 = '/data/bingxiao.fang/voice_conversion/voice_wav/target_path/jl_24k.wav' wav_name2 = '/data/bingxiao.fang/voice_conversion/voice_wav/source_path/yibo_24k.wav' wav_name3 = '/data/bingxiao.fang/voice_conversion/voice_wav/target_path/180_3_3_24k.wav' pro1 = similarity_pro(inferencer, wav_name1, wav_name3) pro2 = similarity_pro(inferencer, wav_name1, wav_name2) pro3 = similarity_pro(inferencer, wav_name3, wav_name2) print('###jl and suiyanzi wavcos distance :', pro1) print('###jl and yibo wav cos distance :', pro2) print('###yibo and sunyanzi wav cos distance :', pro3) pass diff --git a/AutoCoverTool/res/syz_test.wav b/AutoCoverTool/res/syz_test.wav new file mode 100644 index 0000000..130ef69 Binary files /dev/null and b/AutoCoverTool/res/syz_test.wav differ diff --git a/AutoCoverTool/script/upload_mode2db.py b/AutoCoverTool/script/upload_mode2db.py new file mode 100644 index 0000000..be3773d --- /dev/null +++ b/AutoCoverTool/script/upload_mode2db.py @@ -0,0 +1,280 @@ +""" +将训练好的模型写入到数据库 +""" +from online.common import update_db, get_data_by_mysql +import os + +GS_COSCMD = "/data/gpu_env_common/env/anaconda3/envs/auto_song_cover/bin/coscmd" +GS_CONFIG_PATH = "/home/normal/.cos.conf" + + +def exec_cmd(cmd): + ret = os.system(cmd) + if ret != 0: + return False + return True + + +def exec_cmd_and_result(cmd): + r = os.popen(cmd) + text = r.read() + r.close() + return text + + +def upload_file2cos(key, file_path, region, bucket_name): + """ + 将文件上传到cos + :param key: 桶上的具体地址 + :param file_path: 本地文件地址 + :param region: 区域 + :param bucket_name: 桶地址 + :return: + """ + cmd = "{} -c {} -r {} -b {} upload {} {}".format(GS_COSCMD, GS_CONFIG_PATH, region, bucket_name, file_path, key) + print(cmd) + if exec_cmd(cmd): + cmd = "{} -c {} -r {} -b {} info {}".format(GS_COSCMD, GS_CONFIG_PATH, region, bucket_name, key) \ + + "| grep Content-Length |awk \'{print $2}\'" + res_str = exec_cmd_and_result(cmd) + size = float(res_str) + if size > 0: + return True + return False + return False + + +def upload_one2db(db_path, db_name): + # 判断已经在数据库中,则不上传 + sql = "select * from av_db.av_svc_model where user_id=\"{}\"".format(db_name) + data = get_data_by_mysql(sql) + if len(data) == 0: + print('start upload ....') + key = "av_res/so_vits_models/3.0/male/{}.pth".format(db_name) + if upload_file2cos(key, db_path, region="ap-beijing", bucket_name="av-audit-sync-bj-1256122840"): + # 写入到数据库 + sql = "insert into av_db.av_svc_model (model_version, user_id, model_url, gender) values (\"sovits3.0\", \"{}\", \"{}\", 1)".format( + db_name, key) + update_db(sql) + + +if __name__ == '__main__': + # arr = [ + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099162839896/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099162997509/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099163727028/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099163890661/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099163991355/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099164311744/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099164313669/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099165386135/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099166041782/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099166050735/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099166238022/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099166605472/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099166892845/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099166898301/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099167125366/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099167394822/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099167940583/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099168376799/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099168924385/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099169324630/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099169381678/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099169957610/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099169975944/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099170492806/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099170892510/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099171013390/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099171081854/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099171087756/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099171192036/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099171607206/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099171754668/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099172086640/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099172138002/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099172207062/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099172269180/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099172339368/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574138359736/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574138369704/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574138530136/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574139102564/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574139888146/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574139967984/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574140258122/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574140405046/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574140676612/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574140780266/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574142812606/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574143134746/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574143604234/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574143906306/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574144526110/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574144707118/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574145823464/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574145904464/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574146080322/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574146420792/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574146884926/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147339012/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147372254/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147425002/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147597736/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147647706/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147658166/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574147828554/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574148014424/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574148247626/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574148624370/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574148669184/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574148692388/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574148859406/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574149000590/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574149067094/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574149143568/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574149221618/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10414574149303702/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049115833380/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049115944594/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049115987498/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049116130908/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049116285936/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049117044138/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049117276112/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049117685892/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049119207544/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049119659788/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049120426324/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049120919532/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049121183928/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049121338248/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049121406512/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049121502826/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049123071172/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049123219186/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049123447868/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049123506368/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049123660154/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049123805538/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049124073344/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049124110520/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049124182084/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049124450100/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049124595430/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049124833978/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125084058/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125481092/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125584584/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125798928/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125820940/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125864268/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125885128/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125972416/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125997808/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10696049125999636/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524091895906/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524092611108/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524092703694/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524092737576/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524092926748/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524093350560/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524093613618/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524094859474/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524096635844/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524096695280/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524096819198/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524096995342/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524098416100/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524098804908/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524099612646/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524100174518/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524100978492/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524101050108/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524101220516/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524101243434/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524101575638/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524101593280/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524101680844/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102313334/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102348346/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102432628/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102444474/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102525738/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102533320/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102598012/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102674590/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102678972/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10977524102679572/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899906849269/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899908853925/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899908854526/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899908904395/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899909347935/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899909790502/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910057693/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910105120/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910461551/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910516883/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910808376/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910826302/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899910943438/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899911011477/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899911821662/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899911962207/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912327206/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912442110/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912511535/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912520616/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912538184/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912584668/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912859360/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912895306/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912929958/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/1125899912987231/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/3635049378/logs/32k/G_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/8725724286358130/logs/32k/G_2000.pth" + # ] + arr = [ + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/10133099162058848.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/10133099162258844.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/10133099162560644.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/10133099162797809.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/10414574138721494.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/10414574140317353.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/1688849864840588.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/3634463651.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/5629499489839033.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/5910973794723621.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/6755399374234747.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/8162774327817435.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/8162774329368194.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/denglijun_g2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/female/taylor_g2000.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/10133099161752147.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/10133099161920114.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/10133099162292113.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/10133099162767013.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/1125899914308640.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/12384898975368914.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/12947848931397021.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/3096224748076687.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/3096224751151928.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/5066549357604730.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/5348024335101054.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/6755399442719465.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/7036874421386111.pth", + "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/male/jianli_g_2000.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/unknown/10133099171607206.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/unknown/10133099172269180.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/unknown/10414574138369704.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/unknown/10414574143604234.pth", + # "/data/rsync/jianli.yang/AutoCoverTool/data/online_models/models/unknown/10414574144707118.pth" + ] + for d_file in arr: + # d_file = "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/multi_users/10133099162839896/logs/32k/G_2000.pth" + # d_name = "10133099162839896" + d_name = d_file.split("/")[-1].split(".")[0] + print(d_file, d_name) + upload_one2db(d_file, d_name) + # exit(-1) diff --git a/AutoCoverTool/svc_inference/svc_inference_one.py b/AutoCoverTool/svc_inference/svc_inference_one.py index 1bab8e0..5218e1e 100644 --- a/AutoCoverTool/svc_inference/svc_inference_one.py +++ b/AutoCoverTool/svc_inference/svc_inference_one.py @@ -1,187 +1,210 @@ """ SVC推理逻辑 +conda activate auto_song_cover_t4 +export PYTHONPATH=$PWD:$PWD/ref/music_remover/demucs:$PWD/ref/so_vits_svc:$PWD/ref/split_dirty_frame:$PWD/ref/online """ import os import shutil from ref.so_vits_svc.inference_main import * from ref.speaker_feature_extractor.sf_extractor_interface import SFExtractorInterface gs_draw_volume_exe = "/data/gpu_env_common/bin/draw_volume" gs_simple_mixer_path = "/data/gpu_env_common/bin/simple_mixer" gs_svci_success = 0 gs_svci_data_params_check_model_path = 1 gs_svci_data_params_check_vocal_path = 2 gs_svci_data_params_check_acc_path = 3 gs_svci_data_params_check_video_path = 4 gs_svci_data_prepare_transcode_media = 5 gs_svci_data_inference = 6 gs_svci_svc_trans_442 = 7 gs_svci_svc_volume = 8 gs_svci_svc_mix = 9 gs_svci_svc_mix_gen = 10 gs_svci_svc_mix_audio_video = 11 class SVCInferenceOne: def __init__(self): self.vocal_32_wav_path = None self.vocal_wav_path = None self.acc_wav_path = None self.config = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.json") self.spk_emb_inst = SFExtractorInterface() def mix(self, work_dir, svc_file, vocal_file, acc_file, mix_path): """ :param work_dir: :param svc_file: :param vocal_file: :param acc_file: :param mix_path: :return: """ cache_dir = os.path.join(work_dir, "cache") if os.path.exists(cache_dir): shutil.rmtree(cache_dir) os.makedirs(cache_dir) # svc转码到442 svc_442_file = os.path.join(cache_dir, "442.wav") st = time.time() cmd = "ffmpeg -i {} -ar 44100 -ac 2 -y {} -loglevel fatal".format(svc_file, svc_442_file) os.system(cmd) if not os.path.exists(svc_442_file): return gs_svci_svc_trans_442 logging.info("transcode,{},sp={}".format(svc_file, time.time() - st)) # 合并转码后再做一次拉伸,保证响度 st = time.time() volume_path = os.path.join(cache_dir, "volume.wav") cmd = "{} {} {} {}".format(gs_draw_volume_exe, svc_442_file, vocal_file, volume_path) os.system(cmd) if not os.path.exists(volume_path): print("{} ERROR draw volume".format(volume_path)) return gs_svci_svc_volume logging.info("draw_volume2,{},sp={}".format(svc_file, time.time() - st)) # 混合 st = time.time() mix_wav_path = os.path.join(cache_dir, "mix.wav") cmd = "{} {} {} {}".format(gs_simple_mixer_path, volume_path, acc_file, mix_wav_path) os.system(cmd) if not os.path.exists(mix_wav_path): return gs_svci_svc_mix logging.info("mixer,{},sp={}".format(svc_file, time.time() - st)) # 编码为m4a st = time.time() cmd = "ffmpeg -i {} -ab 128k -y {} -loglevel fatal".format(mix_wav_path, mix_path) print(cmd) os.system(cmd) if not os.path.exists(mix_path): return gs_svci_svc_mix logging.info("encode,{},sp={}".format(svc_file, time.time() - st)) return gs_svci_success def params_check(self, model_path, vocal_path, acc_path, video_path): if not os.path.exists(model_path): print("model_path={} is null".format(model_path)) return gs_svci_data_params_check_model_path if not os.path.exists(vocal_path): print("vocal_path={} is null".format(vocal_path)) return gs_svci_data_params_check_vocal_path if not os.path.exists(acc_path): print("acc_path={} is null".format(acc_path)) return gs_svci_data_params_check_acc_path if not os.path.exists(video_path): print("video_path={} is null".format(video_path)) return gs_svci_data_params_check_video_path return gs_svci_success def data_prepare(self, work_dir, vocal_path, acc_path): self.vocal_32_wav_path = os.path.join(work_dir, "vocal_32.wav") self.vocal_wav_path = os.path.join(work_dir, "vocal.wav") self.acc_wav_path = os.path.join(work_dir, "acc.wav") cmd = "ffmpeg -i {} -ar 44100 -ac 2 -y {}".format(vocal_path, self.vocal_wav_path) os.system(cmd) cmd = "ffmpeg -i {} -ar 32000 -ac 1 -y {}".format(vocal_path, self.vocal_32_wav_path) os.system(cmd) cmd = "ffmpeg -i {} -ar 44100 -ac 2 -y {}".format(acc_path, self.acc_wav_path) os.system(cmd) return os.path.exists(self.vocal_32_wav_path) and os.path.exists(self.acc_wav_path) def process_logic(self, work_dir, model_path, vocal_path, acc_path, video_path, out_path): # 1. 先转码人声和伴奏 st = time.time() if not self.data_prepare(work_dir, vocal_path, acc_path): print("transcode vocal={} or acc={} err!\n".format(vocal_path, acc_path)) return gs_svci_data_prepare_transcode_media print("transcode vocal and acc sp={}".format(time.time() - st)) # 2. 进行推理 # raw_audio_path, dst_path st = time.time() svc_file = os.path.join(work_dir, "trans_vocal.wav") # try: inf(model_path, self.config, self.vocal_32_wav_path, svc_file, 'prod') # except Exception as ex: # print(ex) if not os.path.exists(svc_file): print("inference err vocal_path={}, model_path={}".format(vocal_path, model_path)) return gs_svci_data_inference, [] print("inf sp={}".format(time.time() - st)) # 3. 生成作品 st = time.time() mix_tmp_path = os.path.join(work_dir, "mix.wav") err = self.mix(work_dir, svc_file, self.vocal_wav_path, self.acc_wav_path, mix_tmp_path) if err != gs_svci_success: return err, [] if not os.path.exists(mix_tmp_path): return gs_svci_svc_mix_gen, [] print("mix sp={}".format(time.time() - st)) st = time.time() # 4. 音频编码,并且和视频合并 - cmd = "ffmpeg -i {} -i {} -acodec aac -strict -2 -b:a 128k -shortest -af apad -y {}".format(video_path, - mix_tmp_path, out_path) + cmd = "ffmpeg -i {} -i {} -acodec aac -strict -2 -b:a 128k -vcodec copy -shortest -af apad -y {}".format( + video_path, + mix_tmp_path, + out_path) os.system(cmd) if not os.path.exists(out_path): print("mix audio_video err={}".format(video_path, mix_tmp_path)) return gs_svci_svc_mix_audio_video, [] print("mix audio and video sp={}".format(time.time() - st)) # 5. 提取emb st = time.time() emb = self.spk_emb_inst.process(svc_file) print("get emb sp={}".format(time.time() - st)) return gs_svci_success, emb def process(self, work_dir, model_path, vocal_path, acc_path, video_path, out_path): err = self.params_check(model_path, vocal_path, acc_path, video_path) if err != gs_svci_success: return err, [] if os.path.exists(work_dir): shutil.rmtree(work_dir) os.makedirs(work_dir) st = time.time() err, emb = self.process_logic(work_dir, model_path, vocal_path, acc_path, video_path, out_path) print("process_logic sp={}".format(time.time() - st)) shutil.rmtree(work_dir) return err, emb -if __name__ == '__main__': +def test(): svc_inst = SVCInferenceOne() b_dir = "/data/rsync/jianli.yang/AutoCoverTool/data/test_svc_inference_one/" w_dir = os.path.join(b_dir, "rg_input") in_m4a = os.path.join(b_dir, "rg_input.m4a") in_acc_m4a = os.path.join(b_dir, "acc.m4a") in_video = os.path.join(b_dir, "rg.mp4") out_video = os.path.join(b_dir, "rg_input_out.mp4") m_path = "/data/rsync/jianli.yang/AutoCoverTool/data/train_users/jianli/logs/32k/G_2000.pth" err, emb = svc_inst.process(w_dir, m_path, in_m4a, in_acc_m4a, in_video, out_video) print(err) print(emb) + + +if __name__ == '__main__': + if len(sys.argv) != 7: + print("input err!") + print( + "example: work_dir[临时工作目录,内部会自动清除数据] model_path in_media_path in_acc_media_path in_video_path out_video_path") + exit(-1) + + w_dir = sys.argv[1] + m_path = sys.argv[2] + in_m4a = sys.argv[3] + in_acc_m4a = sys.argv[4] + in_video = sys.argv[5] + out_video = sys.argv[6] + svc_inst = SVCInferenceOne() + err, emb = svc_inst.process(w_dir, m_path, in_m4a, in_acc_m4a, in_video, out_video) + print(err) + print(emb) diff --git a/AutoCoverTool/svc_inference/webui.py b/AutoCoverTool/svc_inference/webui.py new file mode 100644 index 0000000..0cb72e5 --- /dev/null +++ b/AutoCoverTool/svc_inference/webui.py @@ -0,0 +1,88 @@ +""" +构建唱歌音色转换网页(基于3.0) +要求: +1. 音频上传 +2. 推理 +3. 下载 +""" +import os +import time +import glob +import shutil +import librosa +import soundfile +import gradio as gr +from online.common import update_db +from ref.so_vits_svc.inference_main import * + +gs_tmp_dir = "/tmp/svc_inference" +gs_model_dir = "/data/prod/so_vits_models/3.0" +gs_test_wav_dir = "/data/prod/so_vits_models/test_svc_file/3.0" +gs_config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.json") + + +def generate_svc_file(): + """ + :return: + """ + if not os.path.exists(gs_test_wav_dir): + os.makedirs(gs_test_wav_dir) + test_wav_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../res/syz_test.wav") + model_path_list = glob.glob(os.path.join(gs_model_dir, "*/*pth")) + st = time.time() + for idx, model_path in enumerate(model_path_list): + model_name = model_path.strip().split("/")[-1].split(".pth", "") + dst_path = os.path.join(gs_test_wav_dir, "{}.wav".format(model_name)) + if not os.path.exists(dst_path): + inf(model_path, gs_config_path, test_wav_path, dst_path, "prod") + print("now_per={}/{}".format(idx, len(model_path_list), time.time() - st)) + + +def update_state(gender, user_id): + sql = "update av_db.av_svc_model set gender={} where user_id=\"{}\"".format(gender, user_id) + update_db(sql) + + +# 按钮控制 +def click(): + pass + + +def main(): + # header + st = time.time() + generate_svc_file() + print("generate svc sp={}".format(time.time() - st)) + + app = gr.Blocks() + with app: + # 头部介绍 + gr.Markdown(value=""" + ### 人声质量评价 + 作者:starmaker音视频 + """) + # 列表展示 + # 1. 每一行有音频,性别,删除等按钮 + svc_files = glob.glob(os.path.join(gs_test_wav_dir, "*wav")) + for svc_file in svc_files: + gr.Audio(source=svc_file) + male_gender_btn = gr.Button("male") + female_gender_btn = gr.Button("female") + del_btn = gr.Button("female") + + refresh_btn = gr.Button("refresh_model_list") + refresh_btn.click(fn=model_select, inputs=[], outputs=gs_model_list_dropdown) + + # 音频输入框 + input_audio = gr.inputs.Audio(label="input") + vc_transform = gr.Number(label="变调(整数,可以正负,半音数量,升高八度就是12)", value=0) + gen_btn = gr.Button("generate", variant="primary") + output_audio = gr.outputs.Audio(label="output", type='filepath') + gen_btn.click(fn=svc, inputs=[input_audio, gs_model_list_dropdown, vc_transform], outputs=output_audio) + # 本方法实现同一时刻只有一个程序在服务器端运行 + app.queue(concurrency_count=1, max_size=2044).launch(server_name="0.0.0.0", inbrowser=True, quiet=True, + server_port=7860) + + +if __name__ == '__main__': + main()