diff --git a/infer-web.py b/infer-web.py index 47596d539..1522d95c1 100644 --- a/infer-web.py +++ b/infer-web.py @@ -835,6 +835,7 @@ def change_f0_method(f0method8): fn=clean, inputs=[], outputs=[sid0], api_name="infer_clean" ) with gr.TabItem(i18n("单次推理")): + vc_output3_base64 = gr.JSON(label="US_Base64_Data", visible=False) with gr.Group(): with gr.Row(): with gr.Column(): @@ -962,7 +963,7 @@ def change_f0_method(f0method8): rms_mix_rate0, protect0, ], - [vc_output1, vc_output2], + [vc_output1, vc_output2, vc_output3_base64], api_name="infer_convert", ) with gr.TabItem(i18n("批量推理")): diff --git a/infer/lib/audio.py b/infer/lib/audio.py index 60ef07cda..efe47abed 100644 --- a/infer/lib/audio.py +++ b/infer/lib/audio.py @@ -5,6 +5,7 @@ from io import BytesIO import traceback import re +import glob def wav2(i, o, format): @@ -36,6 +37,19 @@ def load_audio(file, sr): # This launches a subprocess to decode audio while down-mixing and resampling as necessary. # Requires the ffmpeg CLI and `ffmpeg-python` package to be installed. file = clean_path(file) # 防止小白拷路径头尾带了空格和"和回车 + + if os.path.exists(file) == False: + base_name = os.path.basename(file) + + if "." in base_name and file != "": + search_path = ( + file.rsplit(".", 1)[0] + "*" + "." + file.rsplit(".", 1)[1] + ) + found_files = glob.glob(search_path) + + if len(found_files) > 0: + file = found_files[0] + if os.path.exists(file) == False: raise RuntimeError( "You input a wrong audio path that does not exists, please fix it!" @@ -52,9 +66,10 @@ def load_audio(file, sr): return np.frombuffer(out, np.float32).flatten() - def clean_path(path_str): if platform.system() == "Windows": path_str = path_str.replace("/", "\\") - path_str = re.sub(r'[\u202a\u202b\u202c\u202d\u202e]', '', path_str) # 移除 Unicode 控制字符 + path_str = re.sub( + r"[\u202a\u202b\u202c\u202d\u202e]", "", path_str + ) # 移除 Unicode 控制字符 return path_str.strip(" ").strip('"').strip("\n").strip('"').strip(" ") diff --git a/infer/modules/vc/modules.py b/infer/modules/vc/modules.py index 6f695cc39..5d3fb0c31 100644 --- a/infer/modules/vc/modules.py +++ b/infer/modules/vc/modules.py @@ -8,6 +8,9 @@ import torch from io import BytesIO +import base64 +import os + from infer.lib.audio import load_audio, wav2 from infer.lib.infer_pack.models import ( SynthesizerTrnMs256NSFsid, @@ -158,6 +161,19 @@ def vc_single( rms_mix_rate, protect, ): + + if input_audio_path is None or input_audio_path == "": + if isinstance(f0_file, str) and f0_file != "": + input_audio_path = f0_file + f0_file = None + elif ( + hasattr(f0_file, "name") + and isinstance(getattr(f0_file, "name"), str) + and getattr(f0_file, "name") != "" + ): + input_audio_path = getattr(f0_file, "name") + f0_file = None + if input_audio_path is None: return "You need to upload an audio", None f0_up_key = int(f0_up_key) @@ -214,15 +230,44 @@ def vc_single( if os.path.exists(file_index) else "Index not used." ) + + audio_return = (tgt_sr, audio_opt) + + cleaned_input_path = "" + if input_audio_path and isinstance(input_audio_path, str): + cleaned_input_path = input_audio_path.strip(" ").strip('"').strip("\n") + + temp_dir = ( + os.path.dirname(cleaned_input_path) + if cleaned_input_path and os.path.dirname(cleaned_input_path) + else "./" + ) + + temp_wav_path = os.path.join(temp_dir, f"temp_rvc_base64_{os.getpid()}.wav") + + sf.write(temp_wav_path, audio_opt, tgt_sr, format="WAV") + + with open(temp_wav_path, "rb") as f: + raw_base64 = base64.b64encode(f.read()).decode("utf-8") + + os.remove(temp_wav_path) + + base64_data_uri = f"data:audio/wav;base64,{raw_base64}" + return ( "Success.\n%s\nTime:\nnpy: %.2fs, f0: %.2fs, infer: %.2fs." % (index_info, *times), - (tgt_sr, audio_opt), + audio_return, + { + "name": "rvc_conversion.wav", + "data": base64_data_uri, + "is_us_base64": True, + }, ) except: info = traceback.format_exc() logger.warning(info) - return info, (None, None) + return info, (None, None), None def vc_multi( self, @@ -259,7 +304,7 @@ def vc_multi( paths = [path.name for path in paths] infos = [] for path in paths: - info, opt = self.vc_single( + info, opt, base64_opt = self.vc_single( sid, path, f0_up_key,