diff --git a/.github/workflows/push_format.yml b/.github/workflows/push_format.yml index f43741b..c4ce77f 100644 --- a/.github/workflows/push_format.yml +++ b/.github/workflows/push_format.yml @@ -5,15 +5,11 @@ on: branches: - main +permissions: + contents: write + pull-requests: write jobs: push_format: - permissions: - actions: write - checks: write - contents: write - issues: write - repository-projects: write - pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/Changelog_CN.md b/Changelog_CN.md index f8b58d6..2e23717 100644 --- a/Changelog_CN.md +++ b/Changelog_CN.md @@ -1,42 +1,23 @@ -20230409 +### 20230409 +- 修正训练参数,提升显卡平均利用率,A100最高从25%提升至90%左右,V100:50%->90%左右,2060S:60%->85%左右,P40:25%->95%左右,训练速度显著提升 +- 修正参数:总batch_size改为每张卡的batch_size +- 修正total_epoch:最大限制100解锁至1000;默认10提升至默认20 +- 修复ckpt提取识别是否带音高错误导致推理异常的问题 +- 修复分布式训练每个rank都保存一次ckpt的问题 +- 特征提取进行nan特征过滤 +- 修复静音输入输出随机辅音or噪声的问题(老版模型需要重做训练集重训) - 1-修正训练参数,提升显卡平均利用率,A100最高从25%提升至90%左右,V100:50%->90%左右,2060S:60%->85%左右,P40:25%->95%左右,训练速度显著提升 - - 2-修正参数:总batch_size改为每张卡的batch_size - - 3-修正total_epoch:最大限制100解锁至1000;默认10提升至默认20 - - 4-修复ckpt提取识别是否带音高错误导致推理异常的问题 - - 5-修复分布式训练每个rank都保存一次ckpt的问题 - - 6-特征提取进行nan特征过滤 - - 7-修复静音输入输出随机辅音or噪声的问题(老版模型需要重做训练集重训) - -20230416更新 - - 1-新增本地实时变声迷你GUI,双击go-realtime-gui.bat启动 - - 2-训练推理均对<50Hz的频段进行滤波过滤 - - 3-训练推理音高提取pyworld最低音高从默认80下降至50,50-80hz间的男声低音不会哑 - - 4-WebUI支持根据系统区域变更语言(现支持en_US,ja_JP,zh_CN,zh_HK,zh_SG,zh_TW,不支持的默认en_US) - - 5-修正部分显卡识别(例如V100-16G识别失败,P4识别失败) - -后续计划: - - 1-收集呼吸wav加入训练集修正呼吸变声电音的问题 - - 2-研究更优的默认faiss索引配置,计划将索引打包进weights/xxx.pth中,取消推理界面的 特征/检索库 选择 - - 3-根据显存情况和显卡架构自动给到最优配置(batch size,训练集切块,推理音频长度相关的config,训练是否fp16),未来所有>=4G显存的>=pascal架构的显卡都可以训练或推理,而<4G显存的显卡不会进行支持 - - 4-我们正在训练增加了歌声训练集的底模,未来会公开 - - 5-推理音高识别选项加入"是否开启中值滤波" - - 6-增加选项:每次epoch保存的小模型均进行提取; 增加选项:设置默认测试集音频,每次保存的小模型均在保存后对其进行推理导出,用户可试听(来选择哪个中间epoch最好) +### 20230416更新 +- 新增本地实时变声迷你GUI,双击go-realtime-gui.bat启动 +- 训练推理均对<50Hz的频段进行滤波过滤 +- 训练推理音高提取pyworld最低音高从默认80下降至50,50-80hz间的男声低音不会哑 +- WebUI支持根据系统区域变更语言(现支持en_US,ja_JP,zh_CN,zh_HK,zh_SG,zh_TW,不支持的默认en_US) +- 修正部分显卡识别(例如V100-16G识别失败,P4识别失败) +### 后续计划: +- 收集呼吸wav加入训练集修正呼吸变声电音的问题 +- 研究更优的默认faiss索引配置,计划将索引打包进weights/xxx.pth中,取消推理界面的 特征/检索库 选择 +- 根据显存情况和显卡架构自动给到最优配置(batch size,训练集切块,推理音频长度相关的config,训练是否fp16),未来所有>=4G显存的>=pascal架构的显卡都可以训练或推理,而<4G显存的显卡不会进行支持 +- 我们正在训练增加了歌声训练集的底模,未来会公开 +- 推理音高识别选项加入"是否开启中值滤波" +- 增加选项:每次epoch保存的小模型均进行提取; 增加选项:设置默认测试集音频,每次保存的小模型均在保存后对其进行推理导出,用户可试听(来选择哪个中间epoch最好) diff --git a/extract_locale.py b/extract_locale.py index 546335b..c42bda5 100644 --- a/extract_locale.py +++ b/extract_locale.py @@ -28,3 +28,4 @@ process("gui.py") # Save as a JSON file with open("./i18n/zh_CN.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=4) + f.write("\n") diff --git a/gui.py b/gui.py index 24fcf1e..9aee2e9 100644 --- a/gui.py +++ b/gui.py @@ -1,4 +1,5 @@ -import os,sys +import os, sys + now_dir = os.getcwd() sys.path.append(now_dir) import PySimpleGUI as sg @@ -15,7 +16,6 @@ from infer_pack.models import SynthesizerTrnMs256NSFsid, SynthesizerTrnMs256NSFs from i18n import I18nAuto i18n = I18nAuto() -print(i18n.language_map) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -32,10 +32,11 @@ class RVC: self.f0_max = 1100 self.f0_mel_min = 1127 * np.log(1 + self.f0_min / 700) self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700) - self.index = faiss.read_index(index_path) + if index_rate != 0: + self.index = faiss.read_index(index_path) + self.big_npy = np.load(npy_path) + print("index search enabled") self.index_rate = index_rate - """NOT YET USED""" - self.big_npy = np.load(npy_path) model_path = hubert_path print("load model(s) from {}".format(model_path)) models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task( @@ -110,11 +111,7 @@ class RVC: feats = self.model.final_proj(logits[0]) ####索引优化 - if ( - isinstance(self.index, type(None)) == False - and isinstance(self.big_npy, type(None)) == False - and self.index_rate != 0 - ): + if hasattr(self, "index") and hasattr(self, "big_npy") and self.index_rate != 0: npy = feats[0].cpu().numpy().astype("float32") _, I = self.index.search(npy, 1) npy = self.big_npy[I.squeeze()].astype("float16") @@ -122,6 +119,8 @@ class RVC: torch.from_numpy(npy).unsqueeze(0).to(device) * self.index_rate + (1 - self.index_rate) * feats ) + else: + print("index search FAIL or disabled") feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1) torch.cuda.synchronize() diff --git a/i18n/ja_JP.json b/i18n/ja_JP.json index 270f464..ddc362f 100644 --- a/i18n/ja_JP.json +++ b/i18n/ja_JP.json @@ -11,17 +11,17 @@ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "ピッチ抽出アルゴリズムを選択してください。歌声の場合は、pmを使用して速度を上げることができます。低音が重要な場合は、harvestを使用できますが、非常に遅くなります。", "特征检索库文件路径": "特徴量検索データベースのファイルパス", "特征文件路径": "特徴量ファイルのパス", - "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调", + "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0(最低共振周波数)カーブファイル(オプション、1行に1ピッチ、デフォルトのF0(最低共振周波数)とエレベーションを置き換えます。)", "转换": "変換", "输出信息": "出力情報", "输出音频(右下角三个点,点了可以下载)": "出力音声(右下の三点をクリックしてダウンロードできます)", - "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ", + "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "一括変換、変換する音声フォルダを入力、または複数の音声ファイルをアップロードし、指定したフォルダ(デフォルトのopt)に変換した音声を出力します。", "指定输出文件夹": "出力フォルダを指定してください", "检索特征占比": "検索特徴率", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "処理対象音声フォルダーのパスを入力してください(ファイルマネージャのアドレスバーからコピーしてください)", "也可批量输入音频文件, 二选一, 优先读文件夹": "複数の音声ファイルを一括で入力することもできますが、フォルダーを優先して読み込みます", "伴奏人声分离": "伴奏とボーカルの分離", - "人声伴奏分离批量处理, 使用UVR5模型.
不带和声用HP2, 带和声且提取的人声不需要和声用HP5
合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人声伴奏分离批量处理, 使用UVR5模型.
不带和声用HP2, 带和声且提取的人声不需要和声用HP5
合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)", + "人声伴奏分离批量处理, 使用UVR5模型.
不带和声用HP2, 带和声且提取的人声不需要和声用HP5
合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "UVR5モデルを使用した、声帯分離バッチ処理です。
HP2はハーモニー、ハーモニーのあるボーカルとハーモニーのないボーカルを抽出したものはHP5を使ってください
フォルダーパスの形式例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(エクスプローラーのアドレスバーからコピーするだけです)", "输入待处理音频文件夹路径": "処理するオーディオファイルのフォルダパスを入力してください", "模型": "モデル", "指定输出人声文件夹": "人の声を出力するフォルダを指定してください", @@ -60,7 +60,7 @@ "要置入的模型信息": "挿入するモデル情報", "保存的模型名不带后缀": "拡張子のない保存するモデル名", "融合": "フュージョン", - "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型信息(仅支持weights文件夹下提取的小模型文件)", + "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "モデル情報の修正(weightsフォルダから抽出された小さなモデルファイルのみ対応)", "模型路径": "モデルパス", "要改的模型信息": "変更するモデル情報", "保存的文件名, 默认空为和源文件同名": "保存するファイル名、デフォルトでは空欄で元のファイル名と同じ名前になります", @@ -68,18 +68,18 @@ "查看模型信息(仅支持weights文件夹下提取的小模型文件)": "モデル情報を表示する(小さいモデルファイルはweightsフォルダーからのみサポートされています)", "查看": "表示", "模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "モデル抽出(ログフォルダー内の大きなファイルのモデルパスを入力)、モデルを半分までトレーニングし、自動的に小さいファイルモデルを保存しなかったり、中間モデルをテストしたい場合に適用されます。", - "保存名": "保存するファイル名", + "保存名": "保存ファイル名", "模型是否带音高指导,1是0否": "モデルに音高ガイドを付けるかどうか、1は付ける、0は付けない", "提取": "抽出", "招募音高曲线前端编辑器": "音高曲線フロントエンドエディターを募集", "加开发群联系我xxxxx": "開発グループに参加して私に連絡してくださいxxxxx", "点击查看交流、问题反馈群号": "クリックして交流、問題フィードバックグループ番号を表示", "xxxxx": "xxxxx", - "加载模型": "モデルをロードする", + "加载模型": "モデルをロード", "Hubert模型": "Hubert模型", - "选择.pth文件": ".pthファイルを選択する", - "选择.index文件": ".indexファイルを選択する", - "选择.npy文件": ".npyファイルを選択する", + "选择.pth文件": ".pthファイルを選択", + "选择.index文件": ".indexファイルを選択", + "选择.npy文件": ".npyファイルを選択", "输入设备": "入力デバイス", "输出设备": "出力デバイス", "音频设备(请使用同种类驱动)": "オーディオデバイス(同じ種類のドライバーを使用してください)", @@ -93,7 +93,7 @@ "输入降噪": "入力ノイズの低減", "输出降噪": "出力ノイズの低減", "性能设置": "パフォーマンス設定", - "开始音频转换": "音声変換を開始する", - "停止音频转换": "音声変換を停止する", + "开始音频转换": "音声変換を開始", + "停止音频转换": "音声変換を停止", "推理时间(ms):": "推論時間(ms):" -} \ No newline at end of file +} diff --git a/i18n/locale_diff.py b/i18n/locale_diff.py index 6419266..2572779 100644 --- a/i18n/locale_diff.py +++ b/i18n/locale_diff.py @@ -42,3 +42,4 @@ for lang_file in languages: # Save the updated language file with open(lang_file, "w", encoding="utf-8") as f: json.dump(lang_data, f, ensure_ascii=False, indent=4) + f.write("\n") diff --git a/i18n/zh_CN.json b/i18n/zh_CN.json index d5d744d..5e4f918 100644 --- a/i18n/zh_CN.json +++ b/i18n/zh_CN.json @@ -96,4 +96,4 @@ "开始音频转换": "开始音频转换", "停止音频转换": "停止音频转换", "推理时间(ms):": "推理时间(ms):" -} \ No newline at end of file +} diff --git a/i18n/zh_HK.json b/i18n/zh_HK.json index 338f05f..4b47d95 100644 --- a/i18n/zh_HK.json +++ b/i18n/zh_HK.json @@ -96,4 +96,4 @@ "开始音频转换": "開始音訊轉換", "停止音频转换": "停止音訊轉換", "推理时间(ms):": "推理時間(ms):" -} \ No newline at end of file +} diff --git a/i18n/zh_SG.json b/i18n/zh_SG.json index 338f05f..4b47d95 100644 --- a/i18n/zh_SG.json +++ b/i18n/zh_SG.json @@ -96,4 +96,4 @@ "开始音频转换": "開始音訊轉換", "停止音频转换": "停止音訊轉換", "推理时间(ms):": "推理時間(ms):" -} \ No newline at end of file +} diff --git a/i18n/zh_TW.json b/i18n/zh_TW.json index 338f05f..4b47d95 100644 --- a/i18n/zh_TW.json +++ b/i18n/zh_TW.json @@ -96,4 +96,4 @@ "开始音频转换": "開始音訊轉換", "停止音频转换": "停止音訊轉換", "推理时间(ms):": "推理時間(ms):" -} \ No newline at end of file +} diff --git a/infer-web.py b/infer-web.py index 00d55b2..b027f0e 100644 --- a/infer-web.py +++ b/infer-web.py @@ -139,8 +139,17 @@ def vc_single( if hubert_model == None: load_hubert() if_f0 = cpt.get("f0", 1) - file_index = file_index.strip(" ").strip('"').strip("\n").strip('"').strip(" ").replace("trained","added")#防止小白写错,自动帮他替换掉 - file_big_npy = file_big_npy.strip(" ").strip('"').strip("\n").strip('"').strip(" ") + file_index = ( + file_index.strip(" ") + .strip('"') + .strip("\n") + .strip('"') + .strip(" ") + .replace("trained", "added") + ) # 防止小白写错,自动帮他替换掉 + file_big_npy = ( + file_big_npy.strip(" ").strip('"').strip("\n").strip('"').strip(" ") + ) audio_opt = vc.pipeline( hubert_model, net_g, diff --git a/requirements.txt b/requirements.txt index e00ebda..9b03196 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,8 @@ scipy==1.9.3 librosa==0.9.2 llvmlite==0.39.0 fairseq==0.12.2 -faiss-cpu==1.7.2 +faiss-cpu==1.7.0; sys_platform == "darwin" +faiss-cpu==1.7.2; sys_platform != "darwin" gradio Cython future>=0.18.3 diff --git a/trainset_preprocess_pipeline_print.py b/trainset_preprocess_pipeline_print.py index a771c0e..7b5833a 100644 --- a/trainset_preprocess_pipeline_print.py +++ b/trainset_preprocess_pipeline_print.py @@ -39,7 +39,7 @@ class PreProcess: max_sil_kept=150, ) self.sr = sr - self.bh, self.ah = signal.butter(N=5, Wn=48, btype='high', fs=self.sr) + self.bh, self.ah = signal.butter(N=5, Wn=48, btype="high", fs=self.sr) self.per = 3.7 self.overlap = 0.3 self.tail = self.per + self.overlap diff --git a/vc_infer_pipeline.py b/vc_infer_pipeline.py index 1fa41d1..f85f355 100644 --- a/vc_infer_pipeline.py +++ b/vc_infer_pipeline.py @@ -5,7 +5,9 @@ from config import x_pad, x_query, x_center, x_max import scipy.signal as signal import pyworld, os, traceback, faiss from scipy import signal -bh, ah = signal.butter(N=5, Wn=48, btype='high', fs=16000) + +bh, ah = signal.butter(N=5, Wn=48, btype="high", fs=16000) + class VC(object): def __init__(self, tgt_sr, device, is_half):