Compare commits

...

18 Commits

Author SHA1 Message Date
Karasukaigan
b5a246eb06
Merge 539ad38d310d452aa1a08e659d5eac22f843a01d into 9ec3a60f30d228719e5ec6cd6796c5b2d888dd1a 2025-12-01 19:01:00 -08:00
RVC-Boss
9ec3a60f30
Update config.py 2025-12-01 20:23:49 +08:00
RVC-Boss
fc533b6fb7
Update fasterwhisper_asr.py 2025-12-01 11:38:37 +08:00
XXXXRT666
857799276c
Fix Modelscope (#2679) 2025-12-01 11:13:15 +08:00
Spr_Aachen
92d2d337fd
Fix training error caused by float type of default_batch_size parameter (#2662) 2025-11-28 22:53:43 +08:00
ChasonJiang
6fb441f65e
更友好的流模式选项 (#2678) 2025-11-28 22:13:48 +08:00
XXXXRT666
c85c54eca9
Add ModelScope Snapshot Download For ASR (#2627)
* Add ModelScope Snapshot Download For ASR

* Typo Fix

* Remove YUE in whisper

* Remove HF ENDPOINT

* Add FunASR Download
2025-11-28 22:10:49 +08:00
Karasukaigan
539ad38d31
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-07-02 15:35:45 +08:00
Karasukaigan
6df7921d56
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-06-20 00:30:43 +08:00
Karasukaigan
8d212a9255
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-06-06 19:43:11 +08:00
Karasukaigan
2fb92e74a2 更新WebUI简化版以支持V2Pro
更新了webui_simple.py以支持V2Pro系列模型。
2025-06-06 01:20:45 +08:00
Karasukaigan
be16f387f1
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-06-05 18:41:42 +08:00
Karasukaigan
7e6a607b9e
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-06-05 15:47:39 +08:00
Karasukaigan
ab5e8dc0ae
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-05-31 20:15:19 +08:00
Karasukaigan
b666becb19 撤回对于inference_webui的改动 2025-05-27 22:41:20 +08:00
Karasukaigan
47426d18e7 新增微调训练WebUI简化版
用户不再需要多次切换不同的选项卡页面来完成一次微调训练。现在微调训练的所有流程都在同一个页面里,按照从上往下的顺序排好,并且隐藏了非常用的设置项。
2025-05-27 22:22:15 +08:00
Karasukaigan
b8de0ec0ac
Merge branch 'RVC-Boss:main' into feat/frontend-usability-enhancements 2025-05-27 22:11:36 +08:00
Karasukaigan
f20f17c2c0 修复通过Gradio API调用合成语音接口时出现参数类型错误的问题
修复通过Gradio API调用合成语音接口`/get_tts_wav`时出现参数类型错误的问题。

## 报错信息
TypeError: unsupported operand type(s) for /: 'int' and 'str'

## 错误原因
`inference_webui.py`的`get_tts_wav`里并未对传入`sample_steps`的类型进行判断。而由于Gradio在自动生成接口文档时会将`gr.Radio`传入的值判定为字符串,因此如果有用户参考WebUI下面”通过 API 使用“里的说明调用`/get_tts_wav`时,则会因为文档错误导致传参类型错误,从而导致最终的报错。

## 修复方式
通过在`get_tts_wav`开头部分添加对`sample_steps`格式的转换(统一转为int)来解决传参类型错误的问题。
2025-05-16 17:58:56 +08:00
9 changed files with 2198 additions and 102 deletions

View File

@ -41,11 +41,9 @@ POST:
"repetition_penalty": 1.35, # float. repetition penalty for T2S model.
"sample_steps": 32, # int. number of sampling steps for VITS model V3.
"super_sampling": False, # bool. whether to use super-sampling for audio when using VITS model V3.
"return_fragment": False, # bool. step by step return the audio fragment. (Best Quality, Slowest response speed. old version of streaming mode)
"streaming_mode": False, # bool. return audio chunk by chunk. (Medium quality, Slow response speed)
"streaming_mode": False, # bool or int. return audio chunk by chunk.T he available options are: 0,1,2,3 or True/False (0/False: Disabled | 1/True: Best Quality, Slowest response speed (old version streaming_mode) | 2: Medium Quality, Slow response speed | 3: Lower Quality, Faster response speed )
"overlap_length": 2, # int. overlap length of semantic tokens for streaming mode.
"min_chunk_length": 16, # int. The minimum chunk length of semantic tokens for streaming mode. (affects audio chunk size)
"fixed_length_chunk": False, # bool. When turned on, it can achieve faster streaming response, but with lower quality. (lower quality, faster response speed)
"min_chunk_length": 16, # int. The minimum chunk length of semantic tokens for streaming mode. (affects audio chunk size)
}
```
@ -106,7 +104,7 @@ RESP:
import os
import sys
import traceback
from typing import Generator
from typing import Generator, Union
now_dir = os.getcwd()
sys.path.append(now_dir)
@ -171,15 +169,13 @@ class TTS_Request(BaseModel):
fragment_interval: float = 0.3
seed: int = -1
media_type: str = "wav"
streaming_mode: bool = False
streaming_mode: Union[bool, int] = False
parallel_infer: bool = True
repetition_penalty: float = 1.35
sample_steps: int = 32
super_sampling: bool = False
overlap_length: int = 2
min_chunk_length: int = 16
return_fragment: bool = False
fixed_length_chunk: bool = False
def pack_ogg(io_buffer: BytesIO, data: np.ndarray, rate: int):
@ -373,11 +369,9 @@ async def tts_handle(req: dict):
"repetition_penalty": 1.35, # float. repetition penalty for T2S model.
"sample_steps": 32, # int. number of sampling steps for VITS model V3.
"super_sampling": False, # bool. whether to use super-sampling for audio when using VITS model V3.
"return_fragment": False, # bool. step by step return the audio fragment. (Best Quality, Slowest response speed. old version of streaming mode)
"streaming_mode": False, # bool. return audio chunk by chunk. (Medium quality, Slow response speed)
"streaming_mode": False, # bool or int. return audio chunk by chunk.T he available options are: 0,1,2,3 or True/False (0/False: Disabled | 1/True: Best Quality, Slowest response speed (old version streaming_mode) | 2: Medium Quality, Slow response speed | 3: Lower Quality, Faster response speed )
"overlap_length": 2, # int. overlap length of semantic tokens for streaming mode.
"min_chunk_length": 16, # int. The minimum chunk length of semantic tokens for streaming mode. (affects audio chunk size)
"fixed_length_chunk": False, # bool. When turned on, it can achieve faster streaming response, but with lower quality. (lower quality, faster response speed)
"min_chunk_length": 16, # int. The minimum chunk length of semantic tokens for streaming mode. (affects audio chunk size)
}
returns:
StreamingResponse: audio stream response.
@ -390,9 +384,33 @@ async def tts_handle(req: dict):
check_res = check_params(req)
if check_res is not None:
return check_res
if streaming_mode == 0:
streaming_mode = False
return_fragment = False
fixed_length_chunk = False
elif streaming_mode == 1:
streaming_mode = False
return_fragment = True
fixed_length_chunk = False
elif streaming_mode == 2:
streaming_mode = True
return_fragment = False
fixed_length_chunk = False
elif streaming_mode == 3:
streaming_mode = True
return_fragment = False
fixed_length_chunk = True
else:
return JSONResponse(status_code=400, content={"message": f"the value of streaming_mode must be 0, 1, 2, 3(int) or true/false(bool)"})
req["streaming_mode"] = streaming_mode
req["return_fragment"] = return_fragment
req["fixed_length_chunk"] = fixed_length_chunk
print(f"{streaming_mode} {return_fragment} {fixed_length_chunk}")
streaming_mode = streaming_mode or return_fragment
@ -457,11 +475,9 @@ async def tts_get_endpoint(
repetition_penalty: float = 1.35,
sample_steps: int = 32,
super_sampling: bool = False,
return_fragment: bool = False,
streaming_mode: bool = False,
streaming_mode: Union[bool, int] = False,
overlap_length: int = 2,
min_chunk_length: int = 16,
fixed_length_chunk: bool = False,
):
req = {
"text": text,
@ -488,8 +504,6 @@ async def tts_get_endpoint(
"super_sampling": super_sampling,
"overlap_length": int(overlap_length),
"min_chunk_length": int(min_chunk_length),
"return_fragment": return_fragment,
"fixed_length_chunk": fixed_length_chunk
}
return await tts_handle(req)

2
go-webui-simple-mode.bat Normal file
View File

@ -0,0 +1,2 @@
runtime\python.exe -I webui_simple.py zh_CN
pause

View File

@ -16,7 +16,7 @@ pypinyin
pyopenjtalk>=0.4.1
g2p_en
torchaudio
modelscope==1.10.0
modelscope
sentencepiece
transformers>=4.43,<=4.50
peft
@ -39,7 +39,5 @@ x_transformers
torchmetrics<=1.5
pydantic<=2.10.6
ctranslate2>=4.0,<5
huggingface_hub>=0.13
tokenizers>=0.13,<1
av>=11
tqdm

View File

@ -1,34 +1,13 @@
import os
def check_fw_local_models():
"""
启动时检查本地是否有 Faster Whisper 模型.
"""
model_size_list = [
"medium",
"medium.en",
"distil-large-v2",
"distil-large-v3",
"large-v1",
"large-v2",
"large-v3",
]
for i, size in enumerate(model_size_list):
if os.path.exists(f"tools/asr/models/faster-whisper-{size}"):
model_size_list[i] = size + "-local"
return model_size_list
def get_models():
model_size_list = [
"medium",
"medium.en",
"distil-large-v2",
"distil-large-v3",
"large-v1",
"large-v2",
"large-v3",
"large-v3-turbo",
#"distil-large-v2",
#"distil-large-v3",
#"distil-large-v3.5",
]
return model_size_list
@ -36,7 +15,7 @@ def get_models():
asr_dict = {
"达摩 ASR (中文)": {"lang": ["zh", "yue"], "size": ["large"], "path": "funasr_asr.py", "precision": ["float32"]},
"Faster Whisper (多语种)": {
"lang": ["auto", "zh", "en", "ja", "ko", "yue"],
"lang": ["auto", "en", "ja", "ko"],
"size": get_models(),
"path": "fasterwhisper_asr.py",
"precision": ["float32", "float16", "int8"],

View File

@ -1,12 +1,12 @@
import argparse
import os
import time
import traceback
import requests
import torch
from faster_whisper import WhisperModel
from huggingface_hub import snapshot_download
from huggingface_hub.errors import LocalEntryNotFoundError
from huggingface_hub import snapshot_download as snapshot_download_hf
from modelscope import snapshot_download as snapshot_download_ms
from tqdm import tqdm
from tools.asr.config import get_models
@ -40,11 +40,32 @@ language_code_list = [
def download_model(model_size: str):
if "distil" in model_size:
repo_id = "Systran/faster-{}-whisper-{}".format(*model_size.split("-", maxsplit=1))
url = "https://huggingface.co/api/models/gpt2"
try:
requests.get(url, timeout=3)
source = "HF"
except Exception:
source = "ModelScope"
model_path = ""
if source == "HF":
if "distil" in model_size:
if "3.5" in model_size:
repo_id = "distil-whisper/distil-large-v3.5-ct2"
model_path = "tools/asr/models/faster-distil-whisper-large-v3.5"
else:
repo_id = "Systran/faster-{}-whisper-{}".format(*model_size.split("-", maxsplit=1))
elif model_size == "large-v3-turbo":
repo_id = "mobiuslabsgmbh/faster-whisper-large-v3-turbo"
model_path = "tools/asr/models/faster-whisper-large-v3-turbo"
else:
repo_id = f"Systran/faster-whisper-{model_size}"
model_path = (
model_path or f"tools/asr/models/{repo_id.replace('Systran/', '').replace('distil-whisper/', '', 1)}"
)
else:
repo_id = f"Systran/faster-whisper-{model_size}"
model_path = f"tools/asr/models/{repo_id.strip('Systran/')}"
repo_id = "XXXXRT/faster-whisper"
model_path = "tools/asr/models"
files: list[str] = [
"config.json",
@ -52,32 +73,31 @@ def download_model(model_size: str):
"tokenizer.json",
"vocabulary.txt",
]
if model_size == "large-v3" or "distil" in model_size:
if "large-v3" in model_size or "distil" in model_size:
files.append("preprocessor_config.json")
files.append("vocabulary.json")
files.remove("vocabulary.txt")
for attempt in range(2):
try:
snapshot_download(
repo_id=repo_id,
allow_patterns=files,
local_dir=model_path,
)
break
except LocalEntryNotFoundError:
if attempt < 1:
time.sleep(2)
else:
print("[ERROR] LocalEntryNotFoundError and no fallback.")
traceback.print_exc()
exit(1)
except Exception as e:
print(f"[ERROR] Unexpected error on attempt {attempt + 1}: {e}")
traceback.print_exc()
exit(1)
if source == "ModelScope":
files = [f"faster-whisper-{model_size}/{file}".replace("whisper-distil", "distil-whisper") for file in files]
if source == "HF":
print(f"Downloading model from HuggingFace: {repo_id} to {model_path}")
snapshot_download_hf(
repo_id,
local_dir=model_path,
local_dir_use_symlinks=False,
allow_patterns=files,
)
else:
print(f"Downloading model from ModelScope: {repo_id} to {model_path}")
snapshot_download_ms(
repo_id,
local_dir=model_path,
allow_patterns=files,
)
return model_path + f"/faster-whisper-{model_size}".replace("whisper-distil", "distil-whisper")
return model_path
@ -106,7 +126,7 @@ def execute_asr(input_folder, output_folder, model_path, language, precision):
)
text = ""
if info.language == "zh":
if info.language in ["zh", "yue"]:
print("检测为中文文本, 转 FunASR 处理")
text = only_asr(file_path, language=info.language.lower())

View File

@ -4,9 +4,8 @@ import argparse
import os
import traceback
# from funasr.utils import version_checker
# version_checker.check_for_update = lambda: None
from funasr import AutoModel
from modelscope import snapshot_download
from tqdm import tqdm
funasr_models = {} # 存储模型避免重复加载
@ -16,40 +15,43 @@ def only_asr(input_file, language):
try:
model = create_model(language)
text = model.generate(input=input_file)[0]["text"]
except:
except Exception:
text = ""
print(traceback.format_exc())
return text
def create_model(language="zh"):
path_vad = "tools/asr/models/speech_fsmn_vad_zh-cn-16k-common-pytorch"
path_punc = "tools/asr/models/punc_ct-transformer_zh-cn-common-vocab272727-pytorch"
path_vad = path_vad if os.path.exists(path_vad) else "iic/speech_fsmn_vad_zh-cn-16k-common-pytorch"
path_punc = path_punc if os.path.exists(path_punc) else "iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch"
vad_model_revision = punc_model_revision = "v2.0.4"
if language == "zh":
path_vad = "tools/asr/models/speech_fsmn_vad_zh-cn-16k-common-pytorch"
path_punc = "tools/asr/models/punc_ct-transformer_zh-cn-common-vocab272727-pytorch"
path_asr = "tools/asr/models/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch"
path_asr = (
path_asr
if os.path.exists(path_asr)
else "iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch"
snapshot_download(
"iic/speech_fsmn_vad_zh-cn-16k-common-pytorch",
local_dir="tools/asr/models/speech_fsmn_vad_zh-cn-16k-common-pytorch",
)
snapshot_download(
"iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch",
local_dir="tools/asr/models/punc_ct-transformer_zh-cn-common-vocab272727-pytorch",
)
snapshot_download(
"iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch",
local_dir="tools/asr/models/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch",
)
model_revision = "v2.0.4"
elif language == "yue":
path_asr = "tools/asr/models/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online"
path_asr = (
path_asr
if os.path.exists(path_asr)
else "iic/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online"
snapshot_download(
"iic/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online",
local_dir="tools/asr/models/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online",
)
model_revision = "master"
path_vad = path_punc = None
vad_model_revision = punc_model_revision = None
###友情提示粤语带VAD识别可能会有少量shape不对报错的但是不带VAD可以.不带vad只能分阶段单独加标点。不过标点模型对粤语效果真的不行…
vad_model_revision = punc_model_revision = ""
model_revision = "master"
else:
raise ValueError("FunASR 不支持该语言" + ": " + language)
raise ValueError(f"{language} is not supported")
vad_model_revision = punc_model_revision = "v2.0.4"
if language in funasr_models:
return funasr_models[language]
@ -83,7 +85,7 @@ def execute_asr(input_folder, output_folder, model_size, language):
file_path = os.path.join(input_folder, file_name)
text = model.generate(input=file_path)[0]["text"]
output.append(f"{file_path}|{output_file_name}|{language.upper()}|{text}")
except:
except Exception:
print(traceback.format_exc())
output_folder = output_folder or "output/asr_opt"

View File

@ -38,7 +38,7 @@
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size: FO hop size, the smaller the value, the higher the accuracy",
"max:归一化后最大值多少": "Loudness multiplier after normalized",
"max_sil_kept:切完后静音最多留多长": "Maximum length for silence to be kept",
"min_interval:最短切割间隔": "Minumum interval for audio cutting",
"min_interval:最短切割间隔": "Minimum interval for audio cutting",
"min_length:每段最小多长,如果第一段太短一直和后面段连起来直到超过这个值": "min_length: the minimum length of each segment. If the first segment is too short, it will be concatenated with the next segment until it exceeds this value",
"temperature": "temperature",
"threshold:音量小于这个值视作静音的备选切割点": "Noise gate threshold (loudness below this value will be treated as noise",
@ -176,7 +176,7 @@
"语音降噪": "Speech Denoising",
"请上传3~10秒内参考音频超过会报错": "Please upload a reference audio within the 3-10 second range; if it exceeds this duration, it will raise errors.",
"请上传参考音频": "Please Upload the Reference Audio",
"请填入推理文本": "Please Fill in the Terget Text",
"请填入推理文本": "Please Fill in the Target Text",
"请填入正确的List路径": "Please Fill in the Correct List Path",
"请填入正确的音频文件夹路径": "Please Fill in the Correct Audio Folder Path",
"请输入有效文本": "Please enter valid text.",

View File

@ -86,7 +86,6 @@ from config import (
from tools import my_utils
from tools.my_utils import check_details, check_for_existance
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
# os.environ['PYTORCH_ENABLE_MPS_FALLBACK'] = '1' # 当遇到mps不支持的步骤时使用cpu
@ -117,8 +116,8 @@ def set_default():
gpu_info = "\n".join(gpu_infos)
if is_gpu_ok:
minmem = min(mem)
default_batch_size = minmem // 2 if version not in v3v4set else minmem // 8
default_batch_size_s1 = minmem // 2
default_batch_size = int(minmem // 2 if version not in v3v4set else minmem // 8)
default_batch_size_s1 = int(minmem // 2)
else:
default_batch_size = default_batch_size_s1 = int(psutil.virtual_memory().total / 1024 / 1024 / 1024 / 4)
if version not in v3v4set:
@ -1980,4 +1979,3 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False, js=js, css=css
server_port=webui_port_main,
# quiet=True,
)

2083
webui_simple.py Normal file

File diff suppressed because it is too large Load Diff