From 2398e1d76f1d11cee908beeab480913bc2434baf Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 26 Feb 2023 16:45:27 +0800 Subject: [PATCH 1/3] feat: better support for cmd inference --- inference/infer_tool.py | 24 +++++++++++++++--------- inference_main.py | 37 +++++++++++++++++++------------------ onnx_export.py | 11 ----------- utils.py | 3 +-- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/inference/infer_tool.py b/inference/infer_tool.py index 415e956..6c69982 100644 --- a/inference/infer_tool.py +++ b/inference/infer_tool.py @@ -16,16 +16,19 @@ import torchaudio import cluster -from hubert import hubert_model import utils from models import SynthesizerTrn +from pathlib import Path + logging.getLogger('matplotlib').setLevel(logging.WARNING) def read_temp(file_name): - if not os.path.exists(file_name): - with open(file_name, "w") as f: + path = Path(file_name) + if not path.exists(): + path.parent.mkdir(exist_ok=True) + with open(path, "w") as f: f.write(json.dumps({"info": "temp_dict"})) return {} else: @@ -61,11 +64,13 @@ def run(*args, **kwargs): return run -def format_wav(audio_path): - if Path(audio_path).suffix == '.wav': - return +def format_wav(audio_path: Path): + if audio_path.suffix == '.wav': + return audio_path + audio_path = audio_path.with_suffix(".wav") raw_audio, raw_sample_rate = librosa.load(audio_path, mono=True, sr=None) - soundfile.write(Path(audio_path).with_suffix(".wav"), raw_audio, raw_sample_rate) + soundfile.write(audio_path, raw_audio, raw_sample_rate) + return audio_path def get_end_file(dir_path, end): @@ -107,7 +112,8 @@ def pad_array(arr, target_length): class Svc(object): def __init__(self, net_g_path, config_path, device=None, - cluster_model_path="logs/44k/kmeans_10000.pt"): + cluster_model_path="logs/44k/kmeans_10000.pt", + hubert_model_path="hubert/checkpoint_best_legacy_500.pt"): self.net_g_path = net_g_path if device is None: self.dev = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -119,7 +125,7 @@ def __init__(self, net_g_path, config_path, self.hop_size = self.hps_ms.data.hop_length self.spk2id = self.hps_ms.spk # 加载hubert - self.hubert_model = utils.get_hubert_model().to(self.dev) + self.hubert_model = utils.get_hubert_model(hubert_model_path).to(self.dev) self.load_model() if os.path.exists(cluster_model_path): self.cluster_model = cluster.get_cluster_model(cluster_model_path) diff --git a/inference_main.py b/inference_main.py index f869369..e6102ac 100644 --- a/inference_main.py +++ b/inference_main.py @@ -1,12 +1,10 @@ import io import logging -import time from pathlib import Path -import librosa -import matplotlib.pyplot as plt import numpy as np import soundfile +import platform from inference import infer_tool from inference import slicer @@ -25,7 +23,7 @@ def main(): # 一定要设置的部分 parser.add_argument('-m', '--model_path', type=str, default="logs/44k/G_0.pth", help='模型路径') parser.add_argument('-c', '--config_path', type=str, default="configs/config.json", help='配置文件路径') - parser.add_argument('-n', '--clean_names', type=str, nargs='+', default=["君の知らない物語-src.wav"], help='wav文件名列表,放在raw文件夹下') + parser.add_argument('-f', '--input_files', type=str, nargs='+', default=["raw/君の知らない物語-src.wav"], help='wav文件名列表,放在raw文件夹下') parser.add_argument('-t', '--trans', type=int, nargs='+', default=[0], help='音高调整,支持正负(半音)') parser.add_argument('-s', '--spk_list', type=str, nargs='+', default=['nen'], help='合成目标说话人名称') @@ -41,12 +39,15 @@ def main(): parser.add_argument('-ns', '--noice_scale', type=float, default=0.4, help='噪音级别,会影响咬字和音质,较为玄学') parser.add_argument('-p', '--pad_seconds', type=float, default=0.5, help='推理音频pad秒数,由于未知原因开头结尾会有异响,pad一小段静音段后就不会出现') parser.add_argument('-wf', '--wav_format', type=str, default='flac', help='音频输出格式') + parser.add_argument('-hb', '--hubert_path', type=str, default='hubert/checkpoint_best_legacy_500.pt', help='hubert模型路径') + parser.add_argument('-o', '--output_path', type=str, default="results", help='输出路径(文件夹)') args = parser.parse_args() - svc_model = Svc(args.model_path, args.config_path, args.device, args.cluster_model_path) + svc_model = Svc(args.model_path, args.config_path, + args.device, args.cluster_model_path, hubert_model_path=args.hubert_path) infer_tool.mkdir(["raw", "results"]) - clean_names = args.clean_names + input_list = args.input_files trans = args.trans spk_list = args.spk_list slice_db = args.slice_db @@ -55,14 +56,13 @@ def main(): cluster_infer_ratio = args.cluster_infer_ratio noice_scale = args.noice_scale pad_seconds = args.pad_seconds + output_dir = Path(args.output_path) - infer_tool.fill_a_to_b(trans, clean_names) - for clean_name, tran in zip(clean_names, trans): - raw_audio_path = f"raw/{clean_name}" - if "." not in raw_audio_path: - raw_audio_path += ".wav" - infer_tool.format_wav(raw_audio_path) - wav_path = Path(raw_audio_path).with_suffix('.wav') + infer_tool.fill_a_to_b(trans, input_list) + for input_file, tran in zip(input_list, trans): + wav_path = Path(input_file) + if not wav_path.suffix or platform.system() == "Windows": + wav_path = infer_tool.format_wav(wav_path) chunks = slicer.cut(wav_path, db_thresh=slice_db) audio_data, audio_sr = slicer.chunks2audio(wav_path, chunks) @@ -79,10 +79,10 @@ def main(): # padd pad_len = int(audio_sr * pad_seconds) data = np.concatenate([np.zeros([pad_len]), data, np.zeros([pad_len])]) - raw_path = io.BytesIO() - soundfile.write(raw_path, data, audio_sr, format="wav") - raw_path.seek(0) - out_audio, out_sr = svc_model.infer(spk, tran, raw_path, + data_with_pad = io.BytesIO() + soundfile.write(data_with_pad, data, audio_sr, format="wav") + data_with_pad.seek(0) + out_audio, out_sr = svc_model.infer(spk, tran, data_with_pad, cluster_infer_ratio=cluster_infer_ratio, auto_predict_f0=auto_predict_f0, noice_scale=noice_scale @@ -94,7 +94,8 @@ def main(): audio.extend(list(infer_tool.pad_array(_audio, length))) key = "auto" if auto_predict_f0 else f"{tran}key" cluster_name = "" if cluster_infer_ratio == 0 else f"_{cluster_infer_ratio}" - res_path = f'./results/{clean_name}_{key}_{spk}{cluster_name}.{wav_format}' + clean_name = Path(input_file).stem + res_path = output_dir / f'{clean_name}_{key}_{spk}{cluster_name}.{wav_format}' soundfile.write(res_path, audio, svc_model.target_sample, format=wav_format) if __name__ == '__main__': diff --git a/onnx_export.py b/onnx_export.py index 53b278d..f1ee3d0 100644 --- a/onnx_export.py +++ b/onnx_export.py @@ -4,17 +4,6 @@ from onnxexport.model_onnx import SynthesizerTrn import utils -def get_hubert_model(): - vec_path = "hubert/checkpoint_best_legacy_500.pt" - print("load model(s) from {}".format(vec_path)) - models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task( - [vec_path], - suffix="", - ) - model = models[0] - model.eval() - return model - def main(HubertExport, NetExport): path = "SoVits4.0" diff --git a/utils.py b/utils.py index 229ac28..01f6dc2 100644 --- a/utils.py +++ b/utils.py @@ -179,8 +179,7 @@ def f0_to_coarse(f0): return f0_coarse -def get_hubert_model(): - vec_path = "hubert/checkpoint_best_legacy_500.pt" +def get_hubert_model(vec_path: str = "hubert/checkpoint_best_legacy_500.pt"): print("load model(s) from {}".format(vec_path)) from fairseq import checkpoint_utils models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task( From e31a1f74d5dd202142a7f2b462f44191ff8e56ec Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 26 Feb 2023 18:25:36 +0800 Subject: [PATCH 2/3] fix: fix output floder creation error --- inference_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inference_main.py b/inference_main.py index e6102ac..f8380c0 100644 --- a/inference_main.py +++ b/inference_main.py @@ -46,7 +46,6 @@ def main(): svc_model = Svc(args.model_path, args.config_path, args.device, args.cluster_model_path, hubert_model_path=args.hubert_path) - infer_tool.mkdir(["raw", "results"]) input_list = args.input_files trans = args.trans spk_list = args.spk_list @@ -57,6 +56,7 @@ def main(): noice_scale = args.noice_scale pad_seconds = args.pad_seconds output_dir = Path(args.output_path) + output_dir.mkdir(parents=True, exist_ok=True) infer_tool.fill_a_to_b(trans, input_list) for input_file, tran in zip(input_list, trans): From e9ea9dfa18ecfee1f3aa1fe00314e77cc4265f4c Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 5 Mar 2023 22:08:57 +0800 Subject: [PATCH 3/3] docs: update usage for inference --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e0f35a..0653b42 100644 --- a/README.md +++ b/README.md @@ -79,12 +79,12 @@ python train.py -c configs/config.json -m 44k ```shell # 例 -python inference_main.py -m "logs/44k/G_30400.pth" -c "configs/config.json" -n "君の知らない物語-src.wav" -t 0 -s "nen" +python inference_main.py -m "logs/44k/G_30400.pth" -c "configs/config.json" -f "raw/君の知らない物語-src.wav" -t 0 -s "nen" ``` 必填项部分 + -m, --model_path:模型路径。 + -c, --config_path:配置文件路径。 -+ -n, --clean_names:wav 文件名列表,放在 raw 文件夹下。 ++ -f, --input_files:wav 文件名列表,相对/绝对路径均可。 + -t, --trans:音高调整,支持正负(半音)。 + -s, --spk_list:合成目标说话人名称。