188 Commits

Author SHA1 Message Date
RVC-Boss
c1ace168fa Update Changelog_EN.md 2023-06-18 14:16:08 +00:00
RVC-Boss
41c345557f Update Changelog_CN.md 2023-06-18 14:06:25 +00:00
RVC-Boss
7fbfc60fcb Update Changelog_CN.md 2023-06-18 14:05:24 +00:00
github-actions[bot]
e4417ce82f Format code (#564)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-18 13:55:51 +00:00
RVC-Boss
125a0a7b02 change default train version to v2
change default train version to v2
2023-06-18 13:52:49 +00:00
RVC-Boss
a42330f0ae Add files via upload 2023-06-18 21:49:49 +08:00
RVC-Boss
bc5df2ff8e Add files via upload 2023-06-18 20:05:43 +08:00
RVC-Boss
0812020c90 Add files via upload 2023-06-18 19:37:53 +08:00
RVC-Boss
66667c8f50 Add files via upload 2023-06-18 19:37:21 +08:00
github-actions[bot]
a7647e4094 Format code (#526)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-18 10:39:56 +00:00
RVC-Boss
f92a923487 Update infer-web.py 2023-06-18 09:56:29 +00:00
RVC-Boss
0db402c312 Update infer-web.py 2023-06-18 09:56:16 +00:00
RVC-Boss
6ca9c853b0 v2-48k-32k-support
v2-48k-32k-support
2023-06-18 17:40:07 +08:00
RVC-Boss
44426b18b8 train index:auto kmeans when feature shape too large
train index:auto kmeans when feature shape too large
2023-06-18 16:19:07 +08:00
RVC-Boss
e7f204b32e train index:auto kmeans when feature shape too large
train index:auto kmeans when feature shape too large
2023-06-18 16:16:33 +08:00
Ftps
75264d09b6 Fix format #526 (#533)
* Fix format #526

* fix return
2023-06-18 08:01:34 +00:00
RVC-Boss
cbd29350fe extreme value filtering 2023-06-18 15:30:56 +08:00
RVC-Boss
a9a77f2556 fix-no-f0-model-protect-issue
fix-no-f0-model-protect-issue
2023-06-18 15:17:36 +08:00
RVC-Boss
ec0c39d9bc Update infer-web.py 2023-06-18 06:56:22 +00:00
Ftps
9253948f0d Rewrite syntax of infer-web.py (#536)
* Fix import location

* use any

* Correction of if Syntax

* Class definitions to the front

* format

* fix if Syntax
2023-06-18 06:42:40 +00:00
LINKANG ZHAN
c5758a89db Stop extracting features when hubert_base.pt does not exist. (#535)
* support detection of pretrained model, support train without pretrained model path in web ui

* support detection of pretrained model, support train without pretrained model path in web ui

* support detection of pretrained model, support train without pretrained model path in web ui

* Stop extracting features when hubert_base.pt is not exist.

* Stop extracting features when hubert_base.pt is not exist.

* Make error more noticeable
2023-06-18 04:39:10 +00:00
lliiooll
28383fbeee 进行一些判断操作避免崩溃 (#562) 2023-06-18 04:38:35 +00:00
RVC-Boss
846be17351 Update Retrieval_based_Voice_Conversion_WebUI_v2.ipynb 2023-06-18 04:09:06 +00:00
RVC-Boss
4945fba0a3 Update Retrieval_based_Voice_Conversion_WebUI.ipynb 2023-06-18 04:08:57 +00:00
RVC-Boss
602ee19cf9 Update requirements.txt 2023-06-18 04:08:28 +00:00
Ναρουσέ·μ·γιουμεμί·Χινακάννα
0eb6bb67be Onnx推理dml支持 (#556)
* Add files via upload

* Add files via upload
2023-06-17 14:49:16 +00:00
RVC-Boss
a071f1e089 fix v2 onnx export 2023-06-15 15:29:05 +00:00
RVC-Boss
147d3c83b7 fix v2 onnx export 2023-06-15 15:27:51 +00:00
RVC-Boss
75d7c03d41 fix v2 onnx export 2023-06-15 15:26:57 +00:00
LINKANG ZHAN
f349adc9df Add support for train without specify pretrained model, add support for selecting v2 48k as training setting, and add support for auto remove pretrained model when the user do not have pretrained model in designate folder. (#528)
* support detection of pretrained model, support train without pretrained model path in web ui

* support detection of pretrained model, support train without pretrained model path in web ui

* support detection of pretrained model, support train without pretrained model path in web ui
2023-06-15 10:21:58 +08:00
github-actions[bot]
eb1a88cf7e Format code (#522)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-14 11:48:05 +00:00
红血球AE3803
4de5d0d551 更新批量推理脚本,可以不用 webui (#518)
* 增加批量推理脚本

* 更新批量推理脚本
2023-06-14 10:22:47 +08:00
RVC-Boss
c74727d487 Update Changelog_CN.md 2023-06-13 16:22:17 +08:00
RVC-Boss
78c88a4f75 add vocal2guitar online demo 2023-06-11 13:59:16 +00:00
RVC-Boss
d963c29fec Update README.md 2023-06-11 13:56:06 +00:00
RVC-Boss
986d92b261 Update README.md 2023-06-11 13:54:38 +00:00
André Thieme
e1f084177d Replace deprecated Numpy function np.int. (#434)
It’s an alias for just `int` and it’s being deprecated:
https://numpy.org/devdocs/release/1.20.0-notes.html

Co-authored-by: Ftps <63702646+Tps-F@users.noreply.github.com>
2023-06-10 14:55:34 +00:00
niizam
fcce61b27f Update train_nsf_sim_cache_sid_load_pretrain.py (#497) 2023-06-10 14:54:53 +00:00
Ftps
ff2793249d remove specify version (#492) 2023-06-09 15:05:13 +00:00
ms903x1
ec83e10b8f Update gui.py default config (#482)
* Update envfilescheck.bat

add pretrained_v2 and uvr5 update

* Update envfilescheck.bat

fix bug

* Update envfilescheck.bat

fix bug

* Update data_utils.py

fix bug where data exceeding 4s is filtered out.

* Update gui.py

Update default config

* Update gui.py

fix json bug
2023-06-08 13:29:34 +00:00
github-actions[bot]
fada942ecd Format code (#456)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-08 16:55:18 +08:00
yuuukiasuna
1b307a4222 gui json update (#479)
* Fix gui.py

There seemed to be some conflicts between #338 and #340, so I corrected them.

* Update gui.py

* Update gui.py

---------

Co-authored-by: Ftps <63702646+Tps-F@users.noreply.github.com>
Co-authored-by: RVC-Boss <129054828+RVC-Boss@users.noreply.github.com>
2023-06-08 16:53:51 +08:00
mrhan1993
b28f98fed3 Update gui.py (#475)
增加选择模型时的默认路径以及文件过滤。
2023-06-08 10:42:16 +08:00
Dennis Heckmann
297809bdfd Fixed NameError coming from a typo. (#458) 2023-06-07 10:12:06 +08:00
RVC-Boss
692c245fad Update infer-web.py 2023-06-06 14:37:12 +00:00
github-actions[bot]
52c97ed464 Format code (#455)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-06 14:35:35 +00:00
RVC-Boss
6f1bc7d683 Add files via upload 2023-06-06 22:32:32 +08:00
RVC-Boss
9ff976b155 Add files via upload 2023-06-06 22:32:10 +08:00
RVC-Boss
f358fe7242 Update requirements.txt 2023-06-06 13:20:45 +00:00
RVC-Boss
05b5af7c8c Add files via upload 2023-06-06 20:34:54 +08:00
KakaruHayate
b7337d7bf1 Update Retrieval_based_Voice_Conversion_WebUI_v2.ipynb (#448) 2023-06-06 12:14:04 +00:00
github-actions[bot]
99404baf94 Format code (#409)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-03 08:22:46 +00:00
YuriHead
a94c8e3a69 Updata Online Infer (#419) 2023-06-03 08:18:42 +00:00
RVC-Boss
bf11700125 fix m1/m2 user training 2023-06-03 07:08:35 +00:00
Rice Cake
95cd1759c5 fix python dependency problem (#418) 2023-06-03 07:00:50 +00:00
ms903x1
80929e472e Update data_utils.py (#407)
* Update envfilescheck.bat

add pretrained_v2 and uvr5 update

* Update envfilescheck.bat

fix bug

* Update envfilescheck.bat

fix bug

* Update data_utils.py

fix bug where data exceeding 4s is filtered out.
2023-06-02 10:27:20 +08:00
Ma5onic
a02019e428 English Translation Fixes (#402)
* Fix English Translations

* Minor translation correction
2023-06-01 10:11:38 +08:00
RVC-Boss
4c28652ed9 Update requirements.txt 2023-06-01 10:01:00 +08:00
RVC-Boss
c2f402d7d1 Update requirements.txt 2023-05-30 16:50:05 +00:00
RVC-Boss
a68037be3c Update gui.py 2023-05-30 13:17:10 +00:00
dependabot[bot]
fa97c3f8bd Bump starlette from 0.26.1 to 0.27.0 (#390) 2023-05-30 08:09:34 +00:00
github-actions[bot]
89afd017ba Format code (#384)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-30 15:22:53 +08:00
Pengoose
5284e38c3d Update Changelog_KO.md (#381) 2023-05-30 08:35:12 +09:00
Ναρουσέ·μ·γιουμεμί·Χινακάννα
24f2ad44ea Add files via upload (#379) 2023-05-29 15:52:23 +00:00
HalfMAI
69071119a9 Update infer-web.py (#374)
修复 刷新按钮没有更新 批处理区的 索引路径的问题
2023-05-29 18:26:59 +08:00
github-actions[bot]
86b086e393 🎨 同步 locale (#367)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-29 12:09:26 +08:00
RVC-Boss
95a14b734d Add files via upload 2023-05-29 00:23:09 +08:00
ms903x1
f0a798c53f undate envfilescheck.bat (#368)
* Update envfilescheck.bat

add pretrained_v2 and uvr5 update

* Update envfilescheck.bat

fix bug

* Update envfilescheck.bat

fix bug
2023-05-28 16:21:50 +00:00
github-actions[bot]
e435b3bb8a Format code (#366)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-28 16:06:11 +00:00
RVC-Boss
e569477457 Update Changelog_EN.md 2023-05-28 15:58:23 +00:00
RVC-Boss
d0249262b3 Add files via upload 2023-05-28 23:51:03 +08:00
RVC-Boss
0841d1341b Update Changelog_CN.md 2023-05-28 15:50:59 +00:00
RVC-Boss
7bd25c4623 Add files via upload 2023-05-28 23:40:54 +08:00
RVC-Boss
e8d92c3e91 Update Changelog_CN.md 2023-05-28 15:11:30 +00:00
RVC-Boss
619e9060aa Update requirements.txt 2023-05-28 15:06:43 +00:00
RVC-Boss
35aa864daa Update requirements.txt 2023-05-28 15:04:10 +00:00
RVC-Boss
e53118c60f Add files via upload 2023-05-28 23:00:51 +08:00
RVC-Boss
c93940a25d Add files via upload 2023-05-28 23:00:29 +08:00
RVC-Boss
f1730d42d4 Add files via upload 2023-05-28 22:58:33 +08:00
Ftps
7789c46ded Fix gui.py (#365)
There seemed to be some conflicts between #338 and #340, so I corrected them.
2023-05-28 12:52:05 +00:00
Rice Cake
4b0c86fbeb add project name to index file's name (#357)
* Add files via upload

* Apply Code Formatter Change

---------

Co-authored-by: gak123 <gak123@users.noreply.github.com>
Co-authored-by: Ftps <63702646+Tps-F@users.noreply.github.com>
2023-05-28 12:25:36 +08:00
dependabot[bot]
2280f3e392 Bump tornado from 6.2 to 6.3.2 (#358)
* Bump tornado from 6.2 to 6.3.2

Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.2 to 6.3.2.
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.2.0...v6.3.2)

---
updated-dependencies:
- dependency-name: tornado
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Apply Code Formatter Change

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ftps <63702646+Tps-F@users.noreply.github.com>
2023-05-28 00:36:12 +09:00
Pengoose
7816761bee Add Korean CHANGELOG (#359) 2023-05-28 00:04:31 +09:00
Ftps
a2ef4cca76 fix Config, GUIConfig and self (#340)
Co-authored-by: RVC-Boss <129054828+RVC-Boss@users.noreply.github.com>
2023-05-26 19:32:19 +08:00
fluo10
0729c9d6f2 Exclude python3.11 from dependencies (#352) 2023-05-26 19:28:32 +08:00
JackEllie
039e7afb85 Update gui.py (#338) 2023-05-25 09:27:40 +09:00
RVC-Boss
e0813eb282 Update train_nsf_sim_cache_sid_load_pretrain.py 2023-05-24 12:27:15 +00:00
Rice Cake
8efb101401 upload RVC v2 index training script (#343)
* Add files via upload

* Apply Code Formatter Change

---------

Co-authored-by: gak123 <gak123@users.noreply.github.com>
2023-05-24 12:26:35 +00:00
dependabot[bot]
a4c86a3aa1 Bump requests from 2.28.2 to 2.31.0 (#339)
Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.2...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 22:51:51 +08:00
Yugo Ogura
9cee20f402 feat: ipynb for v2 (#332) 2023-05-23 12:58:05 +08:00
github-actions[bot]
cfd9848128 Format code (#330)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-21 19:19:53 +08:00
Ναρουσέ·μ·γιουμεμί·Χινακάννα
067731db9b 768VecOnnxExport (#328)
* Delete export_onnx.py

* Delete export_onnx_old.py

* Delete models_onnx_moess.py

* Support 768 Vec

* Add files via upload

* Support 768 Vec

Support 768 Vec

* Support 768 Vec Onnx Export

Support 768 Vec Onnx Export
2023-05-21 19:11:29 +08:00
pcunwa
c3de24f2e0 Corrected Japanese translation. (#319)
* Update ja_JP.json

Incorrect or incomplete translations have been corrected.

* Update ja_JP.json

---------

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2023-05-21 11:06:11 +00:00
RVC-Boss
f6e55485d9 Update gui.py 2023-05-21 07:01:34 +00:00
RVC-Boss
615c30c17b Update gui.py 2023-05-21 06:57:16 +00:00
RVC-Boss
79a79c3b99 Update config.py 2023-05-21 03:30:27 +00:00
RVC-Boss
28948f8961 Update infer-web.py 2023-05-21 03:10:20 +00:00
RVC-Boss
19cc9062b0 Update i18n.py 2023-05-21 03:10:07 +00:00
tzshao
50a121fc74 Update of en_US.json and faq_en.md. Proposal for i18n standard. (#318)
* Update en_US.json

1. Severe mistake fixed: certain translation is previously incomplete.

* Update faq_en.md

1. Modified 1 entry for context consistency with lately merged en_US translation

* Update en_US.json

1. Attached colons to all Input Prompts as proposed.
2. Minor changes to translation expressions.

* Update en_US.json

1. Removed trailing periods on button texts
2023-05-20 20:14:23 +08:00
Rilm2525
3f17356c11 Japanese translation added and corrected. (#317)
* Update infer-web.py

* Update ja_JP.json
2023-05-20 10:46:39 +00:00
tzshao
563bf7af6d Update of en_US.json, Proposal for i18n standard. (#314)
* Update en_US.json

### Description:
A rough modification of en-US i18n file.

### Changes:
+ Many translation phrases have been replaced with rather native expressions.
+ Majority of translation phrases have been re-formatted for more efficient reading.

### Problems:
+ There's no standard for i18n. E.g, and my proposal:
	+ All Input Prompts ends with colon(":").
	+ All progress indication(e.g. "step1:processing data","step2a: ...") stays lowercase, may add CSI SGR escape sequences for highlighting.
	+ List of Selections and their descriptions be written in key-value pairs.
+ No more plain-translations.

* Update en_US.json

1.Strings that refer to specific paths/locations have been quoted with '' pairs.
2.1 Typo fixed.

* Update en_US.json

1.Minor re-format.
2023-05-20 10:46:18 +00:00
github-actions[bot]
41d2d72f39 Format code (#310)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-19 20:48:17 +08:00
N. Hiroto
080b7cdc31 bugfix: leaked semaphore error (#309)
* use config for n_cpu

* rm import

* fix process loop

* unuse mp.spawn

ref. https://discuss.pytorch.org/t/how-to-fix-a-sigsegv-in-pytorch-when-using-distributed-training-e-g-ddp/113518/10

* fix commentout
2023-05-19 17:56:06 +08:00
kalomaze
563c64ded9 Small english translation tweaks (#308)
* Update en_US.json

* Update en_US.json
2023-05-19 11:32:50 +08:00
github-actions[bot]
0fbfa1d62b Format code (#307)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-18 18:54:41 +08:00
Cole Mangio
c2039b6eca Fixed index version not being written to the index file on train_index() in infer-web.py (#305) 2023-05-18 10:02:12 +00:00
github-actions[bot]
aadf7443c3 Format code (#304)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-18 13:18:02 +08:00
RVC-Boss
6fb1f8c1b1 Update process_ckpt.py 2023-05-17 15:39:24 +00:00
源文雨
e5374b2041 Revert "fix: merge f0 option value (#298)" (#303)
This reverts commit da0b599fa7.
2023-05-17 23:17:01 +08:00
dependabot[bot]
30c7e417e8 Bump pillow from 9.1.1 to 9.3.0 (#300)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.1.1 to 9.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/9.1.1...9.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-17 14:12:22 +08:00
Yugo Ogura
da0b599fa7 fix: merge f0 option value (#298)
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2023-05-17 05:38:21 +00:00
源文雨
2ec95ab288 fix unitest 2023-05-17 13:32:25 +08:00
github-actions[bot]
5bf26dadca Format code (#296)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-17 00:02:26 +08:00
Xerxes-2
0b0bd911d9 Add timestamp and elapsed time for epoch (#273)
* add timestamp and epoch elapsed time

* don't need a class

* Revert "add timestamp and epoch elapsed time"

This reverts commit 93b8d4a7af.

* adjust class def

* delete duplicate import

---------

Co-authored-by: Ftps <63702646+Tps-F@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2023-05-16 23:54:35 +08:00
R0w9h
8a9909bdd1 Update ja_JP.json (#293) 2023-05-16 10:24:45 +08:00
RVC-Boss
9d949118c0 Update en_US.json 2023-05-15 15:21:58 +00:00
RVC-Boss
1c01099dbc Update requirements.txt 2023-05-15 14:42:15 +00:00
源文雨
b07dedd744 fix workflow (#284)
* Update extract_feature_print.py

* Update unitest.yml
2023-05-15 13:11:01 +08:00
github-actions[bot]
137447bdc9 🎨 同步 locale (#283)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 08:30:20 +00:00
RVC-Boss
f4c2a63a5e Add files via upload 2023-05-14 16:26:33 +08:00
RVC-Boss
2d845e5222 Add files via upload 2023-05-14 16:08:37 +08:00
github-actions[bot]
e06994f473 🎨 同步 locale (#281)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 08:00:48 +00:00
github-actions[bot]
6a3eaef090 Format code (#275)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-14 07:52:36 +00:00
RVC-Boss
32437314b8 Update Changelog_EN.md 2023-05-14 07:50:54 +00:00
RVC-Boss
ac807575ad Update Changelog_CN.md 2023-05-14 07:44:03 +00:00
RVC-Boss
b42f4bf6df Update README.en.md 2023-05-14 07:21:30 +00:00
RVC-Boss
1f63abe3e2 Update README.md 2023-05-14 07:19:35 +00:00
RVC-Boss
bbc3bcba3b Create .gitignore 2023-05-14 07:16:47 +00:00
RVC-Boss
60919b9b02 Update Changelog_CN.md 2023-05-14 07:16:06 +00:00
RVC-Boss
77ff5b08b6 Add files via upload 2023-05-14 15:07:12 +08:00
RVC-Boss
404ce9338f Add files via upload 2023-05-14 15:06:50 +08:00
RVC-Boss
3b5a2298d7 Add files via upload 2023-05-14 15:05:42 +08:00
RVC-Boss
3909ce4a7b Add files via upload 2023-05-13 03:49:38 +08:00
RVC-Boss
0d2212c8ea Add files via upload 2023-05-13 03:47:56 +08:00
github-actions[bot]
af41184320 Format code (#274)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-12 19:43:05 +00:00
RVC-Boss
568378761b Update Changelog_CN.md 2023-05-12 19:41:06 +00:00
RVC-Boss
44449efc2e Add files via upload 2023-05-13 03:29:30 +08:00
github-actions[bot]
0bc1ea782e Format code (#270)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-12 19:27:59 +00:00
Ftps
3d8d0957e4 remove Unnecessary elif (#259) 2023-05-12 19:27:44 +00:00
RVC-Boss
ef016ae6a0 Update gui.py 2023-05-11 14:29:56 +00:00
RVC-Boss
c84371844a default sr->40k is the best; unload weight debug []->""
default sr->40k is the best; unload weight debug []->""
2023-05-11 03:07:02 +08:00
源文雨
339a116074 Update README.md 2023-05-10 23:39:04 +08:00
github-actions[bot]
2f8179fa32 🎨 同步 locale (#266)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-10 23:36:36 +08:00
Sebastian Gabriel Savu
2086a7dab4 [maintenance] change f0 choice to boolean instead of string yes/no + default sample rate for training to 48k (#265) 2023-05-10 23:30:19 +08:00
源文雨
9bab76741e Update README.md 2023-05-10 23:27:33 +08:00
Ftps
769cf352a0 update faiss (#261) 2023-05-10 23:24:03 +08:00
RVC-Boss
c7f6a181a0 Update config.py 2023-05-10 13:19:09 +00:00
Ftps
6cc2279fb9 Support mps generate (#263) 2023-05-10 13:17:13 +00:00
RVC-Boss
5b0ff12163 Update README.md 2023-05-09 11:49:05 +08:00
RVC-Boss
1782a6332e Update requirements.txt 2023-05-08 15:40:06 +00:00
RVC-Boss
28dd13420c Update requirements.txt 2023-05-08 15:34:45 +00:00
github-actions[bot]
75d31f1022 Format code (#254)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-08 15:16:19 +00:00
liu biao
eba9b05b28 增加在macos下安装swig说明 (#253) 2023-05-08 15:16:09 +00:00
RVC-Boss
2c4ec6db93 Update trainset_preprocess_pipeline_print.py 2023-05-08 15:04:21 +00:00
RVC-Boss
4a2c9c062f Update gui.py 2023-05-07 17:42:30 +00:00
RVC-Boss
5928d5358c Update gui.py 2023-05-07 17:40:09 +00:00
Scott
f695fe60f6 Add English CHANGELOG (#243) 2023-05-07 16:24:13 +00:00
源文雨
5d7b649175 Update README.md 2023-05-07 13:46:23 +08:00
源文雨
73992be783 增加发行时自动构建docker镜像 2023-05-07 13:43:27 +08:00
Sebastian Gabriel Savu
d43c1d3cdd add ability to containerize with Docker (add Dockerfile) (#240)
Co-authored-by: Sebastian Savu <sebastian.savu@bidfx.com>
2023-05-07 13:32:16 +08:00
github-actions[bot]
b5b9af0255 🎨 同步 locale (#239)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-07 13:30:57 +08:00
RVC-Boss
aabbcb70c1 Update README.en.md 2023-05-06 18:42:08 +08:00
RVC-Boss
ddec7b713f Update README.md 2023-05-06 18:40:42 +08:00
R0w9h
e76654e634 Update ja_JP.json (#238) 2023-05-06 10:45:39 +09:00
github-actions[bot]
eb7caaa064 Format code (#228)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-06 00:14:11 +08:00
Ftps
e3cb0485ce staticmethod (#232) 2023-05-06 00:13:27 +08:00
Sebastian Gabriel Savu
4abd0bd680 [maintenance] cleanup one click training and related (#219)
- remove unused imports
- remove unused gpus6 param from train1key fn
- improve readability and reusability for various pathing strings
 main
2023-05-05 23:48:39 +08:00
github-actions[bot]
4027928a8e Format code (#227)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-05 14:18:51 +08:00
RVC-Boss
15519de5e5 Update i18n.py 2023-05-05 14:14:31 +08:00
github-actions[bot]
6726af00cf Format code (#221)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-05 13:13:41 +08:00
RVC-Boss
ccf6e6bbd2 batch_add_faiss_index
batch_add_faiss_index
2023-05-05 00:26:52 +08:00
RVC-Boss
da34d75ec9 Add files via upload 2023-05-04 22:22:46 +08:00
nadare
b18f921a50 big_npy should be shuffled (#218) 2023-05-04 14:03:52 +00:00
RVC-Boss
c4a18107dc Update config.py 2023-05-02 12:31:05 +00:00
github-actions[bot]
951989117b Format code (#214)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-02 20:22:08 +08:00
RVC-Boss
71427575c4 Update infer-web.py 2023-05-02 12:17:09 +00:00
RVC-Boss
8370356d95 Update config.py 2023-05-02 12:07:03 +00:00
nadare
69ea94609b update training tips and faiss tips (#208) 2023-04-30 22:26:25 +08:00
Ftps
6d0ec4b00c Escaping when device does not match (#203) 2023-04-29 04:18:06 +00:00
Ftps
b12e33891c fix open (#200) 2023-04-29 12:11:13 +08:00
github-actions[bot]
4cb010bac6 🎨 同步 locale (#196)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-28 20:46:39 +08:00
github-actions[bot]
e9301d7a08 Format code (#195)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-04-28 20:45:21 +08:00
bycloud
bbe333552f added some more zh to en_US translation (#194)
* Add files via upload

* updated i18n() translation for en_US

expanded the dict for other languages

* added more i18n()

---------

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2023-04-28 20:44:46 +08:00
Ftps
f391ac1763 Config class (#192)
* update config.py

* class

* class

* fix
2023-04-28 20:43:02 +08:00
源文雨
b1134d9f64 add 韓國語 2023-04-28 15:54:12 +08:00
RVC-Boss
211a842e88 Update infer-web.py 2023-04-28 11:31:13 +08:00
github-actions[bot]
9068d5283e Format code (#188)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-04-28 11:25:20 +08:00
RVC-Boss
9976df7045 Update Changelog_CN.md 2023-04-27 16:30:45 +00:00
67 changed files with 10055 additions and 6848 deletions

70
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
name: Build And Push Docker Image
on:
workflow_dispatch:
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v3
- name: Set time zone
uses: szenius/set-timezone@v1.0
with:
timezoneLinux: "Asia/Shanghai"
timezoneMacos: "Asia/Shanghai"
timezoneWindows: "China Standard Time"
# # 如果有 dockerhub 账户可以在github的secrets中配置下面两个然后取消下面注释的这几行并在meta步骤的images增加一行 ${{ github.repository }}
# - name: Login to DockerHub
# uses: docker/login-action@v1
# with:
# username: ${{ secrets.DOCKERHUB_USERNAME }}
# password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: |
ghcr.io/${{ github.repository }}
# generate Docker tags based on the following events/attributes
# nightly, master, pr-2, 1.2.3, 1.2, 1
tags: |
type=schedule,pattern=nightly
type=edge
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build and push
id: docker_build
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -33,4 +33,4 @@ jobs:
python trainset_preprocess_pipeline_print.py logs/mute/0_gt_wavs 48000 8 logs/mi-test True python trainset_preprocess_pipeline_print.py logs/mute/0_gt_wavs 48000 8 logs/mi-test True
touch logs/mi-test/extract_f0_feature.log touch logs/mi-test/extract_f0_feature.log
python extract_f0_print.py logs/mi-test $(nproc) pm python extract_f0_print.py logs/mi-test $(nproc) pm
python extract_feature_print.py cpu 1 0 0 logs/mi-test python extract_feature_print.py cpu 1 0 0 logs/mi-test v1

View File

@@ -1,4 +1,53 @@
### 20230409 ### 20230618更新
- v2增加32k和48k两个新预训练模型
- 修复非f0模型推理报错
- 对于超过一小时的训练集的索引建立环节自动kmeans缩小特征处理以加速索引训练、加入和查询
- 附送一个人声转吉他玩具仓库
- 数据处理剔除异常值切片
- onnx导出选项卡
失败的实验:
- ~~特征检索增加时序维度:寄,没啥效果~~
- ~~特征检索增加PCAR降维可选项数据大用kmeans缩小数据量数据小降维操作耗时比省下的匹配耗时还多~~
- ~~支持onnx推理附带仅推理的小压缩包生成nsf还是需要pytorch~~
- ~~训练时在音高、gender、eq、噪声等方面对输入进行随机增强没啥效果~~
todolist
- 接入小型声码器调研
- 训练集音高识别支持crepe
- crepe的精度支持和RVC-config同步
- 对接F0编辑器
### 20230528更新
- 增加v2的jupyter notebook韩文changelog增加一些环境依赖
- 增加呼吸、清辅音、齿音保护模式
- 支持crepe-full推理
- UVR5人声伴奏分离加上3个去延迟模型和MDX-Net去混响模型增加HP3人声提取模型
- 索引名称增加版本和实验名称
- 人声伴奏分离、推理批量导出增加音频导出格式选项
- 废弃32k模型的训练
### 20230513更新
- 清除一键包内部老版本runtime内残留的infer_pack和uvr5_pack
- 修复训练集预处理伪多进程的bug
- 增加harvest识别音高可选通过中值滤波削弱哑音现象可调整中值滤波半径
- 导出音频增加后处理重采样
- 训练n_cpu进程数从"仅调整f0提取"改为"调整数据预处理和f0提取"
- 自动检测logs文件夹下的index路径提供下拉列表功能
- tab页增加"常见问题解答"也可参考github-rvc-wiki
- 相同路径的输入音频推理增加了音高缓存用途使用harvest音高提取整个pipeline会经历漫长且重复的音高提取过程如果不使用缓存实验不同音色、索引、音高中值滤波半径参数的用户在第一次测试后的等待结果会非常痛苦
### 20230514更新
- 音量包络对齐输入混合可以缓解“输入静音输出小幅度噪声”的问题。如果输入音频背景底噪大则不建议开启默认不开启值为1可视为不开启
- 支持按照指定频率保存提取的小模型假如你想尝试不同epoch下的推理效果但是不想保存所有大checkpoint并且每次都要ckpt手工处理提取小模型这项功能会非常实用
- 通过设置环境变量解决服务端开了系统全局代理导致浏览器连接错误的问题
- 支持v2预训练模型目前只公开了40k版本进行测试另外2个采样率还没有训练完全
- 推理前限制超过1的过大音量
- 微调数据预处理参数
### 20230409更新
- 修正训练参数提升显卡平均利用率A100最高从25%提升至90%左右V100:50%->90%左右2060S:60%->85%左右P40:25%->95%左右,训练速度显著提升 - 修正训练参数提升显卡平均利用率A100最高从25%提升至90%左右V100:50%->90%左右2060S:60%->85%左右P40:25%->95%左右,训练速度显著提升
- 修正参数总batch_size改为每张卡的batch_size - 修正参数总batch_size改为每张卡的batch_size
- 修正total_epoch最大限制100解锁至1000默认10提升至默认20 - 修正total_epoch最大限制100解锁至1000默认10提升至默认20
@@ -21,14 +70,11 @@
- 修复部分音频格式下UVR5人声伴奏分离的bug - 修复部分音频格式下UVR5人声伴奏分离的bug
- 实时变声迷你gui增加对非40k与不懈怠音高模型的支持 - 实时变声迷你gui增加对非40k与不懈怠音高模型的支持
### 后续计划: ### 后续计划:
功能 功能
- 增加选项:每次epoch保存的小模型均进行提取 - 支持多人训练选项卡至多4人
- 增加选项:推理额外导出mp3至填写的路径
底模 底模
- 收集呼吸wav加入训练集修正呼吸变声电音的问题 - 收集呼吸wav加入训练集修正呼吸变声电音的问题
- 我们正在训练增加了歌声训练集的底模未来会公开 - 我们正在训练增加了歌声训练集的底模未来会公开
- 升级鉴别器
- 升级自监督特征结构

83
Changelog_EN.md Normal file
View File

@@ -0,0 +1,83 @@
### 2023-06-18
- New pretrained v2 models: 32k and 48k
- Fix non-f0 model inference errors
- For training-set exceeding 1 hour, do automatic minibatch-kmeans to reduce feature shape, so that index training, adding, and searching will be much faster.
- Provide a toy vocal2guitar huggingface space
- Auto delete outlier short cut training-set audios
- Onnx export tab
Failed experiments:
- ~~Feature retrieval: add temporal feature retrieval: not effective~~
- ~~Feature retrieval: add PCAR dimensionality reduction: searching is even slower~~
- ~~Random data augmentation when training: not effective~~
todolist
- Vocos-RVC (tiny vocoder)
- Crepe support for training
- Half precision crepe inference
- F0 editor support
### 2023-05-28
- Add v2 jupyter notebook, korean changelog, fix some environment requirments
- Add voiceless consonant and breath protection mode
- Support crepe-full pitch detect
- UVR5 vocal separation: support dereverb models and de-echo models
- Add experiment name and version on the name of index
- Support users to manually select export format of output audios when batch voice conversion processing and UVR5 vocal separation
- v1 32k model training is no more supported
### 2023-05-13
- Clear the redundant codes in the old version of runtime in the one-click-package: infer_pack and uvr5_pack
- Fix pseudo multiprocessing bug in training set preprocessing
- Adding median filtering radius adjustment for harvest pitch recognize algorithm
- Support post processing resampling for exporting audio
- Multi processing "n_cpu" setting for training is changed from "f0 extraction" to "data preprocessing and f0 extraction"
- Automatically detect the index paths under the logs folder and provide a drop-down list function
- Add "Frequently Asked Questions and Answers" on the tab page (you can also refer to github RVC wiki)
- When inference, harvest pitch is cached when using same input audio path (purpose: using harvest pitch extraction, the entire pipeline will go through a long and repetitive pitch extraction process. If caching is not used, users who experiment with different timbre, index, and pitch median filtering radius settings will experience a very painful waiting process after the first inference)
### 2023-05-14
- Use volume envelope of input to mix or replace the volume envelope of output (can alleviate the problem of "input muting and output small amplitude noise". If the input audio background noise is high, it is not recommended to turn it on, and it is not turned on by default (1 can be considered as not turned on)
- Support saving extracted small models at a specified frequency (if you want to see the performance under different epochs, but do not want to save all large checkpoints and manually extract small models by ckpt-processing every time, this feature will be very practical)
- Resolve the issue of "connection errors" caused by the server's global proxy by setting environment variables
- Supports pre-trained v2 models (currently only 40k versions are publicly available for testing, and the other two sampling rates have not been fully trained yet)
- Limit excessive volume exceeding 1 before inference
- Slightly adjusted the settings of training-set preprocessing
#######################
History changelogs:
### 2023-04-09
- Fixed training parameters to improve GPU utilization rate: A100 increased from 25% to around 90%, V100: 50% to around 90%, 2060S: 60% to around 85%, P40: 25% to around 95%; significantly improved training speed
- Changed parameter: total batch_size is now per GPU batch_size
- Changed total_epoch: maximum limit increased from 100 to 1000; default increased from 10 to 20
- Fixed issue of ckpt extraction recognizing pitch incorrectly, causing abnormal inference
- Fixed issue of distributed training saving ckpt for each rank
- Applied nan feature filtering for feature extraction
- Fixed issue with silent input/output producing random consonants or noise (old models need to retrain with a new dataset)
### 2023-04-16 Update
- Added local real-time voice changing mini-GUI, start by double-clicking go-realtime-gui.bat
- Applied filtering for frequency bands below 50Hz during training and inference
- Lowered the minimum pitch extraction of pyworld from the default 80 to 50 for training and inference, allowing male low-pitched voices between 50-80Hz not to be muted
- WebUI supports changing languages according to system locale (currently supporting en_US, ja_JP, zh_CN, zh_HK, zh_SG, zh_TW; defaults to en_US if not supported)
- Fixed recognition of some GPUs (e.g., V100-16G recognition failure, P4 recognition failure)
### 2023-04-28 Update
- Upgraded faiss index settings for faster speed and higher quality
- Removed dependency on total_npy; future model sharing will not require total_npy input
- Unlocked restrictions for the 16-series GPUs, providing 4GB inference settings for 4GB VRAM GPUs
- Fixed bug in UVR5 vocal accompaniment separation for certain audio formats
- Real-time voice changing mini-GUI now supports non-40k and non-lazy pitch models
### Future Plans:
Features:
- Add option: extract small models for each epoch save
- Add option: export additional mp3 to the specified path during inference
- Support multi-person training tab (up to 4 people)
Base model:
- Collect breathing wav files to add to the training dataset to fix the issue of distorted breath sounds
- We are currently training a base model with an extended singing dataset, which will be released in the future

77
Changelog_KO.md Normal file
View File

@@ -0,0 +1,77 @@
### 2023년 5월 28일 업데이트
- v2 jupyter notebook 추가, 한국어 업데이트 로그 추가, 의존성 모듈 일부 수정.
- 무성음 및 숨소리 보호 모드 추가.
- crepe-full pitch 감지 지원.
- UVR5 보컬 분리: 디버브 및 디-에코 모델 지원.
- index 이름에 experiment 이름과 버전 추가.
- 배치 음성 변환 처리 및 UVR5 보컬 분리 시, 사용자가 수동으로 출력 오디오의 내보내기(export) 형식을 선택할 수 있도록 지원.
- 32k 훈련 모델 지원 종료.
추후 업데이트 목록:
- 특징 검색: 시간적 특징 검색 추가.
- 특징 검색: pre-kmeans 옵션 추가.
- 특징 검색: PCAR 차원 축소 추가.
- onnx 추론 지원 추가.
- 학습 시 랜덤 데이터 증강: 음고, 성별, eq, 잡음.
- v2 버전 사전 훈련된 모델 추가.
### 2023년 5월 13일 업데이트
- 원클릭 패키지의 이전 버전 런타임 내, 불필요한 코드(infer_pack 및 uvr5_pack) 제거.
- 훈련 세트 전처리의 유사 다중 처리 버그 수정.
- Harvest 피치 인식 알고리즘에 대한 중위수 필터링 반경 조정 추가.
- 오디오 내보낼 때, 후처리 리샘플링 지원.
- 훈련에 대한 다중 처리 "n_cpu" 설정이 "f0 추출"에서 "데이터 전처리 및 f0 추출"로 변경.
- logs 폴더 하의 인덱스 경로를 자동으로 감지 및 드롭다운 목록 기능 제공.
- 탭 페이지에 "자주 묻는 질문과 답변" 추가. (github RVC wiki 참조 가능)
- 동일한 입력 오디오 경로를 사용할 때 추론, Harvest 피치를 캐시.
(주의: Harvest 피치 추출을 사용하면 전체 파이프라인은 길고 반복적인 피치 추출 과정을 거치게됩니다. 캐싱을 하지 않는다면, 첫 inference 이후의 단계에서 timbre, 인덱스, 피치 중위수 필터링 반경 설정 등 대기시간이 엄청나게 길어집니다!)
### 2023년 5월 14일 업데이트
- 입력의 볼륨 캡슐을 사용하여 출력의 볼륨 캡슐을 혼합하거나 대체. (입력이 무음이거나 출력의 노이즈 문제를 최소화 할 수 있습니다. 입력 오디오의 배경 노이즈(소음)가 큰 경우 해당 기능을 사용하지 않는 것이 좋습니다. 기본적으로 비활성화 되어있는 옵션입니다. (1: 비활성화 상태))
- 추출된 소형 모델을 지정된 빈도로 저장하는 기능을 지원. (다양한 에폭 하에서의 성능을 보려고 하지만 모든 대형 체크포인트를 저장하고 매번 ckpt 처리를 통해 소형 모델을 수동으로 추출하고 싶지 않은 경우 이 기능은 매우 유용합니다)
- 환경 변수를 설정하여 서버의 전역 프록시로 인한 "연결 오류" 문제 해결.
- 사전 훈련된 v2 모델 지원. (현재 40k 버전만 테스트를 위해 공개적으로 사용 가능하며, 다른 두 개의 샘플링 비율은 아직 완전히 훈련되지 않아 보류되었습니다.)
- 추론 전, 1을 초과하는 과도한 볼륨 제한.
- 데이터 전처리 매개변수 미세 조정.
### 2023년 4월 9일 업데이트
- GPU 이용률 향상을 위해 훈련 파라미터 수정: A100은 25%에서 약 90%로 증가, V100: 50%에서 약 90%로 증가, 2060S: 60%에서 약 85%로 증가, P40: 25%에서 약 95%로 증가.
훈련 속도가 크게 향상.
- 매개변수 기준 변경: total batch_size는 GPU당 batch_size를 의미.
- total_epoch 변경: 최대 한도가 100에서 1000으로 증가. 기본값이 10에서 20으로 증가.
- ckpt 추출이 피치를 잘못 인식하여 비정상적인 추론을 유발하는 문제 수정.
- 분산 훈련 과정에서 각 랭크마다 ckpt를 저장하는 문제 수정.
- 특성 추출 과정에 나노 특성 필터링 적용.
- 무음 입력/출력이 랜덤하게 소음을 생성하는 문제 수정. (이전 모델은 새 데이터셋으로 다시 훈련해야 합니다)
### 2023년 4월 16일 업데이트
- 로컬 실시간 음성 변경 미니-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)
- 일부 GPU의 인식 수정. (예: V100-16G 인식 실패, P4 인식 실패)
### 2023년 4월 28일 업데이트
- Faiss 인덱스 설정 업그레이드로 속도가 더 빨라지고 품질이 향상.
- total_npy에 대한 의존성 제거. 추후의 모델 공유는 total_npy 입력을 필요로 하지 않습니다.
- 16 시리즈 GPU에 대한 제한 해제, 4GB VRAM GPU에 대한 4GB 추론 설정 제공.
- 일부 오디오 형식에 대한 UVR5 보컬 동반 분리에서의 버그 수정.
- 실시간 음성 변경 미니-GUI는 이제 non-40k 및 non-lazy 피치 모델을 지원합니다.
### 추후 계획
Features:
- 다중 사용자 훈련 탭 지원.(최대 4명)
Base model:
- 훈련 데이터셋에 숨소리 wav 파일을 추가하여, 보컬의 호흡이 노이즈로 변환되는 문제 수정.
- 보컬 훈련 세트의 기본 모델을 추가하기 위한 작업을 진행중이며, 이는 향후에 발표될 예정.

13
Dockerfile Normal file
View File

@@ -0,0 +1,13 @@
# syntax=docker/dockerfile:1
FROM python:3.10-bullseye
EXPOSE 7865
WORKDIR /app
COPY . .
RUN pip3 install -r requirements.txt
CMD ["python3", "infer-web.py"]

274
MDXNet.py Normal file
View File

@@ -0,0 +1,274 @@
import soundfile as sf
import torch, pdb, time, argparse, os, warnings, sys, librosa
import numpy as np
import onnxruntime as ort
from scipy.io.wavfile import write
from tqdm import tqdm
import torch
import torch.nn as nn
dim_c = 4
class Conv_TDF_net_trim:
def __init__(
self, device, model_name, target_name, L, dim_f, dim_t, n_fft, hop=1024
):
super(Conv_TDF_net_trim, self).__init__()
self.dim_f = dim_f
self.dim_t = 2**dim_t
self.n_fft = n_fft
self.hop = hop
self.n_bins = self.n_fft // 2 + 1
self.chunk_size = hop * (self.dim_t - 1)
self.window = torch.hann_window(window_length=self.n_fft, periodic=True).to(
device
)
self.target_name = target_name
self.blender = "blender" in model_name
out_c = dim_c * 4 if target_name == "*" else dim_c
self.freq_pad = torch.zeros(
[1, out_c, self.n_bins - self.dim_f, self.dim_t]
).to(device)
self.n = L // 2
def stft(self, x):
x = x.reshape([-1, self.chunk_size])
x = torch.stft(
x,
n_fft=self.n_fft,
hop_length=self.hop,
window=self.window,
center=True,
return_complex=True,
)
x = torch.view_as_real(x)
x = x.permute([0, 3, 1, 2])
x = x.reshape([-1, 2, 2, self.n_bins, self.dim_t]).reshape(
[-1, dim_c, self.n_bins, self.dim_t]
)
return x[:, :, : self.dim_f]
def istft(self, x, freq_pad=None):
freq_pad = (
self.freq_pad.repeat([x.shape[0], 1, 1, 1])
if freq_pad is None
else freq_pad
)
x = torch.cat([x, freq_pad], -2)
c = 4 * 2 if self.target_name == "*" else 2
x = x.reshape([-1, c, 2, self.n_bins, self.dim_t]).reshape(
[-1, 2, self.n_bins, self.dim_t]
)
x = x.permute([0, 2, 3, 1])
x = x.contiguous()
x = torch.view_as_complex(x)
x = torch.istft(
x, n_fft=self.n_fft, hop_length=self.hop, window=self.window, center=True
)
return x.reshape([-1, c, self.chunk_size])
def get_models(device, dim_f, dim_t, n_fft):
return Conv_TDF_net_trim(
device=device,
model_name="Conv-TDF",
target_name="vocals",
L=11,
dim_f=dim_f,
dim_t=dim_t,
n_fft=n_fft,
)
warnings.filterwarnings("ignore")
cpu = torch.device("cpu")
if torch.cuda.is_available():
device = torch.device("cuda:0")
elif torch.backends.mps.is_available():
device = torch.device("mps")
else:
device = torch.device("cpu")
class Predictor:
def __init__(self, args):
self.args = args
self.model_ = get_models(
device=cpu, dim_f=args.dim_f, dim_t=args.dim_t, n_fft=args.n_fft
)
self.model = ort.InferenceSession(
os.path.join(args.onnx, self.model_.target_name + ".onnx"),
providers=["CUDAExecutionProvider", "CPUExecutionProvider"],
)
print("onnx load done")
def demix(self, mix):
samples = mix.shape[-1]
margin = self.args.margin
chunk_size = self.args.chunks * 44100
assert not margin == 0, "margin cannot be zero!"
if margin > chunk_size:
margin = chunk_size
segmented_mix = {}
if self.args.chunks == 0 or samples < chunk_size:
chunk_size = samples
counter = -1
for skip in range(0, samples, chunk_size):
counter += 1
s_margin = 0 if counter == 0 else margin
end = min(skip + chunk_size + margin, samples)
start = skip - s_margin
segmented_mix[skip] = mix[:, start:end].copy()
if end == samples:
break
sources = self.demix_base(segmented_mix, margin_size=margin)
"""
mix:(2,big_sample)
segmented_mix:offset->(2,small_sample)
sources:(1,2,big_sample)
"""
return sources
def demix_base(self, mixes, margin_size):
chunked_sources = []
progress_bar = tqdm(total=len(mixes))
progress_bar.set_description("Processing")
for mix in mixes:
cmix = mixes[mix]
sources = []
n_sample = cmix.shape[1]
model = self.model_
trim = model.n_fft // 2
gen_size = model.chunk_size - 2 * trim
pad = gen_size - n_sample % gen_size
mix_p = np.concatenate(
(np.zeros((2, trim)), cmix, np.zeros((2, pad)), np.zeros((2, trim))), 1
)
mix_waves = []
i = 0
while i < n_sample + pad:
waves = np.array(mix_p[:, i : i + model.chunk_size])
mix_waves.append(waves)
i += gen_size
mix_waves = torch.tensor(mix_waves, dtype=torch.float32).to(cpu)
with torch.no_grad():
_ort = self.model
spek = model.stft(mix_waves)
if self.args.denoise:
spec_pred = (
-_ort.run(None, {"input": -spek.cpu().numpy()})[0] * 0.5
+ _ort.run(None, {"input": spek.cpu().numpy()})[0] * 0.5
)
tar_waves = model.istft(torch.tensor(spec_pred))
else:
tar_waves = model.istft(
torch.tensor(_ort.run(None, {"input": spek.cpu().numpy()})[0])
)
tar_signal = (
tar_waves[:, :, trim:-trim]
.transpose(0, 1)
.reshape(2, -1)
.numpy()[:, :-pad]
)
start = 0 if mix == 0 else margin_size
end = None if mix == list(mixes.keys())[::-1][0] else -margin_size
if margin_size == 0:
end = None
sources.append(tar_signal[:, start:end])
progress_bar.update(1)
chunked_sources.append(sources)
_sources = np.concatenate(chunked_sources, axis=-1)
# del self.model
progress_bar.close()
return _sources
def prediction(self, m, vocal_root, others_root, format):
os.makedirs(vocal_root, exist_ok=True)
os.makedirs(others_root, exist_ok=True)
basename = os.path.basename(m)
mix, rate = librosa.load(m, mono=False, sr=44100)
if mix.ndim == 1:
mix = np.asfortranarray([mix, mix])
mix = mix.T
sources = self.demix(mix.T)
opt = sources[0].T
if format in ["wav", "flac"]:
sf.write(
"%s/%s_main_vocal.%s" % (vocal_root, basename, format), mix - opt, rate
)
sf.write("%s/%s_others.%s" % (others_root, basename, format), opt, rate)
else:
path_vocal = "%s/%s_main_vocal.wav" % (vocal_root, basename)
path_other = "%s/%s_others.wav" % (others_root, basename)
sf.write(path_vocal, mix - opt, rate)
sf.write(path_other, opt, rate)
if os.path.exists(path_vocal):
os.system(
"ffmpeg -i %s -vn %s -q:a 2 -y"
% (path_vocal, path_vocal[:-4] + ".%s" % format)
)
if os.path.exists(path_other):
os.system(
"ffmpeg -i %s -vn %s -q:a 2 -y"
% (path_other, path_other[:-4] + ".%s" % format)
)
class MDXNetDereverb:
def __init__(self, chunks):
self.onnx = "uvr5_weights/onnx_dereverb_By_FoxJoy"
self.shifts = 10 #'Predict with randomised equivariant stabilisation'
self.mixing = "min_mag" # ['default','min_mag','max_mag']
self.chunks = chunks
self.margin = 44100
self.dim_t = 9
self.dim_f = 3072
self.n_fft = 6144
self.denoise = True
self.pred = Predictor(self)
def _path_audio_(self, input, vocal_root, others_root, format):
self.pred.prediction(input, vocal_root, others_root, format)
if __name__ == "__main__":
dereverb = MDXNetDereverb(15)
from time import time as ttime
t0 = ttime()
dereverb._path_audio_(
"雪雪伴奏对消HP5.wav",
"vocal",
"others",
)
t1 = ttime()
print(t1 - t0)
"""
runtime\python.exe MDXNet.py
6G:
15/9:0.8G->6.8G
14:0.8G->6.5G
25:炸
half15:0.7G->6.6G,22.69s
fp32-15:0.7G->6.6G,20.85s
"""

View File

@@ -13,14 +13,17 @@
[![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk) [![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk)
[**更新日志**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md) | [**常见问题解答**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E8%A7%A3%E7%AD%94) | [**AutoDL·5毛钱训练AI歌手**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/Autodl%E8%AE%AD%E7%BB%83RVC%C2%B7AI%E6%AD%8C%E6%89%8B%E6%95%99%E7%A8%8B) | [**对照实验记录**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/Autodl%E8%AE%AD%E7%BB%83RVC%C2%B7AI%E6%AD%8C%E6%89%8B%E6%95%99%E7%A8%8B](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/%E5%AF%B9%E7%85%A7%E5%AE%9E%E9%AA%8C%C2%B7%E5%AE%9E%E9%AA%8C%E8%AE%B0%E5%BD%95))
</div> </div>
------ ------
[**更新日志**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md) [**English**](./docs/README.en.md) | [**中文简体**](./README.md) | [**日本語**](./docs/README.ja.md) | [**한국어**](./docs/README.ko.md) ([**韓國語**](./docs/README.ko.han.md))
[**English**](./docs/README.en.md) | [**中文简体**](./README.md) | [**日本語**](./docs/README.ja.md) | [**한국어**](./docs/README.ko.md) :fire: 使用了RVC变声器训练的人声转木吉他模型在线demo:fire: https://huggingface.co/spaces/lj1995/vocal2guitar
:fire: RVC人声转吉他效果展示视频:fire: https://www.bilibili.com/video/BV19W4y1D7tT/
> 点此查看我们的[演示视频](https://www.bilibili.com/video/BV1pm4y1z7Gm/) ! > 点此查看我们的[演示视频](https://www.bilibili.com/video/BV1pm4y1z7Gm/) !
@@ -60,9 +63,6 @@ poetry install
``` ```
你也可以通过pip来安装依赖 你也可以通过pip来安装依赖
**注意**: `MacOS``faiss 1.7.2`版本会导致抛出段错误,在手动安装时请使用命令`pip install faiss-cpu==1.7.0`指定使用`1.7.0`版本
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
``` ```
@@ -80,6 +80,10 @@ hubert_base.pt
./uvr5_weights ./uvr5_weights
想测试v2版本模型的话(v2版本模型将特征从 9层hubert+final_proj的256维输入 变更为 12层hubert的768维输入并且增加了3个周期鉴别器),需要额外下载
./pretrained_v2
#如果你正在使用Windows则你可能需要这个文件若ffmpeg和ffprobe已安装则跳过; ubuntu/debian 用户可以通过apt install ffmpeg来安装这2个库 #如果你正在使用Windows则你可能需要这个文件若ffmpeg和ffprobe已安装则跳过; ubuntu/debian 用户可以通过apt install ffmpeg来安装这2个库
./ffmpeg ./ffmpeg

View File

@@ -45,7 +45,7 @@
"!apt-get -y install build-essential python3-dev ffmpeg\n", "!apt-get -y install build-essential python3-dev ffmpeg\n",
"!pip3 install --upgrade setuptools wheel\n", "!pip3 install --upgrade setuptools wheel\n",
"!pip3 install --upgrade pip\n", "!pip3 install --upgrade pip\n",
"!pip3 install faiss-gpu fairseq gradio ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2" "!pip3 install faiss-cpu==1.7.2 fairseq gradio==3.14.0 ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
], ],
"metadata": { "metadata": {
"id": "wjddIFr1oS3W" "id": "wjddIFr1oS3W"
@@ -378,4 +378,4 @@
"outputs": [] "outputs": []
} }
] ]
} }

View File

@@ -0,0 +1,401 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ZFFCx5J80SGa"
},
"source": [
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI_v2.ipynb)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "GmFP6bN9dvOq"
},
"outputs": [],
"source": [
"#@title 查看显卡\n",
"!nvidia-smi"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "wjddIFr1oS3W"
},
"outputs": [],
"source": [
"#@title 安装依赖\n",
"!apt-get -y install build-essential python3-dev ffmpeg\n",
"!pip3 install --upgrade setuptools wheel\n",
"!pip3 install --upgrade pip\n",
"!pip3 install faiss-cpu==1.7.2 fairseq gradio==3.14.0 ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ge_97mfpgqTm"
},
"outputs": [],
"source": [
"#@title 克隆仓库\n",
"\n",
"!mkdir Retrieval-based-Voice-Conversion-WebUI\n",
"%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
"!git init\n",
"!git remote add origin https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git\n",
"!git fetch origin cfd984812804ddc9247d65b14c82cd32e56c1133 --depth=1 \n",
"!git reset --hard FETCH_HEAD"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "BLDEZADkvlw1"
},
"outputs": [],
"source": [
"#@title 更新仓库(一般无需执行)\n",
"!git pull"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "pqE0PrnuRqI2"
},
"outputs": [],
"source": [
"#@title 安装aria2\n",
"!apt -y install -qq aria2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "UG3XpUwEomUz"
},
"outputs": [],
"source": [
"#@title 下载底模\n",
"\n",
"# v1\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D40k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D48k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G40k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G48k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D40k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D48k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G40k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G48k.pth\n",
"\n",
"#v2\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D40k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D48k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G40k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G48k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D40k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D48k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G32k.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G40k.pth\n",
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G48k.pth"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "HugjmZqZRuiF"
},
"outputs": [],
"source": [
"#@title 下载人声分离模型\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP2-人声vocals+非人声instrumentals.pth\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP5-主旋律人声vocals+其他instrumentals.pth"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2RCaT9FTR0ej"
},
"outputs": [],
"source": [
"#@title 下载hubert_base\n",
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o hubert_base.pt"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "jwu07JgqoFON"
},
"outputs": [],
"source": [
"#@title 挂载谷歌云盘\n",
"\n",
"from google.colab import drive\n",
"drive.mount('/content/drive')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Mwk7Q0Loqzjx"
},
"outputs": [],
"source": [
"#@title 从谷歌云盘加载打包好的数据集到/content/dataset\n",
"\n",
"#@markdown 数据集位置\n",
"DATASET = \"/content/drive/MyDrive/dataset/lulu20230327_32k.zip\" #@param {type:\"string\"}\n",
"\n",
"!mkdir -p /content/dataset\n",
"!unzip -d /content/dataset -B {DATASET}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "PDlFxWHWEynD"
},
"outputs": [],
"source": [
"#@title 重命名数据集中的重名文件\n",
"!ls -a /content/dataset/\n",
"!rename 's/(\\w+)\\.(\\w+)~(\\d*)/$1_$3.$2/' /content/dataset/*.*~*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "7vh6vphDwO0b"
},
"outputs": [],
"source": [
"#@title 启动web\n",
"%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
"# %load_ext tensorboard\n",
"# %tensorboard --logdir /content/Retrieval-based-Voice-Conversion-WebUI/logs\n",
"!python3 infer-web.py --colab --pycmd python3"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "FgJuNeAwx5Y_"
},
"outputs": [],
"source": [
"#@title 手动将训练后的模型文件备份到谷歌云盘\n",
"#@markdown 需要自己查看logs文件夹下模型的文件名手动修改下方命令末尾的文件名\n",
"\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 模型epoch\n",
"MODELEPOCH = 9600 #@param {type:\"integer\"}\n",
"\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/added_*.index /content/drive/MyDrive/\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/total_*.npy /content/drive/MyDrive/\n",
"\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "OVQoLQJXS7WX"
},
"outputs": [],
"source": [
"#@title 从谷歌云盘恢复pth\n",
"#@markdown 需要自己查看logs文件夹下模型的文件名手动修改下方命令末尾的文件名\n",
"\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 模型epoch\n",
"MODELEPOCH = 7500 #@param {type:\"integer\"}\n",
"\n",
"!mkdir -p /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
"\n",
"!cp /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
"!cp /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
"!cp /content/drive/MyDrive/*.index /content/\n",
"!cp /content/drive/MyDrive/*.npy /content/\n",
"!cp /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ZKAyuKb9J6dz"
},
"outputs": [],
"source": [
"#@title 手动预处理(不推荐)\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 采样率\n",
"BITRATE = 48000 #@param {type:\"integer\"}\n",
"#@markdown 使用的进程数\n",
"THREADCOUNT = 8 #@param {type:\"integer\"}\n",
"\n",
"!python3 trainset_preprocess_pipeline_print.py /content/dataset {BITRATE} {THREADCOUNT} logs/{MODELNAME} True\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "CrxJqzAUKmPJ"
},
"outputs": [],
"source": [
"#@title 手动提取特征(不推荐)\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 使用的进程数\n",
"THREADCOUNT = 8 #@param {type:\"integer\"}\n",
"#@markdown 音高提取算法\n",
"ALGO = \"harvest\" #@param {type:\"string\"}\n",
"\n",
"!python3 extract_f0_print.py logs/{MODELNAME} {THREADCOUNT} {ALGO}\n",
"\n",
"!python3 extract_feature_print.py cpu 1 0 0 logs/{MODELNAME}\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "IMLPLKOaKj58"
},
"outputs": [],
"source": [
"#@title 手动训练(不推荐)\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 使用的GPU\n",
"USEGPU = \"0\" #@param {type:\"string\"}\n",
"#@markdown 批大小\n",
"BATCHSIZE = 32 #@param {type:\"integer\"}\n",
"#@markdown 停止的epoch\n",
"MODELEPOCH = 3200 #@param {type:\"integer\"}\n",
"#@markdown 保存epoch间隔\n",
"EPOCHSAVE = 100 #@param {type:\"integer\"}\n",
"#@markdown 采样率\n",
"MODELSAMPLE = \"48k\" #@param {type:\"string\"}\n",
"#@markdown 是否缓存训练集\n",
"CACHEDATA = 1 #@param {type:\"integer\"}\n",
"#@markdown 是否仅保存最新的ckpt文件\n",
"ONLYLATEST = 0 #@param {type:\"integer\"}\n",
"\n",
"!python3 train_nsf_sim_cache_sid_load_pretrain.py -e lulu -sr {MODELSAMPLE} -f0 1 -bs {BATCHSIZE} -g {USEGPU} -te {MODELEPOCH} -se {EPOCHSAVE} -pg pretrained/f0G{MODELSAMPLE}.pth -pd pretrained/f0D{MODELSAMPLE}.pth -l {ONLYLATEST} -c {CACHEDATA}\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "haYA81hySuDl"
},
"outputs": [],
"source": [
"#@title 删除其它pth只留选中的慎点仔细看代码\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 选中模型epoch\n",
"MODELEPOCH = 9600 #@param {type:\"integer\"}\n",
"\n",
"!echo \"备份选中的模型。。。\"\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
"\n",
"!echo \"正在删除。。。\"\n",
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
"!rm /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*.pth\n",
"\n",
"!echo \"恢复选中的模型。。。\"\n",
"!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth \n",
"!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
"\n",
"!echo \"删除完成\"\n",
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QhSiPTVPoIRh"
},
"outputs": [],
"source": [
"#@title 清除项目下所有文件,只留选中的模型(慎点,仔细看代码)\n",
"#@markdown 模型名\n",
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
"#@markdown 选中模型epoch\n",
"MODELEPOCH = 9600 #@param {type:\"integer\"}\n",
"\n",
"!echo \"备份选中的模型。。。\"\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
"\n",
"!echo \"正在删除。。。\"\n",
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
"!rm -rf /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*\n",
"\n",
"!echo \"恢复选中的模型。。。\"\n",
"!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth \n",
"!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
"\n",
"!echo \"删除完成\"\n",
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"private_outputs": true,
"provenance": []
},
"gpuClass": "standard",
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}

322
app.py Normal file
View File

@@ -0,0 +1,322 @@
import io
import os
import torch
# os.system("wget -P cvec/ https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt")
import gradio as gr
import librosa
import numpy as np
import soundfile
import logging
from fairseq import checkpoint_utils
from my_utils import load_audio
from vc_infer_pipeline import VC
import traceback
from config import Config
from infer_pack.models import (
SynthesizerTrnMs256NSFsid,
SynthesizerTrnMs256NSFsid_nono,
SynthesizerTrnMs768NSFsid,
SynthesizerTrnMs768NSFsid_nono,
)
from i18n import I18nAuto
logging.getLogger("numba").setLevel(logging.WARNING)
logging.getLogger("markdown_it").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("matplotlib").setLevel(logging.WARNING)
i18n = I18nAuto()
i18n.print()
config = Config()
weight_root = "weights"
weight_uvr5_root = "uvr5_weights"
index_root = "logs"
names = []
hubert_model = None
for name in os.listdir(weight_root):
if name.endswith(".pth"):
names.append(name)
index_paths = []
for root, dirs, files in os.walk(index_root, topdown=False):
for name in files:
if name.endswith(".index") and "trained" not in name:
index_paths.append("%s/%s" % (root, name))
def get_vc(sid):
global n_spk, tgt_sr, net_g, vc, cpt, version
if sid == "" or sid == []:
global hubert_model
if hubert_model != None: # 考虑到轮询, 需要加个判断看是否 sid 是由有模型切换到无模型的
print("clean_empty_cache")
del net_g, n_spk, vc, hubert_model, tgt_sr # ,cpt
hubert_model = net_g = n_spk = vc = hubert_model = tgt_sr = None
if torch.cuda.is_available():
torch.cuda.empty_cache()
###楼下不这么折腾清理不干净
if_f0 = cpt.get("f0", 1)
version = cpt.get("version", "v1")
if version == "v1":
if if_f0 == 1:
net_g = SynthesizerTrnMs256NSFsid(
*cpt["config"], is_half=config.is_half
)
else:
net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
elif version == "v2":
if if_f0 == 1:
net_g = SynthesizerTrnMs768NSFsid(
*cpt["config"], is_half=config.is_half
)
else:
net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
del net_g, cpt
if torch.cuda.is_available():
torch.cuda.empty_cache()
cpt = None
return {"visible": False, "__type__": "update"}
person = "%s/%s" % (weight_root, sid)
print("loading %s" % person)
cpt = torch.load(person, map_location="cpu")
tgt_sr = cpt["config"][-1]
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
if_f0 = cpt.get("f0", 1)
version = cpt.get("version", "v1")
if version == "v1":
if if_f0 == 1:
net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=config.is_half)
else:
net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
elif version == "v2":
if if_f0 == 1:
net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=config.is_half)
else:
net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
del net_g.enc_q
print(net_g.load_state_dict(cpt["weight"], strict=False))
net_g.eval().to(config.device)
if config.is_half:
net_g = net_g.half()
else:
net_g = net_g.float()
vc = VC(tgt_sr, config)
n_spk = cpt["config"][-3]
return {"visible": True, "maximum": n_spk, "__type__": "update"}
def load_hubert():
global hubert_model
models, _, _ = checkpoint_utils.load_model_ensemble_and_task(
["hubert_base.pt"],
suffix="",
)
hubert_model = models[0]
hubert_model = hubert_model.to(config.device)
if config.is_half:
hubert_model = hubert_model.half()
else:
hubert_model = hubert_model.float()
hubert_model.eval()
def vc_single(
sid,
input_audio_path,
f0_up_key,
f0_file,
f0_method,
file_index,
file_index2,
# file_big_npy,
index_rate,
filter_radius,
resample_sr,
rms_mix_rate,
protect,
): # spk_item, input_audio0, vc_transform0,f0_file,f0method0
global tgt_sr, net_g, vc, hubert_model, version
if input_audio_path is None:
return "You need to upload an audio", None
f0_up_key = int(f0_up_key)
try:
audio = input_audio_path[1] / 32768.0
if len(audio.shape) == 2:
audio = np.mean(audio, -1)
audio = librosa.resample(audio, orig_sr=input_audio_path[0], target_sr=16000)
audio_max = np.abs(audio).max() / 0.95
if audio_max > 1:
audio /= audio_max
times = [0, 0, 0]
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")
)
if file_index != ""
else file_index2
) # 防止小白写错,自动帮他替换掉
# file_big_npy = (
# file_big_npy.strip(" ").strip('"').strip("\n").strip('"').strip(" ")
# )
audio_opt = vc.pipeline(
hubert_model,
net_g,
sid,
audio,
input_audio_path,
times,
f0_up_key,
f0_method,
file_index,
# file_big_npy,
index_rate,
if_f0,
filter_radius,
tgt_sr,
resample_sr,
rms_mix_rate,
version,
protect,
f0_file=f0_file,
)
if resample_sr >= 16000 and tgt_sr != resample_sr:
tgt_sr = resample_sr
index_info = (
"Using index:%s." % file_index
if os.path.exists(file_index)
else "Index not used."
)
return "Success.\n %s\nTime:\n npy:%ss, f0:%ss, infer:%ss" % (
index_info,
times[0],
times[1],
times[2],
), (tgt_sr, audio_opt)
except:
info = traceback.format_exc()
print(info)
return info, (None, None)
app = gr.Blocks()
with app:
with gr.Tabs():
with gr.TabItem("在线demo"):
gr.Markdown(
value="""
RVC 在线demo
"""
)
sid = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names))
with gr.Column():
spk_item = gr.Slider(
minimum=0,
maximum=2333,
step=1,
label=i18n("请选择说话人id"),
value=0,
visible=False,
interactive=True,
)
sid.change(
fn=get_vc,
inputs=[sid],
outputs=[spk_item],
)
gr.Markdown(
value=i18n("男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ")
)
vc_input3 = gr.Audio(label="上传音频长度小于90秒")
vc_transform0 = gr.Number(label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0)
f0method0 = gr.Radio(
label=i18n("选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU"),
choices=["pm", "harvest", "crepe"],
value="pm",
interactive=True,
)
filter_radius0 = gr.Slider(
minimum=0,
maximum=7,
label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音"),
value=3,
step=1,
interactive=True,
)
with gr.Column():
file_index1 = gr.Textbox(
label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
value="",
interactive=False,
visible=False,
)
file_index2 = gr.Dropdown(
label=i18n("自动检测index路径,下拉式选择(dropdown)"),
choices=sorted(index_paths),
interactive=True,
)
index_rate1 = gr.Slider(
minimum=0,
maximum=1,
label=i18n("检索特征占比"),
value=0.88,
interactive=True,
)
resample_sr0 = gr.Slider(
minimum=0,
maximum=48000,
label=i18n("后处理重采样至最终采样率0为不进行重采样"),
value=0,
step=1,
interactive=True,
)
rms_mix_rate0 = gr.Slider(
minimum=0,
maximum=1,
label=i18n("输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络"),
value=1,
interactive=True,
)
protect0 = gr.Slider(
minimum=0,
maximum=0.5,
label=i18n("保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果"),
value=0.33,
step=0.01,
interactive=True,
)
f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"))
but0 = gr.Button(i18n("转换"), variant="primary")
vc_output1 = gr.Textbox(label=i18n("输出信息"))
vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
but0.click(
vc_single,
[
spk_item,
vc_input3,
vc_transform0,
f0_file,
f0method0,
file_index1,
file_index2,
# file_big_npy1,
index_rate1,
filter_radius0,
resample_sr0,
rms_mix_rate0,
protect0,
],
[vc_output1, vc_output2],
)
app.launch()

229
config.py
View File

@@ -1,106 +1,123 @@
########################硬件参数######################## import argparse
import torch
# 填写cuda:x, cpu 或 mps, x指代第几张卡只支持 N卡 / Apple Silicon 加速 from multiprocessing import cpu_count
device = "cuda:0"
# 9-10-20-30-40系显卡无脑True不影响质量>=20显卡开启有加速 def config_file_change_fp32():
is_half = True for config_file in ["32k.json", "40k.json", "48k.json"]:
with open(f"configs/{config_file}", "r") as f:
# 默认0用上所有线程写数字限制CPU资源使用 strr = f.read().replace("true", "false")
n_cpu = 0 with open(f"configs/{config_file}", "w") as f:
f.write(strr)
########################硬件参数######################## with open("trainset_preprocess_pipeline_print.py", "r") as f:
strr = f.read().replace("3.7", "3.0")
with open("trainset_preprocess_pipeline_print.py", "w") as f:
##################下为参数处理逻辑,勿动################## f.write(strr)
########################命令行参数########################
import argparse class Config:
def __init__(self):
parser = argparse.ArgumentParser() self.device = "cuda:0"
parser.add_argument("--port", type=int, default=7865, help="Listen port") self.is_half = True
parser.add_argument("--pycmd", type=str, default="python", help="Python command") self.n_cpu = 0
parser.add_argument("--colab", action="store_true", help="Launch in colab") self.gpu_name = None
parser.add_argument( self.gpu_mem = None
"--noparallel", action="store_true", help="Disable parallel processing" (
) self.python_cmd,
parser.add_argument( self.listen_port,
"--noautoopen", action="store_true", help="Do not open in browser automatically" self.iscolab,
) self.noparallel,
cmd_opts = parser.parse_args() self.noautoopen,
) = self.arg_parse()
python_cmd = cmd_opts.pycmd self.x_pad, self.x_query, self.x_center, self.x_max = self.device_config()
listen_port = cmd_opts.port if 0 <= cmd_opts.port <= 65535 else 7865
iscolab = cmd_opts.colab @staticmethod
noparallel = cmd_opts.noparallel def arg_parse() -> tuple:
noautoopen = cmd_opts.noautoopen parser = argparse.ArgumentParser()
########################命令行参数######################## parser.add_argument("--port", type=int, default=7865, help="Listen port")
parser.add_argument(
import sys "--pycmd", type=str, default="python", help="Python command"
import torch )
parser.add_argument("--colab", action="store_true", help="Launch in colab")
parser.add_argument(
# has_mps is only available in nightly pytorch (for now) and MasOS 12.3+. "--noparallel", action="store_true", help="Disable parallel processing"
# check `getattr` and try it for compatibility )
def has_mps() -> bool: parser.add_argument(
if sys.platform != "darwin": "--noautoopen",
return False action="store_true",
else: help="Do not open in browser automatically",
if not getattr(torch, "has_mps", False): )
return False cmd_opts = parser.parse_args()
try:
torch.zeros(1).to(torch.device("mps")) cmd_opts.port = cmd_opts.port if 0 <= cmd_opts.port <= 65535 else 7865
return True
except Exception: return (
return False cmd_opts.pycmd,
cmd_opts.port,
cmd_opts.colab,
if not torch.cuda.is_available(): cmd_opts.noparallel,
if has_mps(): cmd_opts.noautoopen,
print("没有发现支持的N卡, 使用MPS进行推理") )
device = "mps"
else: def device_config(self) -> tuple:
print("没有发现支持的N卡, 使用CPU进行推理") if torch.cuda.is_available():
device = "cpu" i_device = int(self.device.split(":")[-1])
is_half = False self.gpu_name = torch.cuda.get_device_name(i_device)
if (
gpu_mem=None ("16" in self.gpu_name and "V100" not in self.gpu_name.upper())
if device not in ["cpu", "mps"]: or "P40" in self.gpu_name.upper()
i_device=int(device.split(":")[-1]) or "1060" in self.gpu_name
gpu_name = torch.cuda.get_device_name(i_device) or "1070" in self.gpu_name
if "16" in gpu_name or "P40"in gpu_name.upper() or "1070"in gpu_name or "1080"in gpu_name: or "1080" in self.gpu_name
print("16系显卡强制单精度") ):
is_half = False print("16系/10系显卡和P40强制单精度")
with open("configs/32k.json","r")as f:strr=f.read().replace("true","false") self.is_half = False
with open("configs/32k.json","w")as f:f.write(strr) config_file_change_fp32()
with open("configs/40k.json","r")as f:strr=f.read().replace("true","false") else:
with open("configs/40k.json","w")as f:f.write(strr) self.gpu_name = None
with open("configs/48k.json","r")as f:strr=f.read().replace("true","false") self.gpu_mem = int(
with open("configs/48k.json","w")as f:f.write(strr) torch.cuda.get_device_properties(i_device).total_memory
with open("trainset_preprocess_pipeline_print.py","r")as f:strr=f.read().replace("3.7","3.0") / 1024
with open("trainset_preprocess_pipeline_print.py","w")as f:f.write(strr) / 1024
gpu_mem=int(torch.cuda.get_device_properties(i_device).total_memory/1024/1024/1024+0.4) / 1024
if(gpu_mem<=4): + 0.4
with open("trainset_preprocess_pipeline_print.py","r")as f:strr=f.read().replace("3.7","3.0") )
with open("trainset_preprocess_pipeline_print.py","w")as f:f.write(strr) if self.gpu_mem <= 4:
from multiprocessing import cpu_count with open("trainset_preprocess_pipeline_print.py", "r") as f:
strr = f.read().replace("3.7", "3.0")
if n_cpu == 0: with open("trainset_preprocess_pipeline_print.py", "w") as f:
n_cpu = cpu_count() f.write(strr)
if is_half: elif torch.backends.mps.is_available():
# 6G显存配置 print("没有发现支持的N卡, 使用MPS进行推理")
x_pad = 3 self.device = "mps"
x_query = 10 self.is_half = False
x_center = 60 config_file_change_fp32()
x_max = 65 else:
else: print("没有发现支持的N卡, 使用CPU进行推理")
# 5G显存配置 self.device = "cpu"
x_pad = 1 self.is_half = False
x_query = 6 config_file_change_fp32()
x_center = 38
x_max = 41 if self.n_cpu == 0:
if(gpu_mem!=None and gpu_mem<=4): self.n_cpu = cpu_count()
x_pad = 1
x_query = 5 if self.is_half:
x_center = 30 # 6G显存配置
x_max = 32 x_pad = 3
x_query = 10
x_center = 60
x_max = 65
else:
# 5G显存配置
x_pad = 1
x_query = 6
x_center = 38
x_max = 41
if self.gpu_mem != None and self.gpu_mem <= 4:
x_pad = 1
x_query = 5
x_center = 30
x_max = 32
return x_pad, x_query, x_center, x_max

46
configs/32k_v2.json Normal file
View File

@@ -0,0 +1,46 @@
{
"train": {
"log_interval": 200,
"seed": 1234,
"epochs": 20000,
"learning_rate": 1e-4,
"betas": [0.8, 0.99],
"eps": 1e-9,
"batch_size": 4,
"fp16_run": true,
"lr_decay": 0.999875,
"segment_size": 12800,
"init_lr_ratio": 1,
"warmup_epochs": 0,
"c_mel": 45,
"c_kl": 1.0
},
"data": {
"max_wav_value": 32768.0,
"sampling_rate": 32000,
"filter_length": 1024,
"hop_length": 320,
"win_length": 1024,
"n_mel_channels": 80,
"mel_fmin": 0.0,
"mel_fmax": null
},
"model": {
"inter_channels": 192,
"hidden_channels": 192,
"filter_channels": 768,
"n_heads": 2,
"n_layers": 6,
"kernel_size": 3,
"p_dropout": 0,
"resblock": "1",
"resblock_kernel_sizes": [3,7,11],
"resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
"upsample_rates": [10,8,2,2],
"upsample_initial_channel": 512,
"upsample_kernel_sizes": [20,16,4,4],
"use_spectral_norm": false,
"gin_channels": 256,
"spk_embed_dim": 109
}
}

46
configs/48k_v2.json Normal file
View File

@@ -0,0 +1,46 @@
{
"train": {
"log_interval": 200,
"seed": 1234,
"epochs": 20000,
"learning_rate": 1e-4,
"betas": [0.8, 0.99],
"eps": 1e-9,
"batch_size": 4,
"fp16_run": true,
"lr_decay": 0.999875,
"segment_size": 11520,
"init_lr_ratio": 1,
"warmup_epochs": 0,
"c_mel": 45,
"c_kl": 1.0
},
"data": {
"max_wav_value": 32768.0,
"sampling_rate": 48000,
"filter_length": 2048,
"hop_length": 480,
"win_length": 2048,
"n_mel_channels": 128,
"mel_fmin": 0.0,
"mel_fmax": null
},
"model": {
"inter_channels": 192,
"hidden_channels": 192,
"filter_channels": 768,
"n_heads": 2,
"n_layers": 6,
"kernel_size": 3,
"p_dropout": 0,
"resblock": "1",
"resblock_kernel_sizes": [3,7,11],
"resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
"upsample_rates": [12,10,2,2],
"upsample_initial_channel": 512,
"upsample_kernel_sizes": [24,20,4,4],
"use_spectral_norm": false,
"gin_channels": 256,
"spk_embed_dim": 109
}
}

View File

@@ -1,7 +1,7 @@
<div align="center"> <div align="center">
<h1>Retrieval-based-Voice-Conversion-WebUI</h1> <h1>Retrieval-based-Voice-Conversion-WebUI</h1>
An easy-to-use SVC framework based on VITS.<br><br> An easy-to-use Voice Conversion framework based on VITS.<br><br>
[![madewithlove](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI) [![madewithlove](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
@@ -16,9 +16,13 @@ An easy-to-use SVC framework based on VITS.<br><br>
</div> </div>
------ ------
[**Changelog**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md) [**Changelog**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md) | [**FAQ (Frequently Asked Questions)**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/FAQ-(Frequently-Asked-Questions))
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) [**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
:fire: A online demo using RVC that convert Vocal to Acoustic Guitar audio:fire: https://huggingface.co/spaces/lj1995/vocal2guitar
:fire: Vocal2Guitar demo video:fire: https://www.bilibili.com/video/BV19W4y1D7tT/
> Check our [Demo Video](https://www.bilibili.com/video/BV1pm4y1z7Gm/) here! > Check our [Demo Video](https://www.bilibili.com/video/BV1pm4y1z7Gm/) here!
@@ -56,8 +60,6 @@ poetry install
``` ```
You can also use pip to install the dependencies You can also use pip to install the dependencies
**Notice**: `faiss 1.7.2` will raise Segmentation Fault: 11 under `MacOS`, please use `pip install faiss-cpu==1.7.0` if you use pip to install it manually.
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
``` ```
@@ -75,6 +77,10 @@ hubert_base.pt
./uvr5_weights ./uvr5_weights
If you want to test the v2 version model (the v2 version model has changed the input from the 256 dimensional feature of 9-layer Hubert+final_proj to the 768 dimensional feature of 12-layer Hubert, and has added 3 period discriminators), you will need to download additional features
./pretrained_v2
#If you are using Windows, you may also need this dictionary, skip if FFmpeg is installed #If you are using Windows, you may also need this dictionary, skip if FFmpeg is installed
ffmpeg.exe ffmpeg.exe
``` ```

View File

@@ -19,7 +19,7 @@ VITSに基づく使いやすい音声変換voice changerframework<br><br>
[**更新日誌**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md) [**更新日誌**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md)
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) [**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
> デモ動画は[こちら](https://www.bilibili.com/video/BV1pm4y1z7Gm/)でご覧ください。 > デモ動画は[こちら](https://www.bilibili.com/video/BV1pm4y1z7Gm/)でご覧ください。
@@ -61,8 +61,6 @@ poetry install
pipでも依存関係のインストールが可能です: pipでも依存関係のインストールが可能です:
**注意**:`faiss 1.7.2``macOS``Segmentation Fault: 11`を起こすので、マニュアルインストールする場合は、 `pip install faiss-cpu==1.7.0`を実行してください。
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
``` ```

100
docs/README.ko.han.md Normal file
View File

@@ -0,0 +1,100 @@
<div align="center">
<h1>Retrieval-based-Voice-Conversion-WebUI</h1>
VITS基盤의 簡單하고使用하기 쉬운音聲變換틀<br><br>
[![madewithlove](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
<img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
[![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/github/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb)
[![Licence](https://img.shields.io/github/license/liujing04/Retrieval-based-Voice-Conversion-WebUI?style=for-the-badge)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/%E4%BD%BF%E7%94%A8%E9%9C%80%E9%81%B5%E5%AE%88%E7%9A%84%E5%8D%8F%E8%AE%AE-LICENSE.txt)
[![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)
[![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk)
</div>
------
[**更新日誌**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md)
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
> [示範映像](https://www.bilibili.com/video/BV1pm4y1z7Gm/)을 確認해 보세요!
> RVC를活用한實時間音聲變換: [w-okada/voice-changer](https://github.com/w-okada/voice-changer)
> 基本모델은 50時間假量의 高品質 오픈 소스 VCTK 데이터셋을 使用하였으므로, 著作權上의 念慮가 없으니 安心하고 使用하시기 바랍니다.
> 著作權問題가 없는 高品質의 노래를 以後에도 繼續해서 訓練할 豫定입니다.
## 紹介
本Repo는 다음과 같은 特徵을 가지고 있습니다:
+ top1檢索을利用하여 入力音色特徵을 訓練세트音色特徵으로 代替하여 音色의漏出을 防止;
+ 相對的으로 낮은性能의 GPU에서도 빠른訓練可能;
+ 적은量의 데이터로 訓練해도 좋은 結果를 얻을 수 있음 (最小10分以上의 低雜음音聲데이터를 使用하는 것을 勸獎);
+ 모델融合을通한 音色의 變調可能 (ckpt處理탭->ckpt混合選擇);
+ 使用하기 쉬운 WebUI (웹 使用者인터페이스);
+ UVR5 모델을 利用하여 목소리와 背景音樂의 빠른 分離;
## 環境의準備
poetry를通해 依存를設置하는 것을 勸獎합니다.
다음命令은 Python 버전3.8以上의環境에서 實行되어야 합니다:
```bash
# PyTorch 關聯主要依存設置, 이미設置되어 있는 境遇 건너뛰기 可能
# 參照: https://pytorch.org/get-started/locally/
pip install torch torchvision torchaudio
# Windows + Nvidia Ampere Architecture(RTX30xx)를 使用하고 있다面, #21 에서 명시된 것과 같이 PyTorch에 맞는 CUDA 버전을 指定해야 합니다.
#pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
# Poetry 設置, 이미設置되어 있는 境遇 건너뛰기 可能
# Reference: https://python-poetry.org/docs/#installation
curl -sSL https://install.python-poetry.org | python3 -
# 依存設置
poetry install
```
pip를 活用하여依存를 設置하여도 無妨합니다.
```bash
pip install -r requirements.txt
```
## 其他預備모델準備
RVC 모델은 推論과訓練을 依하여 다른 預備모델이 必要합니다.
[Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 通해서 다운로드 할 수 있습니다.
다음은 RVC에 必要한 預備모델 및 其他 파일 目錄입니다:
```bash
hubert_base.pt
./pretrained
./uvr5_weights
# Windows를 使用하는境遇 이 사전도 必要할 수 있습니다. FFmpeg가 設置되어 있으면 건너뛰어도 됩니다.
ffmpeg.exe
```
그後 以下의 命令을 使用하여 WebUI를 始作할 수 있습니다:
```bash
python infer-web.py
```
Windows를 使用하는境遇 `RVC-beta.7z`를 다운로드 및 壓縮解除하여 RVC를 直接使用하거나 `go-web.bat`을 使用하여 WebUi를 直接할 수 있습니다.
## 參考
+ [ContentVec](https://github.com/auspicious3000/contentvec/)
+ [VITS](https://github.com/jaywalnut310/vits)
+ [HIFIGAN](https://github.com/jik876/hifi-gan)
+ [Gradio](https://github.com/gradio-app/gradio)
+ [FFmpeg](https://github.com/FFmpeg/FFmpeg)
+ [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
+ [audio-slicer](https://github.com/openvpi/audio-slicer)
## 모든寄與者분들의勞力에感謝드립니다
<a href="https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
<img src="https://contrib.rocks/image?repo=liujing04/Retrieval-based-Voice-Conversion-WebUI" />
</a>

View File

@@ -4,9 +4,9 @@
VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.<br><br> VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.<br><br>
[![madewithlove](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI) [![madewithlove](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
<img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br> <img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
[![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/github/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb) [![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/github/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb)
[![Licence](https://img.shields.io/github/license/liujing04/Retrieval-based-Voice-Conversion-WebUI?style=for-the-badge)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/%E4%BD%BF%E7%94%A8%E9%9C%80%E9%81%B5%E5%AE%88%E7%9A%84%E5%8D%8F%E8%AE%AE-LICENSE.txt) [![Licence](https://img.shields.io/github/license/liujing04/Retrieval-based-Voice-Conversion-WebUI?style=for-the-badge)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/%E4%BD%BF%E7%94%A8%E9%9C%80%E9%81%B5%E5%AE%88%E7%9A%84%E5%8D%8F%E8%AE%AE-LICENSE.txt)
[![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/) [![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)
@@ -15,10 +15,11 @@ VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.<b
</div> </div>
------ ---
[**업데이트 로그**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md)
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) [**업데이트 로그**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_KO.md)
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
> [데모 영상](https://www.bilibili.com/video/BV1pm4y1z7Gm/)을 확인해 보세요! > [데모 영상](https://www.bilibili.com/video/BV1pm4y1z7Gm/)을 확인해 보세요!
@@ -29,18 +30,22 @@ VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.<b
> 저작권 문제가 없는 고퀄리티의 노래를 이후에도 계속해서 훈련할 예정입니다. > 저작권 문제가 없는 고퀄리티의 노래를 이후에도 계속해서 훈련할 예정입니다.
## 소개 ## 소개
본 Repo는 다음과 같은 특징을 가지고 있습니다: 본 Repo는 다음과 같은 특징을 가지고 있습니다:
+ top1 검색을 이용하여 입력 소스 기능을 훈련 세트 기능으로 대체하여 음색의 누출을 방지;
+ 상대적으로 낮은 성능의 GPU에서도 빠른 훈련 가능; - top1 검색을 이용하여 입력 음색 특징을 훈련 세트 음색 특징으로 대체하여 음색의 누출을 방지;
+ 적은 양의 데이터로 훈련해도 좋은 결과를 얻을 수 있음 (최소 10분 이상의 저잡음 음성 데이터를 사용하는 것을 권장); - 상대적으로 낮은 성능의 GPU에서도 빠른 훈련 가능;
+ 모델 융합을 통한 음색의 변조 가능 (ckpt 처리 탭->ckpt 병합 선택); - 적은 양의 데이터로 훈련해도 좋은 결과를 얻을 수 있음 (최소 10분 이상의 저잡음 음성 데이터를 사용하는 것을 권장);
+ 사용하기 쉬운 WebUI (웹 인터페이스); - 모델 융합을 통한 음색의 변조 가능 (ckpt 처리 탭->ckpt 병합 선택);
+ UVR5 모델을 이용하여 목소리와 배경음악의 빠른 분리; - 사용하기 쉬운 WebUI (웹 인터페이스);
- UVR5 모델을 이용하여 목소리와 배경음악의 빠른 분리;
## 환경의 준비 ## 환경의 준비
poetry를 통해 dependecies를 설치하는 것을 권장합니다. poetry를 통해 dependecies를 설치하는 것을 권장합니다.
다음 명령은 Python 버전 3.8 이상의 환경에서 실행되어야 합니다: 다음 명령은 Python 버전 3.8 이상의 환경에서 실행되어야 합니다:
```bash ```bash
# PyTorch 관련 주요 dependencies 설치, 이미 설치되어 있는 경우 건너뛰기 가능 # PyTorch 관련 주요 dependencies 설치, 이미 설치되어 있는 경우 건너뛰기 가능
# 참조: https://pytorch.org/get-started/locally/ # 참조: https://pytorch.org/get-started/locally/
@@ -56,49 +61,52 @@ curl -sSL https://install.python-poetry.org | python3 -
# Dependecies 설치 # Dependecies 설치
poetry install poetry install
``` ```
pip를 활용하여 dependencies를 설치하여도 무방합니다.
**공지**: `MacOS`에서 `faiss 1.7.2`용하면 Segmentation Fault: 11 오류가 발생할 수 있습니다. 수동으로 pip를 사용하여 설치하는 경우 `pip install faiss-cpu==1.7.0`을 사용해야 합니다. pip용하여 dependencies를 설치하여도 무방합니다.
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
``` ```
## 기타 사전 모델 준비 ## 기타 사전 모델 준비
RVC 모델은 추론과 훈련을 위하여 다른 사전 모델이 필요합니다. RVC 모델은 추론과 훈련을 위하여 다른 사전 모델이 필요합니다.
[Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 통해서 다운로드 할 수 있습니다. [Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 통해서 다운로드 할 수 있습니다.
다음은 RVC에 필요한 사전 모델 및 기타 파일 목록입니다: 다음은 RVC에 필요한 사전 모델 및 기타 파일 목록입니다:
```bash ```bash
hubert_base.pt hubert_base.pt
./pretrained ./pretrained
./uvr5_weights ./uvr5_weights
# Windows를 사용하는 경우 이 사전도 필요할 수 있습니다. FFmpeg가 설치되어 있으면 건너뛰어도 됩니다. # Windows를 사용하는 경우 이 사전도 필요할 수 있습니다. FFmpeg가 설치되어 있으면 건너뛰어도 됩니다.
ffmpeg.exe ffmpeg.exe
``` ```
그 후 이하의 명령을 사용하여 WebUI를 시작할 수 있습니다: 그 후 이하의 명령을 사용하여 WebUI를 시작할 수 있습니다:
```bash ```bash
python infer-web.py python infer-web.py
``` ```
Windows를 사용하는 경우 `RVC-beta.7z`를 다운로드 및 압축 해제하여 RVC를 직접 사용하거나 `go-web.bat`을 사용하여 WebUi를 시작할 수 있습니다. Windows를 사용하는 경우 `RVC-beta.7z`를 다운로드 및 압축 해제하여 RVC를 직접 사용하거나 `go-web.bat`을 사용하여 WebUi를 시작할 수 있습니다.
중국어로 된 RVC에 대한 튜토리얼도 있으니 필요하다면 확인할 수 있습니다. ## 참고
- [ContentVec](https://github.com/auspicious3000/contentvec/)
- [VITS](https://github.com/jaywalnut310/vits)
- [HIFIGAN](https://github.com/jik876/hifi-gan)
- [Gradio](https://github.com/gradio-app/gradio)
- [FFmpeg](https://github.com/FFmpeg/FFmpeg)
- [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
- [audio-slicer](https://github.com/openvpi/audio-slicer)
## 크레딧
+ [ContentVec](https://github.com/auspicious3000/contentvec/)
+ [VITS](https://github.com/jaywalnut310/vits)
+ [HIFIGAN](https://github.com/jik876/hifi-gan)
+ [Gradio](https://github.com/gradio-app/gradio)
+ [FFmpeg](https://github.com/FFmpeg/FFmpeg)
+ [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
+ [audio-slicer](https://github.com/openvpi/audio-slicer)
## 모든 기여자 분들의 노력에 감사드립니다. ## 모든 기여자 분들의 노력에 감사드립니다.
<a href="https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank"> <a href="https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
<img src="https://contrib.rocks/image?repo=liujing04/Retrieval-based-Voice-Conversion-WebUI" /> <img src="https://contrib.rocks/image?repo=liujing04/Retrieval-based-Voice-Conversion-WebUI" />
</a> </a>

View File

@@ -12,10 +12,7 @@ In '/logs/your-experiment/3_feature256' where the model is located, features ext
From here we read the npy files in order sorted by filename and concatenate the vectors to create big_npy. (This vector has shape [N, 256].) From here we read the npy files in order sorted by filename and concatenate the vectors to create big_npy. (This vector has shape [N, 256].)
After saving big_npy as /logs/your-experiment/total_fea.npy, train it with faiss. After saving big_npy as /logs/your-experiment/total_fea.npy, train it with faiss.
As of 2023/04/18, IVF based on L2 distance is used using the index factory function of faiss. In this article, I will explain the meaning of these parameters.
The number of IVF divisions (n_ivf) is N//39, and n_probe uses int(np.power(n_ivf, 0.3)). (Look around train_index in infer-web.py.)
In this article, I will first explain the meaning of these parameters, and then write advice for developers to create a better index.
# Explanation of the method # Explanation of the method
## index factory ## index factory
@@ -103,44 +100,3 @@ https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-co
## RFlat ## RFlat
RFlat is an instruction to recalculate the rough distance calculated by FastScan with the exact distance specified by the third argument of index factory. RFlat is an instruction to recalculate the rough distance calculated by FastScan with the exact distance specified by the third argument of index factory.
When getting k neighbors, k*k_factor points are recalculated. When getting k neighbors, k*k_factor points are recalculated.
# Techniques for embedding
## alpha query expansion
Query expansion is a technique used in searches, for example in full-text searches, where a few words are added to the entered search sentence to improve search accuracy. Several methods have also been proposed for vector search, among which α-query expansion is known as a highly effective method that does not require additional learning. In the paper, it is introduced in [Attention-Based Query Expansion Learning](https://arxiv.org/abs/2007.08019), etc., and [2nd place solution of kaggle shopee competition](https://www.kaggle.com/code/lyakaap/2nd-place-solution/notebook).
α-query expansion can be done by summing a vector with neighboring vectors with weights raised to the power of similarity. How to paste the code example. Replace big_npy with α query expansion.
```python
alpha = 3.
index = faiss.index_factory(256, "IVF512,PQ128x4fs,RFlat")
original_norm = np.maximum(np.linalg.norm(big_npy, ord=2, axis=1, keepdims=True), 1e-9)
big_npy /= original_norm
index.train(big_npy)
index.add(big_npy)
dist, neighbor = index.search(big_npy, num_expand)
expand_arrays = []
ixs = np.arange(big_npy.shape[0])
for i in range(-(-big_npy.shape[0]//batch_size)):
ix = ixs[i*batch_size:(i+1)*batch_size]
weight = np.power(np.einsum("nd,nmd->nm", big_npy[ix], big_npy[neighbor[ix]]), alpha)
expand_arrays.append(np.sum(big_npy[neighbor[ix]] * np.expand_dims(weight, axis=2),axis=1))
big_npy = np.concatenate(expand_arrays, axis=0)
# normalize index version
big_npy = big_npy / np.maximum(np.linalg.norm(big_npy, ord=2, axis=1, keepdims=True), 1e-9)
```
This is a technique that can be applied both to the query that does the search and to the DB being searched.
## Compress embedding with MiniBatch KMeans
If total_fea.npy is too large, it is possible to shrink the vector using KMeans.
Compression of embedding is possible with the following code. Specify the size you want to compress for n_clusters, and specify 256 * number of CPU cores for batch_size to fully benefit from CPU parallelization.
```python
import multiprocessing
from sklearn.cluster import MiniBatchKMeans
kmeans = MiniBatchKMeans(n_clusters=10000, batch_size=256 * multiprocessing.cpu_count(), init="random")
kmeans.fit(big_npy)
sample_npy = kmeans.cluster_centers_
```

View File

@@ -9,13 +9,9 @@ RVCではHuBERTで変換した特徴量のEmbeddingに対し、学習データ
# 実装のoverview # 実装のoverview
モデルが配置されている '/logs/your-experiment/3_feature256'には各音声データからHuBERTで抽出された特徴量が配置されています。 モデルが配置されている '/logs/your-experiment/3_feature256'には各音声データからHuBERTで抽出された特徴量が配置されています。
ここからnpyファイルをファイル名でソートした順番で読み込み、ベクトルを連結してbig_npyを作成します。(このベクトルのshapeは[N, 256]です。) ここからnpyファイルをファイル名でソートした順番で読み込み、ベクトルを連結してbig_npyを作成しfaissを学習させます。(このベクトルのshapeは[N, 256]です。)
big_npyを/logs/your-experiment/total_fea.npyとして保存した後、faissを学習させます。
2023/04/18時点ではfaissのindex factoryの機能を用いて、L2距離に基づくIVFを用いています。 本Tipsではまずこれらのパラメータの意味を解説します。
IVFの分割数(n_ivf)はN//39で、n_probeはint(np.power(n_ivf, 0.3))が採用されています。(infer-web.pyのtrain_index周りを探してください。)
本Tipsではまずこれらのパラメータの意味を解説し、その後よりよいindexを作成するための開発者向けアドバイスを書きます。
# 手法の解説 # 手法の解説
## index factory ## index factory
@@ -103,44 +99,3 @@ https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-co
## RFlat ## RFlat
RFlatはFastScanで計算した大まかな距離を、index factoryの第三引数で指定した正確な距離で再計算する指示です。 RFlatはFastScanで計算した大まかな距離を、index factoryの第三引数で指定した正確な距離で再計算する指示です。
k個の近傍を取得する際は、k*k_factor個の点について再計算が行われます。 k個の近傍を取得する際は、k*k_factor個の点について再計算が行われます。
# Embeddingに関するテクニック
## alpha query expansion
クエリ拡張は検索で使われるテクニックで、例えば全文検索では入力された検索文に単語を幾つか追加することで検索精度を上げることがあります。ベクトル検索にもいくつか提唱されていて、その内追加の学習がいらず効果が高い手法としてα-query expansionが知られています。論文では[Attention-Based Query Expansion Learning](https://arxiv.org/abs/2007.08019)などで紹介されていて、[kaggleのshopeeコンペの2位の解法](https://www.kaggle.com/code/lyakaap/2nd-place-solution/notebook)にも用いられていました。
α-query expansionはあるベクトルに対し、近傍のベクトルを類似度のα乗した重みで足し合わせることでできます。いかにコードの例を張ります。big_npyをα query expansionしたものに置き換えます。
```python
alpha = 3.
index = faiss.index_factory(256, "IVF512,PQ128x4fs,RFlat")
original_norm = np.maximum(np.linalg.norm(big_npy, ord=2, axis=1, keepdims=True), 1e-9)
big_npy /= original_norm
index.train(big_npy)
index.add(big_npy)
dist, neighbor = index.search(big_npy, num_expand)
expand_arrays = []
ixs = np.arange(big_npy.shape[0])
for i in range(-(-big_npy.shape[0]//batch_size)):
ix = ixs[i*batch_size:(i+1)*batch_size]
weight = np.power(np.einsum("nd,nmd->nm", big_npy[ix], big_npy[neighbor[ix]]), alpha)
expand_arrays.append(np.sum(big_npy[neighbor[ix]] * np.expand_dims(weight, axis=2),axis=1))
big_npy = np.concatenate(expand_arrays, axis=0)
# normalize index version
big_npy = big_npy / np.maximum(np.linalg.norm(big_npy, ord=2, axis=1, keepdims=True), 1e-9)
```
これは、検索を行うクエリにも、検索対象のDBにも適応可能なテクニックです。
## MiniBatch KMeansによるembeddingの圧縮
total_fea.npyが大きすぎる場合、KMeansを用いてベクトルを小さくすることが可能です。
以下のコードで、embeddingの圧縮が可能です。n_clustersは圧縮したい大きさを指定し、batch_sizeは256 * CPUのコア数を指定することでCPUの並列化の恩恵を十分に得ることができます。
```python
import multiprocessing
from sklearn.cluster import MiniBatchKMeans
kmeans = MiniBatchKMeans(n_clusters=10000, batch_size=256 * multiprocessing.cpu_count(), init="random")
kmeans.fit(big_npy)
sample_npy = kmeans.cluster_centers_
```

89
docs/faq.md Normal file
View File

@@ -0,0 +1,89 @@
## Q1:ffmpeg error/utf8 error.
大概率不是ffmpeg问题而是音频路径问题<br>
ffmpeg读取路径带空格、()等特殊符号可能出现ffmpeg error训练集音频带中文路径在写入filelist.txt的时候可能出现utf8 error<br>
## Q2:一键训练结束没有索引
显示"Training is done. The program is closed."则模型训练成功,后续紧邻的报错是假的;<br>
一键训练结束完成没有added开头的索引文件可能是因为训练集太大卡住了添加索引的步骤已通过批处理add索引解决内存add索引对内存需求过大的问题。临时可尝试再次点击"训练索引"按钮。<br>
## Q3:训练结束推理没看到训练集的音色
点刷新音色再看看如果还没有看看训练有没有报错控制台和webui的截图logs/实验名下的log都可以发给开发者看看。<br>
## Q4:如何分享模型
rvc_root/logs/实验名 下面存储的pth不是用来分享模型用来推理的而是为了存储实验状态供复现以及继续训练用的。用来分享的模型应该是weights文件夹下大小为60+MB的pth文件<br>
后续将把weights/exp_name.pth和logs/exp_name/added_xxx.index合并打包成weights/exp_name.zip省去填写index的步骤那么zip文件用来分享不要分享pth文件除非是想换机器继续训练<br>
如果你把logs文件夹下的几百MB的pth文件复制/分享到weights文件夹下强行用于推理可能会出现f0tgt_sr等各种key不存在的报错。你需要用ckpt选项卡最下面手工或自动本地logs下如果能找到相关信息则会自动选择是否携带音高、目标音频采样率的选项后进行ckpt小模型提取输入路径填G开头的那个提取完在weights文件夹下会出现60+MB的pth文件刷新音色后可以选择使用。<br>
## Q5:Connection Error.
也许你关闭了控制台(黑色窗口)。<br>
## Q6:WebUI弹出Expecting value: line 1 column 1 (char 0).
请关闭系统局域网代理/全局代理。<br>
这个不仅是客户端的代理也包括服务端的代理例如你使用autodl设置了http_proxy和https_proxy学术加速使用时也需要unset关掉<br>
## Q7:不用WebUI如何通过命令训练推理
训练脚本:<br>
可先跑通WebUI消息窗内会显示数据集处理和训练用命令行<br>
推理脚本:<br>
https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/myinfer.py<br>
例子:<br>
runtime\python.exe myinfer.py 0 "E:\codes\py39\RVC-beta\todo-songs\1111.wav" "E:\codes\py39\logs\mi-test\added_IVF677_Flat_nprobe_7.index" harvest "test.wav" "weights/mi-test.pth" 0.6 cuda:0 True<br>
f0up_key=sys.argv[1]<br>
input_path=sys.argv[2]<br>
index_path=sys.argv[3]<br>
f0method=sys.argv[4]#harvest or pm<br>
opt_path=sys.argv[5]<br>
model_path=sys.argv[6]<br>
index_rate=float(sys.argv[7])<br>
device=sys.argv[8]<br>
is_half=bool(sys.argv[9])<br>
## Q8:Cuda error/Cuda out of memory.
小概率是cuda配置问题、设备不支持大概率是显存不够out of memory<br>
训练的话缩小batch size如果缩小到1还不够只能更换显卡训练推理的话酌情缩小config.py结尾的x_padx_queryx_centerx_max。4G以下显存例如10603G和各种2G显卡可以直接放弃4G显存显卡还有救。<br>
## Q9:total_epoch调多少比较好
如果训练集音质差底噪大20~30足够了调太高底模音质无法带高你的低音质训练集<br>
如果训练集音质高底噪低时长多可以调高200是ok的训练速度很快既然你有条件准备高音质训练集显卡想必条件也不错肯定不在乎多一些训练时间<br>
## Q10:需要多少训练集时长
推荐10min至50min<br>
  保证音质高底噪低的情况下,如果有个人特色的音色统一,则多多益善<br>
  高水平的训练集(精简+音色有特色5min至10min也是ok的仓库作者本人就经常这么玩<br>
也有人拿1min至2min的数据来训练并且训练成功的但是成功经验是其他人不可复现的不太具备参考价值。这要求训练集音色特色非常明显比如说高频气声较明显的萝莉少女音且音质高<br>
1min以下时长数据目前没见有人尝试成功过。不建议进行这种鬼畜行为。<br>
## Q11:index rate干嘛用的怎么调科普
  如果底模和推理源的音质高于训练集的音质,他们可以带高推理结果的音质,但代价可能是音色往底模/推理源的音色靠,这种现象叫做"音色泄露"<br>
index rate用来削减/解决音色泄露问题。调到1则理论上不存在推理源的音色泄露问题但音质更倾向于训练集。如果训练集音质比推理源低则index rate调高可能降低音质。调到0则不具备利用检索混合来保护训练集音色的效果<br>
如果训练集优质时长多可调高total_epoch此时模型本身不太会引用推理源和底模的音色很少存在"音色泄露"问题此时index_rate不重要你甚至可以不建立/分享index索引文件。<br>
## Q11:推理怎么选gpu
config.py文件里device cuda:后面选择卡号;<br>
卡号和显卡的映射关系,在训练选项卡的显卡信息栏里能看到。<br>
## Q12:如何推理训练中间保存的pth
通过ckpt选项卡最下面提取小模型。<br>
## Q13:如何中断和继续训练
现阶段只能关闭WebUI控制台双击go-web.bat重启程序。网页参数也要刷新重新填写<br>
继续训练相同网页参数点训练模型就会接着上次的checkpoint继续训练。<br>
## Q14:训练时出现文件页面/内存error
进程开太多了,内存炸了。你可能可以通过如下方式解决<br>
1、"提取音高和处理数据使用的CPU进程数" 酌情拉低;<br>
2、训练集音频手工切一下不要太长。<br>

95
docs/faq_en.md Normal file
View File

@@ -0,0 +1,95 @@
## Q1:ffmpeg error/utf8 error.
It is most likely not a FFmpeg issue, but rather an audio path issue;
FFmpeg may encounter an error when reading paths containing special characters like spaces and (), which may cause an FFmpeg error; and when the training set's audio contains Chinese paths, writing it into filelist.txt may cause a utf8 error.<br>
## Q2:Cannot find index file after "One-click Training".
If it displays "Training is done. The program is closed," then the model has been trained successfully, and the subsequent errors are fake;
The lack of an 'added' index file after One-click training may be due to the training set being too large, causing the addition of the index to get stuck; this has been resolved by using batch processing to add the index, which solves the problem of memory overload when adding the index. As a temporary solution, try clicking the "Train Index" button again.<br>
## Q3:Cannot find the model in “Inferencing timbre” after training
Click “Refresh timbre list” and check again; if still not visible, check if there are any errors during training and send screenshots of the console, web UI, and logs/experiment_name/*.log to the developers for further analysis.<br>
## Q4:How to share a model/How to use others' models?
The pth files stored in rvc_root/logs/experiment_name are not meant for sharing or inference, but for storing the experiment checkpoits for reproducibility and further training. The model to be shared should be the 60+MB pth file in the weights folder;
In the future, weights/exp_name.pth and logs/exp_name/added_xxx.index will be merged into a single weights/exp_name.zip file to eliminate the need for manual index input; so share the zip file, not the pth file, unless you want to continue training on a different machine;
Copying/sharing the several hundred MB pth files from the logs folder to the weights folder for forced inference may result in errors such as missing f0, tgt_sr, or other keys. You need to use the ckpt tab at the bottom to manually or automatically (if the information is found in the logs/exp_name), select whether to include pitch infomation and target audio sampling rate options and then extract the smaller model. After extraction, there will be a 60+ MB pth file in the weights folder, and you can refresh the voices to use it.<br>
## Q5:Connection Error.
You may have closed the console (black command line window).<br>
## Q6:WebUI popup 'Expecting value: line 1 column 1 (char 0)'.
Please disable system LAN proxy/global proxy and then refresh.<br>
## Q7:How to train and infer without the WebUI?
Training script:<br>
You can run training in WebUI first, and the command-line versions of dataset preprocessing and training will be displayed in the message window.<br>
Inference script:<br>
https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/myinfer.py<br>
e.g.<br>
runtime\python.exe myinfer.py 0 "E:\codes\py39\RVC-beta\todo-songs\1111.wav" "E:\codes\py39\logs\mi-test\added_IVF677_Flat_nprobe_7.index" harvest "test.wav" "weights/mi-test.pth" 0.6 cuda:0 True<br>
f0up_key=sys.argv[1]<br>
input_path=sys.argv[2]<br>
index_path=sys.argv[3]<br>
f0method=sys.argv[4]#harvest or pm<br>
opt_path=sys.argv[5]<br>
model_path=sys.argv[6]<br>
index_rate=float(sys.argv[7])<br>
device=sys.argv[8]<br>
is_half=bool(sys.argv[9])<br>
## Q8:Cuda error/Cuda out of memory.
There is a small chance that there is a problem with the CUDA configuration or the device is not supported; more likely, there is not enough memory (out of memory).<br>
For training, reduce the batch size (if reducing to 1 is still not enough, you may need to change the graphics card); for inference, adjust the x_pad, x_query, x_center, and x_max settings in the config.py file as needed. 4G or lower memory cards (e.g. 1060(3G) and various 2G cards) can be abandoned, while 4G memory cards still have a chance.<br>
## Q9:How many total_epoch are optimal?
If the training dataset's audio quality is poor and the noise floor is high, 20-30 epochs are sufficient. Setting it too high won't improve the audio quality of your low-quality training set.<br>
If the training set audio quality is high, the noise floor is low, and there is sufficient duration, you can increase it. 200 is acceptable (since training is fast, and if you're able to prepare a high-quality training set, your GPU likely can handle a longer training duration without issue).<br>
## Q10:How much training set duration is needed?
A dataset of around 10min to 50min is recommended.<br>
With guaranteed high sound quality and low bottom noise, more can be added if the dataset's timbre is uniform.<br>
For a high-level training set (lean + distinctive tone), 5min to 10min is fine.<br>
There are some people who have trained successfully with 1min to 2min data, but the success is not reproducible by others and is not very informative. <br>This requires that the training set has a very distinctive timbre (e.g. a high-frequency airy anime girl sound) and the quality of the audio is high;
Data of less than 1min duration has not been successfully attempted so far. This is not recommended.<br>
## Q11:What is the index rate for and how to adjust it?
If the tone quality of the pre-trained model and inference source is higher than that of the training set, they can bring up the tone quality of the inference result, but at the cost of a possible tone bias towards the tone of the underlying model/inference source rather than the tone of the training set, which is generally referred to as "tone leakage".<br>
The index rate is used to reduce/resolve the timbre leakage problem. If the index rate is set to 1, theoretically there is no timbre leakage from the inference source and the timbre quality is more biased towards the training set. If the training set has a lower sound quality than the inference source, then a higher index rate may reduce the sound quality. Turning it down to 0 does not have the effect of using retrieval blending to protect the training set tones.<br>
If the training set has good audio quality and long duration, turn up the total_epoch, when the model itself is less likely to refer to the inferred source and the pretrained underlying model, and there is little "tone leakage", the index_rate is not important and you can even not create/share the index file.<br>
## Q12:How to choose the gpu when inferring?
In the config.py file, select the card number after "device cuda:".<br>
The mapping between card number and graphics card can be seen in the graphics card information section of the training tab.<br>
## Q13:How to use the model saved in the middle of training?
Save via model extraction at the bottom of the ckpt processing tab.
## Q14:File/memory error(when training)?
Too many processes and your memory is not enough. You may fix it by:
1、decrease the input in field "Threads of CPU".
2、pre-cut trainset to shorter audio files.

View File

@@ -6,8 +6,12 @@ This TIPS explains how data training is done.
I will explain along the steps in the training tab of the GUI. I will explain along the steps in the training tab of the GUI.
## step1 ## step1
Set the experiment name here. You can also set here whether the model should take pitch into account. Set the experiment name here.
Data for each experiment is placed in `/logs/experiment name/`.
You can also set here whether the model should take pitch into account.
If the model doesn't consider pitch, the model will be lighter, but not suitable for singing.
Data for each experiment is placed in `/logs/your-experiment-name/`.
## step2a ## step2a
Loads and preprocesses audio. Loads and preprocesses audio.
@@ -23,14 +27,14 @@ After converting to int16 with ffmpeg, convert to float32 and normalize between
The audio is smoothed by scipy's filtfilt. The audio is smoothed by scipy's filtfilt.
### Audio Split ### Audio Split
First, the input audio is divided by detecting parts of silence that last longer than a certain period (max_sil_kept=5 seconds?). After splitting the audio on silence, split the audio every 4 seconds with an overlap of 0.3 seconds. For audio separated within 4 seconds, after normalizing the volume, convert the wav file to `/logs/experiment name/0_gt_wavs` and then convert it to 16k sampling rate to `/logs/experiment name/1_16k_wavs ` as a wav file. First, the input audio is divided by detecting parts of silence that last longer than a certain period (max_sil_kept=5 seconds?). After splitting the audio on silence, split the audio every 4 seconds with an overlap of 0.3 seconds. For audio separated within 4 seconds, after normalizing the volume, convert the wav file to `/logs/your-experiment-name/0_gt_wavs` and then convert it to 16k sampling rate to `/logs/your-experiment-name/1_16k_wavs ` as a wav file.
## step2b ## step2b
### Extract pitch ### Extract pitch
Extract pitch information from wav files. Extract the pitch information (=f0) using the method built into parselmouth or pyworld and save it in `/logs/experiment name/2a_f0`. Then logarithmically convert the pitch information to an integer between 1 and 255 and save it in `/logs/experiment name/2b-f0nsf`. Extract pitch information from wav files. Extract the pitch information (=f0) using the method built into parselmouth or pyworld and save it in `/logs/your-experiment-name/2a_f0`. Then logarithmically convert the pitch information to an integer between 1 and 255 and save it in `/logs/your-experiment-name/2b-f0nsf`.
### Extract feature_print ### Extract feature_print
Convert the wav file to embedding in advance using HuBERT. Read the wav file saved in `/logs/experiment name/1_16k_wavs`, convert the wav file to 256-dimensional features with HuBERT, and save in npy format in `/logs/experiment name/3_feature256`. Convert the wav file to embedding in advance using HuBERT. Read the wav file saved in `/logs/your-experiment-name/1_16k_wavs`, convert the wav file to 256-dimensional features with HuBERT, and save in npy format in `/logs/your-experiment-name/3_feature256`.
## step3 ## step3
train the model. train the model.
@@ -40,11 +44,20 @@ In deep learning, the data set is divided and the learning proceeds little by li
Therefore, the learning time is the learning time per step x (the number of data in the dataset / batch size) x the number of epochs. In general, the larger the batch size, the more stable the learning becomes (learning time per step ÷ batch size) becomes smaller, but it uses more GPU memory. GPU RAM can be checked with the nvidia-smi command. Learning can be done in a short time by increasing the batch size as much as possible according to the machine of the execution environment. Therefore, the learning time is the learning time per step x (the number of data in the dataset / batch size) x the number of epochs. In general, the larger the batch size, the more stable the learning becomes (learning time per step ÷ batch size) becomes smaller, but it uses more GPU memory. GPU RAM can be checked with the nvidia-smi command. Learning can be done in a short time by increasing the batch size as much as possible according to the machine of the execution environment.
### Specify pretrained model ### Specify pretrained model
RVC starts training the model from pretrained weights instead of from 0, so it can be trained with a small dataset. By default it loads `rvc-location/pretrained/f0G40k.pth` and `rvc-location/pretrained/f0D40k.pth`. When learning, model parameters are saved in `logs/experiment name/G_{}.pth` and `logs/experiment name/D_{}.pth` for each save_every_epoch, but by specifying this path, you can start learning. You can restart or start training from model weights learned in a different experiment. RVC starts training the model from pretrained weights instead of from 0, so it can be trained with a small dataset.
By default
- If you consider pitch, it loads `rvc-location/pretrained/f0G40k.pth` and `rvc-location/pretrained/f0D40k.pth`.
- If you don't consider pitch, it loads `rvc-location/pretrained/f0G40k.pth` and `rvc-location/pretrained/f0D40k.pth`.
When learning, model parameters are saved in `logs/your-experiment-name/G_{}.pth` and `logs/your-experiment-name/D_{}.pth` for each save_every_epoch, but by specifying this path, you can start learning. You can restart or start training from model weights learned in a different experiment.
### learning index ### learning index
RVC saves the HuBERT feature values used during training, and during inference, searches for feature values that are similar to the feature values used during learning to perform inference. In order to perform this search at high speed, the index is learned in advance. RVC saves the HuBERT feature values used during training, and during inference, searches for feature values that are similar to the feature values used during learning to perform inference. In order to perform this search at high speed, the index is learned in advance.
For index learning, we use the approximate neighborhood search library faiss. Read the feature value of `/logs/experiment name/3_feature256`, save the combined feature value as `/logs/experiment name/total_fea.npy`, and use it to learn the index `/logs/experiment name Save it as /add_XXX.index`. For index learning, we use the approximate neighborhood search library faiss. Read the feature value of `logs/your-experiment-name/3_feature256` and use it to learn the index, and save it as `logs/your-experiment-name/add_XXX.index`.
(From the 20230428update version, it is read from the index, and saving / specifying is no longer necessary.)
### Button description ### Button description
- Train model: After executing step2b, press this button to train the model. - Train model: After executing step2b, press this button to train the model.

View File

@@ -6,7 +6,10 @@ RVCの訓練における説明、およびTIPS
GUIの訓練タブのstepに沿って説明します。 GUIの訓練タブのstepに沿って説明します。
## step1 ## step1
実験名の設定を行います。また、モデルにピッチを考慮させるかもここで設定できます。 実験名の設定を行います。
また、モデルに音高ガイド(ピッチ)を考慮させるかもここで設定できます。考慮させない場合はモデルは軽量になりますが、歌唱には向かなくなります。
各実験のデータは`/logs/実験名/`に配置されます。 各実験のデータは`/logs/実験名/`に配置されます。
## step2a ## step2a
@@ -40,11 +43,19 @@ HuBERTを用いてwavファイルを事前にembeddingに変換します。`/log
そのため、学習時間は 1step当たりの学習時間 x (データセット内のデータ数 ÷ バッチサイズ) x epoch数 かかります。一般にバッチサイズを大きくするほど学習は安定し、(1step当たりの学習時間÷バッチサイズ)は小さくなりますが、その分GPUのメモリを多く使用します。GPUのRAMはnvidia-smiコマンド等で確認できます。実行環境のマシンに合わせてバッチサイズをできるだけ大きくするとより短時間で学習が可能です。 そのため、学習時間は 1step当たりの学習時間 x (データセット内のデータ数 ÷ バッチサイズ) x epoch数 かかります。一般にバッチサイズを大きくするほど学習は安定し、(1step当たりの学習時間÷バッチサイズ)は小さくなりますが、その分GPUのメモリを多く使用します。GPUのRAMはnvidia-smiコマンド等で確認できます。実行環境のマシンに合わせてバッチサイズをできるだけ大きくするとより短時間で学習が可能です。
### pretrained modelの指定 ### pretrained modelの指定
RVCではモデルの訓練を0からではなく、事前学習済みの重みから開始するため、少ないデータセットで学習を行えます。デフォルトでは`RVCのある場所/pretrained/f0G40k.pth``RVCのある場所/pretrained/f0D40k.pth`を読み込みます。学習時はsave_every_epochごとにモデルのパラメータが`logs/実験名/G_{}.pth``logs/実験名/D_{}.pth`に保存されますが、このパスを指定することで学習を再開したり、もしくは違う実験で学習したモデルの重みから学習を開始できます。 RVCではモデルの訓練を0からではなく、事前学習済みの重みから開始するため、少ないデータセットで学習を行えます。
デフォルトでは
- 音高ガイドを考慮する場合、`RVCのある場所/pretrained/f0G40k.pth``RVCのある場所/pretrained/f0D40k.pth`を読み込みます。
- 音高ガイドを考慮しない場合、`RVCのある場所/pretrained/G40k.pth``RVCのある場所/pretrained/D40k.pth`を読み込みます。
学習時はsave_every_epochごとにモデルのパラメータが`logs/実験名/G_{}.pth``logs/実験名/D_{}.pth`に保存されますが、このパスを指定することで学習を再開したり、もしくは違う実験で学習したモデルの重みから学習を開始できます。
### indexの学習 ### indexの学習
RVCでは学習時に使われたHuBERTの特徴量を保存し、推論時は学習時の特徴量から近い特徴量を探してきて推論を行います。この検索を高速に行うために事前にindexの学習を行います。 RVCでは学習時に使われたHuBERTの特徴量を保存し、推論時は学習時の特徴量から近い特徴量を探してきて推論を行います。この検索を高速に行うために事前にindexの学習を行います。
indexの学習には近似近傍探索ライブラリのfaissを用います。`/logs/実験名/3_feature256`の特徴量を読み込み、全て結合させた特徴量を`/logs/実験名/total_fea.npy`として保存、それを用いて学習したindexを`/logs/実験名/add_XXX.index`として保存します。 indexの学習には近似近傍探索ライブラリのfaissを用います。`/logs/実験名/3_feature256`の特徴量を読み込み、それを用いて学習したindexを`/logs/実験名/add_XXX.index`として保存します。
(20230428updateよりtotal_fea.npyはindexから読み込むので不要になりました。)
### ボタンの説明 ### ボタンの説明
- モデルのトレーニング: step2bまでを実行した後、このボタンを押すとモデルの学習を行います。 - モデルのトレーニング: step2bまでを実行した後、このボタンを押すとモデルの学習を行います。

View File

@@ -30,6 +30,9 @@ set g32=f0G32k.pth
set g40=f0G40k.pth set g40=f0G40k.pth
set g48=f0G48k.pth set g48=f0G48k.pth
set d40v2=f0D40k.pth
set g40v2=f0G40k.pth
set dld32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth set dld32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth
set dld40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth set dld40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth
set dld48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth set dld48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth
@@ -37,11 +40,24 @@ set dlg32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretra
set dlg40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth set dlg40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth
set dlg48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth set dlg48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth
set hp2=HP2-人声vocals+非人声instrumentals.pth set dld40v2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth
set hp5=HP5-主旋律人声vocals+其他instrumentals.pth set dlg40v2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth
set dlhp2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth set hp2_all=HP2_all_vocals.pth
set dlhp5=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth set hp3_all=HP3_all_vocals.pth
set hp5_only=HP5_only_main_vocal.pth
set VR_DeEchoAggressive=VR-DeEchoAggressive.pth
set VR_DeEchoDeReverb=VR-DeEchoDeReverb.pth
set VR_DeEchoNormal=VR-DeEchoNormal.pth
set onnx_dereverb=vocals.onnx
set dlhp2_all=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2_all_vocals.pth
set dlhp3_all=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP3_all_vocals.pth
set dlhp5_only=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5_only_main_vocal.pth
set dlVR_DeEchoAggressive=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoAggressive.pth
set dlVR_DeEchoDeReverb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoDeReverb.pth
set dlVR_DeEchoNormal=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoNormal.pth
set dlonnx_dereverb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/onnx_dereverb_By_FoxJoy/vocals.onnx
set hb=hubert_base.pt set hb=hubert_base.pt
@@ -56,12 +72,24 @@ if exist "%~dp0pretrained" (
echo failed. generating dir .\pretrained. echo failed. generating dir .\pretrained.
mkdir pretrained mkdir pretrained
) )
if exist "%~dp0pretrained_v2" (
echo dir .\pretrained_v2 checked.
) else (
echo failed. generating dir .\pretrained_v2.
mkdir pretrained_v2
)
if exist "%~dp0uvr5_weights" ( if exist "%~dp0uvr5_weights" (
echo dir .\uvr5_weights checked. echo dir .\uvr5_weights checked.
) else ( ) else (
echo failed. generating dir .\uvr5_weights. echo failed. generating dir .\uvr5_weights.
mkdir uvr5_weights mkdir uvr5_weights
) )
if exist "%~dp0uvr5_weights\onnx_dereverb_By_FoxJoy" (
echo dir .\uvr5_weights\onnx_dereverb_By_FoxJoy checked.
) else (
echo failed. generating dir .\uvr5_weights\onnx_dereverb_By_FoxJoy.
mkdir uvr5_weights\onnx_dereverb_By_FoxJoy
)
echo= echo=
echo dir check finished. echo dir check finished.
@@ -89,7 +117,17 @@ if exist "%~dp0pretrained\D40k.pth" (
if exist "%~dp0pretrained\D40k.pth" (echo download successful.) else (echo please try again! if exist "%~dp0pretrained\D40k.pth" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking D48k.pth echo checking D40k.pth
if exist "%~dp0pretrained_v2\D40k.pth" (
echo D40k.pth in .\pretrained_v2 checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d %~dp0pretrained_v2 -o D40k.pth
if exist "%~dp0pretrained_v2\D40k.pth" (echo download successful.) else (echo please try again!
echo=)
)
echo checking D48k.pth
if exist "%~dp0pretrained\D48k.pth" ( if exist "%~dp0pretrained\D48k.pth" (
echo D48k.pth in .\pretrained checked. echo D48k.pth in .\pretrained checked.
echo= echo=
@@ -99,7 +137,7 @@ if exist "%~dp0pretrained\D48k.pth" (
if exist "%~dp0pretrained\D48k.pth" (echo download successful.) else (echo please try again! if exist "%~dp0pretrained\D48k.pth" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking G32k.pth echo checking G32k.pth
if exist "%~dp0pretrained\G32k.pth" ( if exist "%~dp0pretrained\G32k.pth" (
echo G32k.pth in .\pretrained checked. echo G32k.pth in .\pretrained checked.
echo= echo=
@@ -109,7 +147,7 @@ if exist "%~dp0pretrained\G32k.pth" (
if exist "%~dp0pretrained\G32k.pth" (echo download successful.) else (echo please try again! if exist "%~dp0pretrained\G32k.pth" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking G40k.pth echo checking G40k.pth
if exist "%~dp0pretrained\G40k.pth" ( if exist "%~dp0pretrained\G40k.pth" (
echo G40k.pth in .\pretrained checked. echo G40k.pth in .\pretrained checked.
echo= echo=
@@ -119,7 +157,17 @@ if exist "%~dp0pretrained\G40k.pth" (
if exist "%~dp0pretrained\G40k.pth" (echo download successful.) else (echo please try again! if exist "%~dp0pretrained\G40k.pth" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking G48k.pth echo checking G40k.pth
if exist "%~dp0pretrained_v2\G40k.pth" (
echo G40k.pth in .\pretrained_v2 checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d %~dp0pretrained_v2 -o G40k.pth
if exist "%~dp0pretrained_v2\G40k.pth" (echo download successful.) else (echo please try again!
echo=)
)
echo checking G48k.pth
if exist "%~dp0pretrained\G48k.pth" ( if exist "%~dp0pretrained\G48k.pth" (
echo G48k.pth in .\pretrained checked. echo G48k.pth in .\pretrained checked.
echo= echo=
@@ -150,6 +198,16 @@ if exist "%~dp0pretrained\%d40%" (
if exist "%~dp0pretrained\%d40%" (echo download successful.) else (echo please try again! if exist "%~dp0pretrained\%d40%" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking %d40v2%
if exist "%~dp0pretrained_v2\%d40v2%" (
echo %d40v2% in .\pretrained_v2 checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dld40v2% -d %~dp0pretrained_v2 -o %d40v2%
if exist "%~dp0pretrained_v2\%d40v2%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %d48% echo checking %d48%
if exist "%~dp0pretrained\%d48%" ( if exist "%~dp0pretrained\%d48%" (
echo %d48% in .\pretrained checked. echo %d48% in .\pretrained checked.
@@ -180,6 +238,16 @@ if exist "%~dp0pretrained\%g40%" (
if exist "%~dp0pretrained\%g40%" (echo download successful.) else (echo please try again! if exist "%~dp0pretrained\%g40%" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking %g40v2%
if exist "%~dp0pretrained_v2\%g40v2%" (
echo %g40v2% in .\pretrained_v2 checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlg40v2% -d %~dp0pretrained_v2 -o %g40v2%
if exist "%~dp0pretrained_v2\%g40v2%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %g48% echo checking %g48%
if exist "%~dp0pretrained\%g48%" ( if exist "%~dp0pretrained\%g48%" (
echo %g48% in .\pretrained checked. echo %g48% in .\pretrained checked.
@@ -191,26 +259,76 @@ if exist "%~dp0pretrained\%g48%" (
echo=) echo=)
) )
echo checking %hp2% echo checking %hp2_all%
if exist "%~dp0uvr5_weights\%hp2%" ( if exist "%~dp0uvr5_weights\%hp2_all%" (
echo %hp2% in .\uvr5_weights checked. echo %hp2_all% in .\uvr5_weights checked.
echo= echo=
) else ( ) else (
echo failed. starting download from huggingface. echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp2% -d %~dp0\uvr5_weights -o %hp2% %~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp2_all% -d %~dp0\uvr5_weights -o %hp2_all%
if exist "%~dp0uvr5_weights\%hp2%" (echo download successful.) else (echo please try again! if exist "%~dp0uvr5_weights\%hp2_all%" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking %hp5% echo checking %hp3_all%
if exist "%~dp0uvr5_weights\%hp5%" ( if exist "%~dp0uvr5_weights\%hp3_all%" (
echo %hp5% in .\uvr5_weights checked. echo %hp3_all% in .\uvr5_weights checked.
echo= echo=
) else ( ) else (
echo failed. starting download from huggingface. echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp5% -d %~dp0\uvr5_weights -o %HP5% %~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp3_all% -d %~dp0\uvr5_weights -o %hp3_all%
if exist "%~dp0uvr5_weights\%hp5%" (echo download successful.) else (echo please try again! if exist "%~dp0uvr5_weights\%hp3_all%" (echo download successful.) else (echo please try again!
echo=) echo=)
) )
echo checking %hp5_only%
if exist "%~dp0uvr5_weights\%hp5_only%" (
echo %hp5_only% in .\uvr5_weights checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp5_only% -d %~dp0\uvr5_weights -o %hp5_only%
if exist "%~dp0uvr5_weights\%hp5_only%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %VR_DeEchoAggressive%
if exist "%~dp0uvr5_weights\%VR_DeEchoAggressive%" (
echo %VR_DeEchoAggressive% in .\uvr5_weights checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoAggressive% -d %~dp0\uvr5_weights -o %VR_DeEchoAggressive%
if exist "%~dp0uvr5_weights\%VR_DeEchoAggressive%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %VR_DeEchoDeReverb%
if exist "%~dp0uvr5_weights\%VR_DeEchoDeReverb%" (
echo %VR_DeEchoDeReverb% in .\uvr5_weights checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoDeReverb% -d %~dp0\uvr5_weights -o %VR_DeEchoDeReverb%
if exist "%~dp0uvr5_weights\%VR_DeEchoDeReverb%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %VR_DeEchoNormal%
if exist "%~dp0uvr5_weights\%VR_DeEchoNormal%" (
echo %VR_DeEchoNormal% in .\uvr5_weights checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoNormal% -d %~dp0\uvr5_weights -o %VR_DeEchoNormal%
if exist "%~dp0uvr5_weights\%VR_DeEchoNormal%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %onnx_dereverb%
if exist "%~dp0uvr5_weights\onnx_dereverb_By_FoxJoy\%onnx_dereverb%" (
echo %onnx_dereverb% in .\uvr5_weights\onnx_dereverb_By_FoxJoy checked.
echo=
) else (
echo failed. starting download from huggingface.
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlonnx_dereverb% -d %~dp0\uvr5_weights\onnx_dereverb_By_FoxJoy -o %onnx_dereverb%
if exist "%~dp0uvr5_weights\onnx_dereverb_By_FoxJoy\%onnx_dereverb%" (echo download successful.) else (echo please try again!
echo=)
)
echo checking %hb% echo checking %hb%
if exist "%~dp0%hb%" ( if exist "%~dp0%hb%" (
@@ -227,4 +345,4 @@ echo required files check finished.
echo envfiles check complete. echo envfiles check complete.
pause pause
:end :end
del flag.txt del flag.txt

View File

@@ -1,5 +1,4 @@
from infer_pack.models_onnx_moess import SynthesizerTrnMs256NSFsidM from infer_pack.models_onnx import SynthesizerTrnMsNSFsidM
from infer_pack.models_onnx import SynthesizerTrnMs256NSFsidO
import torch import torch
if __name__ == "__main__": if __name__ == "__main__":
@@ -21,65 +20,35 @@ if __name__ == "__main__":
device = "cpu" # 导出时设备(不影响使用模型) device = "cpu" # 导出时设备(不影响使用模型)
if MoeVS: net_g = SynthesizerTrnMsNSFsidM(
net_g = SynthesizerTrnMs256NSFsidM( *cpt["config"], is_half=False
*cpt["config"], is_half=False ) # fp32导出C++要支持fp16必须手动将内存重新排列所以暂时不用fp16
) # fp32导出C++要支持fp16必须手动将内存重新排列所以暂时不用fp16 net_g.load_state_dict(cpt["weight"], strict=False)
net_g.load_state_dict(cpt["weight"], strict=False) input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"] output_names = [
output_names = [ "audio",
"audio", ]
] # net_g.construct_spkmixmap(n_speaker) 多角色混合轨道导出
torch.onnx.export( torch.onnx.export(
net_g, net_g,
( (
test_phone.to(device), test_phone.to(device),
test_phone_lengths.to(device), test_phone_lengths.to(device),
test_pitch.to(device), test_pitch.to(device),
test_pitchf.to(device), test_pitchf.to(device),
test_ds.to(device), test_ds.to(device),
test_rnd.to(device), test_rnd.to(device),
), ),
ExportedPath, ExportedPath,
dynamic_axes={ dynamic_axes={
"phone": [1], "phone": [1],
"pitch": [1], "pitch": [1],
"pitchf": [1], "pitchf": [1],
"rnd": [2], "rnd": [2],
}, },
do_constant_folding=False, do_constant_folding=False,
opset_version=16, opset_version=16,
verbose=False, verbose=False,
input_names=input_names, input_names=input_names,
output_names=output_names, output_names=output_names,
) )
else:
net_g = SynthesizerTrnMs256NSFsidO(
*cpt["config"], is_half=False
) # fp32导出C++要支持fp16必须手动将内存重新排列所以暂时不用fp16
net_g.load_state_dict(cpt["weight"], strict=False)
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds"]
output_names = [
"audio",
]
torch.onnx.export(
net_g,
(
test_phone.to(device),
test_phone_lengths.to(device),
test_pitch.to(device),
test_pitchf.to(device),
test_ds.to(device),
),
ExportedPath,
dynamic_axes={
"phone": [1],
"pitch": [1],
"pitchf": [1],
},
do_constant_folding=False,
opset_version=16,
verbose=False,
input_names=input_names,
output_names=output_names,
)

View File

@@ -1,47 +0,0 @@
from infer_pack.models_onnx_moess import SynthesizerTrnMs256NSFsidM
import torch
person = "Shiroha/shiroha.pth"
exported_path = "model.onnx"
cpt = torch.load(person, map_location="cpu")
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
print(*cpt["config"])
net_g = SynthesizerTrnMs256NSFsidM(*cpt["config"], is_half=False)
net_g.load_state_dict(cpt["weight"], strict=False)
test_phone = torch.rand(1, 200, 256)
test_phone_lengths = torch.tensor([200]).long()
test_pitch = torch.randint(size=(1, 200), low=5, high=255)
test_pitchf = torch.rand(1, 200)
test_ds = torch.LongTensor([0])
test_rnd = torch.rand(1, 192, 200)
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
output_names = [
"audio",
]
device = "cpu"
torch.onnx.export(
net_g,
(
test_phone.to(device),
test_phone_lengths.to(device),
test_pitch.to(device),
test_pitchf.to(device),
test_ds.to(device),
test_rnd.to(device),
),
exported_path,
dynamic_axes={
"phone": [1],
"pitch": [1],
"pitchf": [1],
"rnd": [2],
},
do_constant_folding=False,
opset_version=16,
verbose=False,
input_names=input_names,
output_names=output_names,
)

View File

@@ -1,5 +1,8 @@
import os, traceback, sys, parselmouth import os, traceback, sys, parselmouth
import librosa
now_dir = os.getcwd()
sys.path.append(now_dir)
from my_utils import load_audio
import pyworld import pyworld
from scipy.io import wavfile from scipy.io import wavfile
import numpy as np, logging import numpy as np, logging
@@ -33,17 +36,14 @@ class FeatureInput(object):
self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700) self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700)
def compute_f0(self, path, f0_method): def compute_f0(self, path, f0_method):
# default resample type of librosa.resample is "soxr_hq". x = load_audio(path, self.fs)
# Quality: soxr_vhq > soxr_hq
x, sr = librosa.load(path, self.fs) # , res_type='soxr_vhq'
p_len = x.shape[0] // self.hop p_len = x.shape[0] // self.hop
assert sr == self.fs
if f0_method == "pm": if f0_method == "pm":
time_step = 160 / 16000 * 1000 time_step = 160 / 16000 * 1000
f0_min = 50 f0_min = 50
f0_max = 1100 f0_max = 1100
f0 = ( f0 = (
parselmouth.Sound(x, sr) parselmouth.Sound(x, self.fs)
.to_pitch_ac( .to_pitch_ac(
time_step=time_step / 1000, time_step=time_step / 1000,
voicing_threshold=0.6, voicing_threshold=0.6,
@@ -60,19 +60,19 @@ class FeatureInput(object):
elif f0_method == "harvest": elif f0_method == "harvest":
f0, t = pyworld.harvest( f0, t = pyworld.harvest(
x.astype(np.double), x.astype(np.double),
fs=sr, fs=self.fs,
f0_ceil=self.f0_max, f0_ceil=self.f0_max,
f0_floor=self.f0_min, f0_floor=self.f0_min,
frame_period=1000 * self.hop / sr, frame_period=1000 * self.hop / self.fs,
) )
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs) f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs)
elif f0_method == "dio": elif f0_method == "dio":
f0, t = pyworld.dio( f0, t = pyworld.dio(
x.astype(np.double), x.astype(np.double),
fs=sr, fs=self.fs,
f0_ceil=self.f0_max, f0_ceil=self.f0_max,
f0_floor=self.f0_min, f0_floor=self.f0_min,
frame_period=1000 * self.hop / sr, frame_period=1000 * self.hop / self.fs,
) )
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs) f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs)
return f0 return f0
@@ -86,7 +86,7 @@ class FeatureInput(object):
# use 0 or 1 # use 0 or 1
f0_mel[f0_mel <= 1] = 1 f0_mel[f0_mel <= 1] = 1
f0_mel[f0_mel > self.f0_bin - 1] = self.f0_bin - 1 f0_mel[f0_mel > self.f0_bin - 1] = self.f0_bin - 1
f0_coarse = np.rint(f0_mel).astype(np.int) f0_coarse = np.rint(f0_mel).astype(int)
assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, ( assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, (
f0_coarse.max(), f0_coarse.max(),
f0_coarse.min(), f0_coarse.min(),
@@ -154,7 +154,7 @@ if __name__ == "__main__":
f0method, f0method,
), ),
) )
p.start()
ps.append(p) ps.append(p)
for p in ps: p.start()
p.join() for i in range(n_p):
ps[i].join()

View File

@@ -5,11 +5,12 @@ n_part = int(sys.argv[2])
i_part = int(sys.argv[3]) i_part = int(sys.argv[3])
if len(sys.argv) == 5: if len(sys.argv) == 5:
exp_dir = sys.argv[4] exp_dir = sys.argv[4]
version = sys.argv[5]
else: else:
i_gpu = sys.argv[4] i_gpu = sys.argv[4]
exp_dir = sys.argv[5] exp_dir = sys.argv[5]
os.environ["CUDA_VISIBLE_DEVICES"] = str(i_gpu) os.environ["CUDA_VISIBLE_DEVICES"] = str(i_gpu)
version = sys.argv[6]
import torch import torch
import torch.nn.functional as F import torch.nn.functional as F
import soundfile as sf import soundfile as sf
@@ -18,6 +19,13 @@ from fairseq import checkpoint_utils
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if torch.cuda.is_available():
device = "cuda"
elif torch.backends.mps.is_available():
device = "mps"
else:
device = "cpu"
f = open("%s/extract_f0_feature.log" % exp_dir, "a+") f = open("%s/extract_f0_feature.log" % exp_dir, "a+")
@@ -32,7 +40,9 @@ model_path = "hubert_base.pt"
printt(exp_dir) printt(exp_dir)
wavPath = "%s/1_16k_wavs" % exp_dir wavPath = "%s/1_16k_wavs" % exp_dir
outPath = "%s/3_feature256" % exp_dir outPath = (
"%s/3_feature256" % exp_dir if version == "v1" else "%s/3_feature768" % exp_dir
)
os.makedirs(outPath, exist_ok=True) os.makedirs(outPath, exist_ok=True)
@@ -53,6 +63,13 @@ def readwave(wav_path, normalize=False):
# HuBERT model # HuBERT model
printt("load model(s) from {}".format(model_path)) printt("load model(s) from {}".format(model_path))
# if hubert model is exist
if os.access(model_path, os.F_OK) == False:
printt(
"Error: Extracting is shut down because %s does not exist, you may download it from https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main"
% model_path
)
exit(0)
models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task( models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
[model_path], [model_path],
suffix="", suffix="",
@@ -60,7 +77,7 @@ models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
model = models[0] model = models[0]
model = model.to(device) model = model.to(device)
printt("move model to %s" % device) printt("move model to %s" % device)
if device != "cpu": if device not in ["mps", "cpu"]:
model = model.half() model = model.half()
model.eval() model.eval()
@@ -83,14 +100,16 @@ else:
padding_mask = torch.BoolTensor(feats.shape).fill_(False) padding_mask = torch.BoolTensor(feats.shape).fill_(False)
inputs = { inputs = {
"source": feats.half().to(device) "source": feats.half().to(device)
if device != "cpu" if device not in ["mps", "cpu"]
else feats.to(device), else feats.to(device),
"padding_mask": padding_mask.to(device), "padding_mask": padding_mask.to(device),
"output_layer": 9, # layer 9 "output_layer": 9 if version == "v1" else 12, # layer 9
} }
with torch.no_grad(): with torch.no_grad():
logits = model.extract_features(**inputs) logits = model.extract_features(**inputs)
feats = model.final_proj(logits[0]) feats = (
model.final_proj(logits[0]) if version == "v1" else logits[0]
)
feats = feats.squeeze(0).float().cpu().numpy() feats = feats.squeeze(0).float().cpu().numpy()
if np.isnan(feats).sum() == 0: if np.isnan(feats).sum() == 0:

250
gui.py
View File

@@ -1,7 +1,24 @@
import os, sys """
0416后的更新
引入config中half
重建npy而不用填写
v2支持
无f0模型支持
修复
int16
增加无索引支持
f0算法改harvest(怎么看就只有这个会影响CPU占用),但是不这么改效果不好
"""
import os, sys, traceback, re
import json
now_dir = os.getcwd() now_dir = os.getcwd()
sys.path.append(now_dir) sys.path.append(now_dir)
from config import Config
Config = Config()
import PySimpleGUI as sg import PySimpleGUI as sg
import sounddevice as sd import sounddevice as sd
import noisereduce as nr import noisereduce as nr
@@ -12,12 +29,19 @@ import torch.nn.functional as F
import torchaudio.transforms as tat import torchaudio.transforms as tat
import scipy.signal as signal import scipy.signal as signal
# import matplotlib.pyplot as plt # import matplotlib.pyplot as plt
from infer_pack.models import SynthesizerTrnMs256NSFsid, SynthesizerTrnMs256NSFsid_nono from infer_pack.models import (
SynthesizerTrnMs256NSFsid,
SynthesizerTrnMs256NSFsid_nono,
SynthesizerTrnMs768NSFsid,
SynthesizerTrnMs768NSFsid_nono,
)
from i18n import I18nAuto from i18n import I18nAuto
i18n = I18nAuto() i18n = I18nAuto()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
current_dir = os.getcwd()
class RVC: class RVC:
@@ -38,7 +62,8 @@ class RVC:
self.window = 160 self.window = 160
if index_rate != 0: if index_rate != 0:
self.index = faiss.read_index(index_path) self.index = faiss.read_index(index_path)
self.big_npy = np.load(npy_path) # self.big_npy = np.load(npy_path)
self.big_npy = self.index.reconstruct_n(0, self.index.ntotal)
print("index search enabled") print("index search enabled")
self.index_rate = index_rate self.index_rate = index_rate
model_path = hubert_path model_path = hubert_path
@@ -49,22 +74,39 @@ class RVC:
) )
self.model = models[0] self.model = models[0]
self.model = self.model.to(device) self.model = self.model.to(device)
self.model = self.model.half() if Config.is_half:
self.model = self.model.half()
else:
self.model = self.model.float()
self.model.eval() self.model.eval()
cpt = torch.load(pth_path, map_location="cpu") cpt = torch.load(pth_path, map_location="cpu")
self.tgt_sr = cpt["config"][-1] self.tgt_sr = cpt["config"][-1]
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
self.if_f0 = cpt.get("f0", 1) self.if_f0 = cpt.get("f0", 1)
if self.if_f0 == 1: self.version = cpt.get("version", "v1")
self.net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=True) if self.version == "v1":
else: if self.if_f0 == 1:
self.net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"]) self.net_g = SynthesizerTrnMs256NSFsid(
*cpt["config"], is_half=Config.is_half
)
else:
self.net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
elif self.version == "v2":
if self.if_f0 == 1:
self.net_g = SynthesizerTrnMs768NSFsid(
*cpt["config"], is_half=Config.is_half
)
else:
self.net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
del self.net_g.enc_q del self.net_g.enc_q
print(self.net_g.load_state_dict(cpt["weight"], strict=False)) print(self.net_g.load_state_dict(cpt["weight"], strict=False))
self.net_g.eval().to(device) self.net_g.eval().to(device)
self.net_g.half() if Config.is_half:
except Exception as e: self.net_g = self.net_g.half()
print(e) else:
self.net_g = self.net_g.float()
except:
print(traceback.format_exc())
def get_f0(self, x, f0_up_key, inp_f0=None): def get_f0(self, x, f0_up_key, inp_f0=None):
x_pad = 1 x_pad = 1
@@ -112,28 +154,45 @@ class RVC:
assert feats.dim() == 1, feats.dim() assert feats.dim() == 1, feats.dim()
feats = feats.view(1, -1) feats = feats.view(1, -1)
padding_mask = torch.BoolTensor(feats.shape).fill_(False) padding_mask = torch.BoolTensor(feats.shape).fill_(False)
if Config.is_half:
feats = feats.half()
else:
feats = feats.float()
inputs = { inputs = {
"source": feats.half().to(device), "source": feats.to(device),
"padding_mask": padding_mask.to(device), "padding_mask": padding_mask.to(device),
"output_layer": 9, # layer 9 "output_layer": 9 if self.version == "v1" else 12,
} }
torch.cuda.synchronize() torch.cuda.synchronize()
with torch.no_grad(): with torch.no_grad():
logits = self.model.extract_features(**inputs) logits = self.model.extract_features(**inputs)
feats = self.model.final_proj(logits[0]) feats = (
self.model.final_proj(logits[0]) if self.version == "v1" else logits[0]
)
####索引优化 ####索引优化
if hasattr(self, "index") and hasattr(self, "big_npy") and self.index_rate != 0: try:
npy = feats[0].cpu().numpy().astype("float32") if (
_, I = self.index.search(npy, 1) hasattr(self, "index")
npy = self.big_npy[I.squeeze()].astype("float16") and hasattr(self, "big_npy")
feats = ( and self.index_rate != 0
torch.from_numpy(npy).unsqueeze(0).to(device) * self.index_rate ):
+ (1 - self.index_rate) * feats npy = feats[0].cpu().numpy().astype("float32")
) score, ix = self.index.search(npy, k=8)
else: weight = np.square(1 / score)
print("index search FAIL or disabled") weight /= weight.sum(axis=1, keepdims=True)
npy = np.sum(self.big_npy[ix] * np.expand_dims(weight, axis=2), axis=1)
if Config.is_half:
npy = npy.astype("float16")
feats = (
torch.from_numpy(npy).unsqueeze(0).to(device) * self.index_rate
+ (1 - self.index_rate) * feats
)
else:
print("index search FAIL or disabled")
except:
traceback.print_exc()
print("index search FAIL")
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1) feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
torch.cuda.synchronize() torch.cuda.synchronize()
print(feats.shape) print(feats.shape)
@@ -169,7 +228,7 @@ class RVC:
return infered_audio return infered_audio
class Config: class GUIConfig:
def __init__(self) -> None: def __init__(self) -> None:
self.hubert_path: str = "" self.hubert_path: str = ""
self.pth_path: str = "" self.pth_path: str = ""
@@ -189,12 +248,34 @@ class Config:
class GUI: class GUI:
def __init__(self) -> None: def __init__(self) -> None:
self.config = Config() self.config = GUIConfig()
self.flag_vc = False self.flag_vc = False
self.launcher() self.launcher()
def load(self):
input_devices, output_devices, _, _ = self.get_devices()
try:
with open("values1.json", "r") as j:
data = json.load(j)
except:
with open("values1.json", "w") as j:
data = {
"pth_path": " ",
"index_path": " ",
"sg_input_device": input_devices[sd.default.device[0]],
"sg_output_device": output_devices[sd.default.device[1]],
"threhold": "-45",
"pitch": "0",
"index_rate": "0",
"block_time": "1",
"crossfade_length": "0.04",
"extra_time": "1",
}
return data
def launcher(self): def launcher(self):
data = self.load()
sg.theme("LightBlue3") sg.theme("LightBlue3")
input_devices, output_devices, _, _ = self.get_devices() input_devices, output_devices, _, _ = self.get_devices()
layout = [ layout = [
@@ -204,27 +285,49 @@ class GUI:
layout=[ layout=[
[ [
sg.Input( sg.Input(
default_text="TEMP\\hubert_base.pt", key="hubert_path" default_text="hubert_base.pt",
key="hubert_path",
disabled=True,
),
sg.FileBrowse(
i18n("Hubert模型"),
initial_folder=os.path.join(os.getcwd()),
file_types=((". pt"),),
), ),
sg.FileBrowse(i18n("Hubert模型")),
],
[
sg.Input(default_text="TEMP\\atri.pth", key="pth_path"),
sg.FileBrowse(i18n("选择.pth文件")),
], ],
[ [
sg.Input( sg.Input(
default_text="TEMP\\added_IVF512_Flat_atri_baseline_src_feat.index", default_text=data.get("pth_path", ""),
key="pth_path",
),
sg.FileBrowse(
i18n("选择.pth文件"),
initial_folder=os.path.join(os.getcwd(), "weights"),
file_types=((". pth"),),
),
],
[
sg.Input(
default_text=data.get("index_path", ""),
key="index_path", key="index_path",
), ),
sg.FileBrowse(i18n("选择.index文件")), sg.FileBrowse(
i18n("选择.index文件"),
initial_folder=os.path.join(os.getcwd(), "logs"),
file_types=((". index"),),
),
], ],
[ [
sg.Input( sg.Input(
default_text="TEMP\\big_src_feature_atri.npy", default_text="你不需要填写这个You don't need write this.",
key="npy_path", key="npy_path",
disabled=True,
),
sg.FileBrowse(
i18n("选择.npy文件"),
initial_folder=os.path.join(os.getcwd(), "logs"),
file_types=((". npy"),),
), ),
sg.FileBrowse(i18n("选择.npy文件")),
], ],
], ],
) )
@@ -237,7 +340,7 @@ class GUI:
sg.Combo( sg.Combo(
input_devices, input_devices,
key="sg_input_device", key="sg_input_device",
default_value=input_devices[sd.default.device[0]], default_value=data.get("sg_input_device", ""),
), ),
], ],
[ [
@@ -245,7 +348,7 @@ class GUI:
sg.Combo( sg.Combo(
output_devices, output_devices,
key="sg_output_device", key="sg_output_device",
default_value=output_devices[sd.default.device[1]], default_value=data.get("sg_output_device", ""),
), ),
], ],
], ],
@@ -262,7 +365,7 @@ class GUI:
key="threhold", key="threhold",
resolution=1, resolution=1,
orientation="h", orientation="h",
default_value=-30, default_value=data.get("threhold", ""),
), ),
], ],
[ [
@@ -272,7 +375,7 @@ class GUI:
key="pitch", key="pitch",
resolution=1, resolution=1,
orientation="h", orientation="h",
default_value=12, default_value=data.get("pitch", ""),
), ),
], ],
[ [
@@ -282,7 +385,7 @@ class GUI:
key="index_rate", key="index_rate",
resolution=0.01, resolution=0.01,
orientation="h", orientation="h",
default_value=0.5, default_value=data.get("index_rate", ""),
), ),
], ],
], ],
@@ -297,7 +400,7 @@ class GUI:
key="block_time", key="block_time",
resolution=0.1, resolution=0.1,
orientation="h", orientation="h",
default_value=1.0, default_value=data.get("block_time", ""),
), ),
], ],
[ [
@@ -307,7 +410,7 @@ class GUI:
key="crossfade_length", key="crossfade_length",
resolution=0.01, resolution=0.01,
orientation="h", orientation="h",
default_value=0.08, default_value=data.get("crossfade_length", ""),
), ),
], ],
[ [
@@ -317,7 +420,7 @@ class GUI:
key="extra_time", key="extra_time",
resolution=0.01, resolution=0.01,
orientation="h", orientation="h",
default_value=0.05, default_value=data.get("extra_time", ""),
), ),
], ],
[ [
@@ -335,7 +438,6 @@ class GUI:
sg.Text("0", key="infer_time"), sg.Text("0", key="infer_time"),
], ],
] ]
self.window = sg.Window("RVC - GUI", layout=layout) self.window = sg.Window("RVC - GUI", layout=layout)
self.event_handler() self.event_handler()
@@ -346,16 +448,45 @@ class GUI:
self.flag_vc = False self.flag_vc = False
exit() exit()
if event == "start_vc" and self.flag_vc == False: if event == "start_vc" and self.flag_vc == False:
self.set_values(values) if self.set_values(values) == True:
print(str(self.config.__dict__)) print("using_cuda:" + str(torch.cuda.is_available()))
print("using_cuda:" + str(torch.cuda.is_available())) self.start_vc()
self.start_vc() settings = {
"pth_path": values["pth_path"],
"index_path": values["index_path"],
"sg_input_device": values["sg_input_device"],
"sg_output_device": values["sg_output_device"],
"threhold": values["threhold"],
"pitch": values["pitch"],
"index_rate": values["index_rate"],
"block_time": values["block_time"],
"crossfade_length": values["crossfade_length"],
"extra_time": values["extra_time"],
}
with open("values1.json", "w") as j:
json.dump(settings, j)
if event == "stop_vc" and self.flag_vc == True: if event == "stop_vc" and self.flag_vc == True:
self.flag_vc = False self.flag_vc = False
def set_values(self, values): def set_values(self, values):
if len(values["pth_path"].strip()) == 0:
sg.popup(i18n("请选择pth文件"))
return False
if len(values["index_path"].strip()) == 0:
sg.popup(i18n("请选择index文件"))
return False
pattern = re.compile("[^\x00-\x7F]+")
if pattern.findall(values["hubert_path"]):
sg.popup(i18n("hubert模型路径不可包含中文"))
return False
if pattern.findall(values["pth_path"]):
sg.popup(i18n("pth文件路径不可包含中文"))
return False
if pattern.findall(values["index_path"]):
sg.popup(i18n("index文件路径不可包含中文"))
return False
self.set_devices(values["sg_input_device"], values["sg_output_device"]) self.set_devices(values["sg_input_device"], values["sg_output_device"])
self.config.hubert_path = values["hubert_path"] self.config.hubert_path = os.path.join(current_dir, "hubert_base.pt")
self.config.pth_path = values["pth_path"] self.config.pth_path = values["pth_path"]
self.config.index_path = values["index_path"] self.config.index_path = values["index_path"]
self.config.npy_path = values["npy_path"] self.config.npy_path = values["npy_path"]
@@ -367,6 +498,7 @@ class GUI:
self.config.I_noise_reduce = values["I_noise_reduce"] self.config.I_noise_reduce = values["I_noise_reduce"]
self.config.O_noise_reduce = values["O_noise_reduce"] self.config.O_noise_reduce = values["O_noise_reduce"]
self.config.index_rate = values["index_rate"] self.config.index_rate = values["index_rate"]
return True
def start_vc(self): def start_vc(self):
torch.cuda.empty_cache() torch.cuda.empty_cache()
@@ -375,9 +507,7 @@ class GUI:
self.crossfade_frame = int(self.config.crossfade_time * self.config.samplerate) self.crossfade_frame = int(self.config.crossfade_time * self.config.samplerate)
self.sola_search_frame = int(0.012 * self.config.samplerate) self.sola_search_frame = int(0.012 * self.config.samplerate)
self.delay_frame = int(0.01 * self.config.samplerate) # 往前预留0.02s self.delay_frame = int(0.01 * self.config.samplerate) # 往前预留0.02s
self.extra_frame = int( self.extra_frame = int(self.config.extra_time * self.config.samplerate)
self.config.extra_time * self.config.samplerate
)
self.rvc = None self.rvc = None
self.rvc = RVC( self.rvc = RVC(
self.config.pitch, self.config.pitch,
@@ -408,7 +538,9 @@ class GUI:
orig_freq=self.config.samplerate, new_freq=16000, dtype=torch.float32 orig_freq=self.config.samplerate, new_freq=16000, dtype=torch.float32
) )
self.resampler2 = tat.Resample( self.resampler2 = tat.Resample(
orig_freq=self.rvc.tgt_sr, new_freq=self.config.samplerate, dtype=torch.float32 orig_freq=self.rvc.tgt_sr,
new_freq=self.config.samplerate,
dtype=torch.float32,
) )
thread_vc = threading.Thread(target=self.soundinput) thread_vc = threading.Thread(target=self.soundinput)
thread_vc.start() thread_vc.start()
@@ -531,10 +663,14 @@ class GUI:
if d["max_output_channels"] > 0 if d["max_output_channels"] > 0
] ]
input_devices_indices = [ input_devices_indices = [
d["index"] for d in devices if d["max_input_channels"] > 0 d["index"] if "index" in d else d["name"]
for d in devices
if d["max_input_channels"] > 0
] ]
output_devices_indices = [ output_devices_indices = [
d["index"] for d in devices if d["max_output_channels"] > 0 d["index"] if "index" in d else d["name"]
for d in devices
if d["max_output_channels"] > 0
] ]
return ( return (
input_devices, input_devices,

View File

@@ -18,8 +18,11 @@ class I18nAuto:
if not os.path.exists(f"./i18n/{language}.json"): if not os.path.exists(f"./i18n/{language}.json"):
language = "en_US" language = "en_US"
self.language = language self.language = language
print("Use Language:", language) # print("Use Language:", language)
self.language_map = load_language_list(language) self.language_map = load_language_list(language)
def __call__(self, key): def __call__(self, key):
return self.language_map[key] return self.language_map.get(key, key)
def print(self):
print("Use Language:", self.language)

View File

@@ -1,104 +1,136 @@
{ {
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "This software is open source under the MIT license, the author does not have any control over the software, and those who use the software and spread the sounds exported by the software are solely responsible. <br>If you do not agree with this clause, you cannot use or quote any codes and files in the software package . See root directory <b>Agreement-LICENSE.txt</b> for details.", "很遗憾您这没有能用的显卡来支持您训练": "Unfortunately, there is no compatible GPU available to support your training.",
"模型推理": "Model inference", "": "Yes",
"推理音色": "Inferencing timbre", "step1:正在处理数据": "Step 1: Processing data",
"刷新音色列表": "Refresh timbre list", "step2a:无需提取音高": "Step 2a: Skipping pitch extraction",
"卸载音色省显存": "Unload timbre to save GPU memory", "step2b:正在提取特征": "Step 2b: Extracting features",
"请选择说话人id": "Please select a speaker id", "step3a:正在训练模型": "Step 3a: Model training started",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "It is recommended +12key for male to female conversion, and -12key for female to male conversion. If the sound range explodes and the timbre is distorted, you can also adjust it to the appropriate range by yourself. ", "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "Training complete. You can check the training logs in the console or the 'train.log' file under the experiment folder.",
"变调(整数, 半音数量, 升八度12降八度-12)": "transpose(integer, number of semitones, octave sharp 12 octave flat -12)", "全流程结束!": "All processes have been completed!",
"输入待处理音频文件路径(默认是正确格式示例)": "Enter the path of the audio file to be processed (the default is the correct format example)", "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "This software is open source under the MIT license. The author does not have any control over the software. Users who use the software and distribute the sounds exported by the software are solely responsible. <br>If you do not agree with this clause, you cannot use or reference any codes and files within the software package. See the root directory <b>Agreement-LICENSE.txt</b> for details.",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "Select the algorithm for pitch extraction. Use 'pm' to speed up for singing voices, or use 'harvest' for better low-pitched voices, but it is extremely slow.", "模型推理": "Model Inference",
"特征检索库文件路径": "Feature search database file path", "推理音色": "Inferencing voice:",
"特征文件路径": "Feature file path", "刷新音色列表和索引路径": "Refresh voice list and index path",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0 curve file, optional, one pitch per line, instead of the default F0 and ups and downs", "卸载音色省显存": "Unload voice to save GPU memory:",
"转换": "Conversion", "请选择说话人id": "Select Speaker/Singer ID:",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "Recommended +12 key for male to female conversion, and -12 key for female to male conversion. If the sound range goes too far and the voice is distorted, you can also adjust it to the appropriate range by yourself.",
"变调(整数, 半音数量, 升八度12降八度-12)": "Transpose (integer, number of semitones, raise by an octave: 12, lower by an octave: -12):",
"输入待处理音频文件路径(默认是正确格式示例)": "Enter the path of the audio file to be processed (default is the correct format example):",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "Select the pitch extraction algorithm ('pm': faster extraction but lower-quality speech; 'harvest': better bass but extremely slow; 'crepe': better quality but GPU intensive):",
">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": "If >=3: apply median filtering to the harvested pitch results. The value represents the filter radius and can reduce breathiness.",
"特征检索库文件路径,为空则使用下拉的选择结果": "Path to the feature index file. Leave blank to use the selected result from the dropdown:",
"自动检测index路径,下拉式选择(dropdown)": "Auto-detect index path and select from the dropdown:",
"特征文件路径": "Path to feature file:",
"检索特征占比": "Search feature ratio:",
"后处理重采样至最终采样率0为不进行重采样": "Resample the output audio in post-processing to the final sample rate. Set to 0 for no resampling:",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "Use the volume envelope of the input to replace or mix with the volume envelope of the output. The closer the ratio is to 1, the more the output envelope is used:",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "Protect voiceless consonants and breath sounds to prevent artifacts such as tearing in electronic music. Set to 0.5 to disable. Decrease the value to increase protection, but it may reduce indexing accuracy:",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0 curve file (optional). One pitch per line. Replaces the default F0 and pitch modulation:",
"转换": "Convert",
"输出信息": "Output information", "输出信息": "Output information",
"输出音频(右下角三个点,点了可以下载)": "Output audio (three dots in the lower right corner, click to download)", "输出音频(右下角三个点,点了可以下载)": "Export audio (click on the three dots in the lower right corner to download)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "For batch conversion, input the audio folder to be converted, or upload multiple audio files, and output the converted audio in the specified folder (opt by default). ", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "Batch conversion. Enter the folder containing the audio files to be converted or upload multiple audio files. The converted audio will be output in the specified folder (default: 'opt').",
"指定输出文件夹": "Specify output folder", "指定输出文件夹": "Specify output folder:",
"检索特征占比": "Search feature ratio", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Enter the path of the audio folder to be processed (copy it from the address bar of the file manager):",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Enter the path of the audio folder to be processed (just go to the address bar of the file manager and copy it)", "也可批量输入音频文件, 二选一, 优先读文件夹": "You can also input audio files in batches. Choose one of the two options. Priority is given to reading from the folder.",
"也可批量输入音频文件, 二选一, 优先读文件夹": "You can also input audio files in batches, choose one of the two, and read the folder first", "导出文件格式": "Export file format",
"伴奏人声分离": "Accompaniment and vocal separation", "伴奏人声分离&去混响&去回声": "Vocals/Accompaniment Separation & Reverberation Removal",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "Batch processing of vocal accompaniment separation, using UVR5 model. <br>Without harmony, use HP2, with harmony and extracted vocals do not need harmony, use HP5<br>Example of qualified folder path format: E:\\ codes\\py39\\vits_vc_gpu\\Egret Shuanghua test sample (just go to the address bar of the file manager and copy it)", "输入待处理音频文件夹路径": "Enter the path of the audio folder to be processed:",
"输入待处理音频文件夹路径": "Input audio folder path",
"模型": "Model", "模型": "Model",
"指定输出人声文件夹": "Specify vocals output folder", "指定输出人声文件夹": "Specify the output folder for vocals:",
"指定输出乐器文件夹": "Specify instrumentals output folder", "指定输出非主人声文件夹": "Specify the output folder for accompaniment:",
"训练": "Train", "训练": "Train",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: Fill in the experimental configuration. The experimental data is placed under logs, and each experiment has a folder. You need to manually enter the experimental name path, which contains the experimental configuration, logs, and model files obtained from training. ", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "Step 1: Fill in the experimental configuration. Experimental data is stored in the 'logs' folder, with each experiment having a separate folder. Manually enter the experiment name path, which contains the experimental configuration, logs, and trained model files.",
"输入实验名": "Input experiment name", "输入实验名": "Enter the experiment name:",
"目标采样率": "Target sample rate", "目标采样率": "Target sample rate:",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Does the model have pitch guidance (singing must, voice can not.)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "Whether the model has pitch guidance (required for singing, optional for speech):",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: Automatically traverse all files that can be decoded into audio in the training folder and perform slice normalization, and generate 2 wav folders in the experiment directory; only single-person training is supported for the time being. ", "版本": "Version",
"输入训练文件夹路径": "Input training folder path", "提取音高和处理数据使用的CPU进程数": "Number of CPU processes used for pitch extraction and data processing:",
"请指定说话人id": "Please specify speaker ID", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "Step 2a: Automatically traverse all files in the training folder that can be decoded into audio and perform slice normalization. Generates 2 wav folders in the experiment directory. Currently, only single-singer/speaker training is supported.",
"输入训练文件夹路径": "Enter the path of the training folder:",
"请指定说话人id": "Please specify the speaker/singer ID:",
"处理数据": "Process data", "处理数据": "Process data",
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "step2b: Use CPU to extract pitch (if the model has pitch), use GPU to extract features (select card number)", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "Step 2b: Use CPU to extract pitch (if the model has pitch), use GPU to extract features (select GPU index):",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Enter the card numbers used separated by -, for example 0-1-2 use card 0 and card 1 and card 2", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Enter the GPU index(es) separated by '-', e.g., 0-1-2 to use GPU 0, 1, and 2:",
"显卡信息": "GPU information", "显卡信息": "GPU Information",
"提取音高使用的CPU进程数": "Number of CPU threads to use for pitch extraction", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Select the pitch extraction algorithm ('pm': faster extraction but lower-quality speech; 'dio': improved speech but slower extraction; 'harvest': better quality but slower extraction):",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Select pitch extraction algorithm: Use 'pm' for faster processing of singing voice, 'dio' for high-quality speech but slower processing, and 'harvest' for the best quality but slowest processing.",
"特征提取": "Feature extraction", "特征提取": "Feature extraction",
"step3: 填写训练设置, 开始训练模型和索引": "step3: Fill in the training settings, start training the model and index", "step3: 填写训练设置, 开始训练模型和索引": "Step 3: Fill in the training settings and start training the model and index",
"保存频率save_every_epoch": "Save frequency (save_every_epoch)", "保存频率save_every_epoch": "Save frequency (save_every_epoch):",
"总训练轮数total_epoch": "Total training epochs (total_epoch)", "总训练轮数total_epoch": "Total training epochs (total_epoch):",
"是否仅保存最新的ckpt文件以节省硬盘空间": "Whether to save only the latest ckpt file to save disk space", "每张显卡的batch_size": "Batch size per GPU:",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Whether to cache all training sets to video memory. Small data under 10 minutes can be cached to speed up training, and large data cache will blow up video memory and not increase the speed much", "是否仅保存最新的ckpt文件以节省硬盘空间": "Save only the latest '.ckpt' file to save disk space:",
"加载预训练底模G路径": "Load pre-trained base model G path.", "否": "No",
"加载预训练底模D路径": "Load pre-trained base model D path.", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Cache all training sets to GPU memory. Caching small datasets (less than 10 minutes) can speed up training, but caching large datasets will consume a lot of GPU memory and may not provide much speed improvement:",
"训练模型": "Train model.", "是否在每次保存时间点将最终小模型保存至weights文件夹": "Save a small final model to the 'weights' folder at each save point:",
"训练特征索引": "Train feature index.", "加载预训练底模G路径": "Load pre-trained base model G path:",
"一键训练": "One-click training.", "加载预训练底模D路径": "Load pre-trained base model D path:",
"ckpt处理": "ckpt processing.", "训练模型": "Train model",
"模型融合, 可用于测试音色融合": "Model Fusion, which can be used to test sound fusion", "训练特征索引": "Train feature index",
"A模型路径": "A model path.", "一键训练": "One-click training",
"B模型路径": "B model path.", "ckpt处理": "ckpt Processing",
"A模型权重": "A model weight for model A.", "模型融合, 可用于测试音色融合": "Model fusion, can be used to test timbre fusion",
"模型是否带音高指导": "Whether the model has pitch guidance.", "A模型路径": "Path to Model A:",
"要置入的模型信息": "Model information to be placed.", "B模型路径": "Path to Model B:",
"保存的模型名不带后缀": "Saved model name without extension.", "A模型权重": "Weight (w) for Model A:",
"融合": "Fusion.", "模型是否带音高指导": "Whether the model has pitch guidance:",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modify model information (only small model files extracted from the weights folder are supported)", "要置入的模型信息": "Model information to be placed:",
"模型路径": "Model path", "保存的模型名不带后缀": "Saved model name (without extension):",
"要改的模型信息": "Model information to be modified", "模型版本型号": "Model architecture version:",
"保存的文件名, 默认空为和源文件同名": "The saved file name, the default is empty and the same name as the source file", "融合": "Fusion",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modify model information (only supported for small model files extracted from the 'weights' folder)",
"模型路径": "Path to Model:",
"要改的模型信息": "Model information to be modified:",
"保存的文件名, 默认空为和源文件同名": "Save file name (default: same as the source file):",
"修改": "Modify", "修改": "Modify",
"查看模型信息(仅支持weights文件夹下提取的小模型文件)": "View model information (only small model files extracted from the weights folder are supported)", "查看模型信息(仅支持weights文件夹下提取的小模型文件)": "View model information (only supported for small model files extracted from the 'weights' folder)",
"查看": "View", "查看": "View",
"模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "Model extraction (enter the path of the large file model under the logs folder), which is suitable for half of the training and does not want to train the model without automatically extracting and saving the small file model, or if you want to test the intermediate model", "模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "Model extraction (enter the path of the large file model under the 'logs' folder). This is useful if you want to stop training halfway and manually extract and save a small model file, or if you want to test an intermediate model:",
"保存名": "Save Name", "保存名": "Save name:",
"模型是否带音高指导,1是0否": "Whether the model has pitch guidance, 1 for yes, 0 for no", "模型是否带音高指导,1是0否": "Whether the model has pitch guidance (1: yes, 0: no):",
"提取": "Extract", "提取": "Extract",
"Onnx导出": "Onnx", "Onnx导出": "Export Onnx",
"RVC模型路径": "RVC Path", "RVC模型路径": "RVC Model Path:",
"Onnx输出路径": "Onnx Export Path", "Onnx输出路径": "Onnx Export Path:",
"MoeVS模型": "MoeSS?", "MoeVS模型": "MoeVS Model",
"导出Onnx模型": "Export Onnx Model", "导出Onnx模型": "Export Onnx Model",
"招募音高曲线前端编辑器": "Recruit front-end editors for pitch curves", "常见问题解答": "FAQ (Frequently Asked Questions)",
"加开发群联系我xxxxx": "Add development group to contact me xxxxx", "招募音高曲线前端编辑器": "Recruiting front-end editors for pitch curves",
"加开发群联系我xxxxx": "Join the development group and contact me at xxxxx",
"点击查看交流、问题反馈群号": "Click to view the communication and problem feedback group number", "点击查看交流、问题反馈群号": "Click to view the communication and problem feedback group number",
"xxxxx": "xxxxx", "xxxxx": "xxxxx",
"加载模型": "load model", "加载模型": "Load model",
"Hubert模型": "Hubert File", "Hubert模型": "Hubert Model",
"选择.pth文件": "Select the .pth file", "选择.pth文件": "Select the .pth file",
"选择.index文件": "Select the .index file", "选择.index文件": "Select the .index file",
"选择.npy文件": "Select the .npy file", "选择.npy文件": "Select the .npy file",
"输入设备": "input device", "输入设备": "Input device",
"输出设备": "output device", "输出设备": "Output device",
"音频设备(请使用同种类驱动)": "Audio device (please use the same type of driver)", "音频设备(请使用同种类驱动)": "Audio device (please use the same type of driver)",
"响应阈值": "response threshold", "响应阈值": "Response threshold",
"音调设置": "tone setting", "音调设置": "Pitch settings",
"Index Rate": "Index Rate", "Index Rate": "Index Rate",
"常规设置": "general settings", "常规设置": "General settings",
"采样长度": "Sample length", "采样长度": "Sample length",
"淡入淡出长度": "fade length", "淡入淡出长度": "Fade length",
"额外推理时长": "extra inference time", "额外推理时长": "Extra inference time",
"输入降噪": "Input Noisereduce", "输入降噪": "Input noise reduction",
"输出降噪": "Output Noisereduce", "输出降噪": "Output noise reduction",
"性能设置": "performance settings", "性能设置": "Performance settings",
"开始音频转换": "start audio conversion", "开始音频转换": "Start audio conversion",
"停止音频转换": "stop audio conversion", "停止音频转换": "Stop audio conversion",
"推理时间(ms):": "Infer Time(ms):" "推理时间(ms):": "Inference time (ms):",
} "人声伴奏分离批量处理, 使用UVR5模型。 <br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。 <br>模型分为三类: <br>1、保留人声不带和声的音频选这个对主人声保留比HP5更好。内置HP2和HP3两个模型HP3可能轻微漏伴奏但对主人声保留比HP2稍微好一丁点 <br>2、仅保留主人声带和声的音频选这个对主人声可能有削弱。内置HP5一个模型 <br> 3、去混响、去延迟模型by FoxJoy<br>(1)MDX-Net(onnx_dereverb):对于双通道混响是最好的选择,不能去除单通道混响;<br>&emsp;(234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底DeReverb额外去除混响可去除单声道混响但是对高频重的板式混响去不干净。<br>去混响/去延迟,附:<br>1、DeEcho-DeReverb模型的耗时是另外2个DeEcho模型的接近2倍<br>2、MDX-Net-Dereverb模型挺慢的<br>3、个人推荐的最干净的配置是先MDX-Net再DeEcho-Aggressive。":"Batch processing for vocal accompaniment separation using the UVR5 model.<br>Example of a valid folder path format: D:\\path\\to\\input\\folder (copy it from the file manager address bar).<br>The model is divided into three categories:<br>1. Preserve vocals: Choose this option for audio without harmonies. It preserves vocals better than HP5. It includes two built-in models: HP2 and HP3. HP3 may slightly leak accompaniment but preserves vocals slightly better than HP2.<br>2. Preserve main vocals only: Choose this option for audio with harmonies. It may weaken the main vocals. It includes one built-in model: HP5.<br>3. De-reverb and de-delay models (by FoxJoy):<br>(1) MDX-Net: The best choice for stereo reverb removal but cannot remove mono reverb;<br>&emsp;(234) DeEcho: Removes delay effects. Aggressive mode removes more thoroughly than Normal mode. DeReverb additionally removes reverb and can remove mono reverb, but not very effectively for heavily reverberated high-frequency content.<br>De-reverb/de-delay notes:<br>1. The processing time for the DeEcho-DeReverb model is approximately twice as long as the other two DeEcho models.<br>2. The MDX-Net-Dereverb model is quite slow.<br>3. The recommended cleanest configuration is to apply MDX-Net first and then DeEcho-Aggressive.",
"人声伴奏分离批量处理, 使用UVR5模型。": "Batch processing for vocal accompaniment separation using the UVR5 model.",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Example of a valid folder path format: D:\\path\\to\\input\\folder (copy it from the file manager address bar).",
"模型分为三类:": "The model is divided into three categories:",
"1、保留人声不带和声的音频选这个对主人声保留比HP5更好。内置HP2和HP3两个模型HP3可能轻微漏伴奏但对主人声保留比HP2稍微好一丁点": "1. Preserve vocals: Choose this option for audio without harmonies. It preserves vocals better than HP5. It includes two built-in models: HP2 and HP3. HP3 may slightly leak accompaniment but preserves vocals slightly better than HP2.",
"2、仅保留主人声带和声的音频选这个对主人声可能有削弱。内置HP5一个模型": "2. Preserve main vocals only: Choose this option for audio with harmonies. It may weaken the main vocals. It includes one built-in model: HP5.",
"3、去混响、去延迟模型by FoxJoy": "3. De-reverb and de-delay models (by FoxJoy):",
"(1)MDX-Net:对于双通道混响是最好的选择,不能去除单通道混响;": "(1) MDX-Net: The best choice for stereo reverb removal but cannot remove mono reverb;",
"(234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底DeReverb额外去除混响可去除单声道混响但是对高频重的板式混响去不干净。": "(234) DeEcho: Removes delay effects. Aggressive mode removes more thoroughly than Normal mode. DeReverb additionally removes reverb and can remove mono reverb, but not very effectively for heavily reverberated high-frequency content.",
"去混响/去延迟,附:": "De-reverb/de-delay notes:",
"1、DeEcho-DeReverb模型的耗时是另外2个DeEcho模型的接近2倍": "1. The processing time for the DeEcho-DeReverb model is approximately twice as long as the other two DeEcho models.",
"2、MDX-Net-Dereverb模型挺慢的": "2. The MDX-Net-Dereverb model is quite slow.",
"3、个人推荐的最干净的配置是先MDX-Net再DeEcho-Aggressive。": "3. The recommended cleanest configuration is to apply MDX-Net first and then DeEcho-Aggressive."
}

View File

@@ -1,36 +1,51 @@
{ {
"很遗憾您这没有能用的显卡来支持您训练": "很遗憾您这没有能用的显卡来支持您训练",
"是": "是",
"step1:正在处理数据": "step1:正在处理数据",
"step2a:无需提取音高": "step2a:无需提取音高",
"step2b:正在提取特征": "step2b:正在提取特征",
"step3a:正在训练模型": "step3a:正在训练模型",
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log",
"全流程结束!": "全流程结束!",
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "Este software es de código abierto bajo la licencia MIT, el autor no tiene ningún control sobre el software, y aquellos que usan el software y difunden los sonidos exportados por el software son los únicos responsables.<br>Si no está de acuerdo con esta cláusula , no puede utilizar ni citar ningún código ni archivo del paquete de software Consulte el directorio raíz <b>Agreement-LICENSE.txt</b> para obtener más información.", "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "Este software es de código abierto bajo la licencia MIT, el autor no tiene ningún control sobre el software, y aquellos que usan el software y difunden los sonidos exportados por el software son los únicos responsables.<br>Si no está de acuerdo con esta cláusula , no puede utilizar ni citar ningún código ni archivo del paquete de software Consulte el directorio raíz <b>Agreement-LICENSE.txt</b> para obtener más información.",
"模型推理": "inferencia del modelo", "模型推理": "inferencia del modelo",
"推理音色": "inferencia de voz", "推理音色": "inferencia de voz",
"刷新音色列表": "Actualizar lista de voces", "刷新音色列表和索引路径": "刷新音色列表和索引路径",
"卸载音色省显存": "Descargue la voz para ahorrar memoria GPU", "卸载音色省显存": "Descargue la voz para ahorrar memoria GPU",
"请选择说话人id": "seleccione una identificación de altavoz", "请选择说话人id": "seleccione una identificación de altavoz",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "Tecla +12 recomendada para conversión de voz de hombre a mujer, tecla -12 para conversión de voz de mujer a hombre. Si el rango de tono es demasiado amplio y causa distorsión, ajústelo usted mismo a un rango adecuado.", "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "Tecla +12 recomendada para conversión de voz de hombre a mujer, tecla -12 para conversión de voz de mujer a hombre. Si el rango de tono es demasiado amplio y causa distorsión, ajústelo usted mismo a un rango adecuado.",
"变调(整数, 半音数量, 升八度12降八度-12)": "Cambio de tono (entero, número de semitonos, subir una octava +12 o bajar una octava -12)", "变调(整数, 半音数量, 升八度12降八度-12)": "Cambio de tono (entero, número de semitonos, subir una octava +12 o bajar una octava -12)",
"输入待处理音频文件路径(默认是正确格式示例)": "Ingrese la ruta del archivo del audio que se procesará (el formato predeterminado es el ejemplo correcto)", "输入待处理音频文件路径(默认是正确格式示例)": "Ingrese la ruta del archivo del audio que se procesará (el formato predeterminado es el ejemplo correcto)",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "Seleccione el algoritmo para la extracción de tono. Use 'pm' para acelerar las voces cantadas, o use 'harvest' para mejorar las voces bajas, pero es extremadamente lento.", "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
"特征检索库文件路径": "Ruta del archivo de la base de datos de búsqueda de características", ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音",
"特征检索库文件路径,为空则使用下拉的选择结果": "特征检索库文件路径,为空则使用下拉的选择结果",
"自动检测index路径,下拉式选择(dropdown)": "自动检测index路径,下拉式选择(dropdown)",
"特征文件路径": "Ruta del archivo de características", "特征文件路径": "Ruta del archivo de características",
"检索特征占比": "Proporción de función de búsqueda",
"后处理重采样至最终采样率0为不进行重采样": "后处理重采样至最终采样率0为不进行重采样",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "Archivo de curva F0, opcional, un tono por línea, en lugar de F0 predeterminado y cambio de tono", "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "Archivo de curva F0, opcional, un tono por línea, en lugar de F0 predeterminado y cambio de tono",
"转换": "Conversión", "转换": "Conversión",
"输出信息": "Información de salida", "输出信息": "Información de salida",
"输出音频(右下角三个点,点了可以下载)": "Salida de audio (haga clic en los tres puntos en la esquina inferior derecha para descargar)", "输出音频(右下角三个点,点了可以下载)": "Salida de audio (haga clic en los tres puntos en la esquina inferior derecha para descargar)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "Conversión por lotes, ingrese la carpeta que contiene los archivos de audio para convertir o cargue varios archivos de audio. El audio convertido se emitirá en la carpeta especificada (opción predeterminada).", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "Conversión por lotes, ingrese la carpeta que contiene los archivos de audio para convertir o cargue varios archivos de audio. El audio convertido se emitirá en la carpeta especificada (opción predeterminada).",
"指定输出文件夹": "Especificar carpeta de salida", "指定输出文件夹": "Especificar carpeta de salida",
"检索特征占比": "Proporción de función de búsqueda",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Ingrese la ruta a la carpeta de audio que se procesará (simplemente cópiela desde la barra de direcciones del administrador de archivos)", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Ingrese la ruta a la carpeta de audio que se procesará (simplemente cópiela desde la barra de direcciones del administrador de archivos)",
"也可批量输入音频文件, 二选一, 优先读文件夹": "También se pueden ingresar múltiples archivos de audio, cualquiera de las dos opciones, con prioridad dada a la carpeta", "也可批量输入音频文件, 二选一, 优先读文件夹": "También se pueden ingresar múltiples archivos de audio, cualquiera de las dos opciones, con prioridad dada a la carpeta",
"伴奏人声分离": "Instrumental and vocal separation", "导出文件格式": "导出文件格式",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "Procesamiento por lotes de separación instrumental y vocal utilizando el modelo UVR5. <br>Utilice HP2 para la separación vocal sin armónicos, y utilice HP5 para la separación vocal con armónicos y las voces extraídas no necesitan tener armónicos. <br>Ejemplo de una ruta de carpeta calificada: E:\\codes\\py39\\vits_vc_gpu\\test_sample (simplemente cópielo desde la barra de direcciones del administrador de archivos)", "伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
"输入待处理音频文件夹路径": "Ingrese la ruta a la carpeta de audio que se procesará", "输入待处理音频文件夹路径": "Ingrese la ruta a la carpeta de audio que se procesará",
"模型": "Modelo", "模型": "Modelo",
"指定输出人声文件夹": "Especificar la carpeta de salida de voces", "指定输出人声文件夹": "指定输出主人声文件夹",
"指定输出乐器文件夹": "Especificar la carpeta de salida de instrumentales", "指定输出非主人声文件夹": "指定输出非主人声文件夹",
"训练": "Entrenamiento", "训练": "Entrenamiento",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "paso 1: Complete la configuración del experimento. Los datos del experimento se almacenan en el directorio 'logs', con cada experimento en una carpeta separada. La ruta del nombre del experimento debe ingresarse manualmente y debe contener la configuración del experimento, los registros y los archivos del modelo entrenado.", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "paso 1: Complete la configuración del experimento. Los datos del experimento se almacenan en el directorio 'logs', con cada experimento en una carpeta separada. La ruta del nombre del experimento debe ingresarse manualmente y debe contener la configuración del experimento, los registros y los archivos del modelo entrenado.",
"输入实验名": "Ingrese el nombre del modelo", "输入实验名": "Ingrese el nombre del modelo",
"目标采样率": "Tasa de muestreo objetivo", "目标采样率": "Tasa de muestreo objetivo",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Si el modelo tiene guía de tono (necesaria para cantar, pero no para hablar)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "Si el modelo tiene guía de tono (necesaria para cantar, pero no para hablar)",
"版本": "版本",
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "paso 2a: recorra automáticamente la carpeta de capacitación y corte y normalice todos los archivos de audio que se pueden decodificar en audio. Se generarán dos carpetas 'wav' en el directorio del experimento. Actualmente, solo se admite la capacitación de una sola persona.", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "paso 2a: recorra automáticamente la carpeta de capacitación y corte y normalice todos los archivos de audio que se pueden decodificar en audio. Se generarán dos carpetas 'wav' en el directorio del experimento. Actualmente, solo se admite la capacitación de una sola persona.",
"输入训练文件夹路径": "Introduzca la ruta de la carpeta de entrenamiento", "输入训练文件夹路径": "Introduzca la ruta de la carpeta de entrenamiento",
"请指定说话人id": "Especifique el ID del hablante", "请指定说话人id": "Especifique el ID del hablante",
@@ -38,14 +53,16 @@
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "paso 2b: use la CPU para extraer el tono (si el modelo tiene guía de tono) y la GPU para extraer características (seleccione el número de tarjeta).", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "paso 2b: use la CPU para extraer el tono (si el modelo tiene guía de tono) y la GPU para extraer características (seleccione el número de tarjeta).",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Separe los números de identificación de la GPU con '-' al ingresarlos. Por ejemplo, '0-1-2' significa usar GPU 0, GPU 1 y GPU 2.", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Separe los números de identificación de la GPU con '-' al ingresarlos. Por ejemplo, '0-1-2' significa usar GPU 0, GPU 1 y GPU 2.",
"显卡信息": "información de la GPU", "显卡信息": "información de la GPU",
"提取音高使用的CPU进程数": "Número de subprocesos de CPU que se utilizarán para la extracción de tono",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Seleccione el algoritmo de extracción de tono: utilice 'pm' para un procesamiento más rápido de la voz cantada, 'dio' para un discurso de alta calidad pero un procesamiento más lento y 'cosecha' para obtener la mejor calidad pero un procesamiento más lento.", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Seleccione el algoritmo de extracción de tono: utilice 'pm' para un procesamiento más rápido de la voz cantada, 'dio' para un discurso de alta calidad pero un procesamiento más lento y 'cosecha' para obtener la mejor calidad pero un procesamiento más lento.",
"特征提取": "Extracción de características", "特征提取": "Extracción de características",
"step3: 填写训练设置, 开始训练模型和索引": "Paso 3: complete la configuración de entrenamiento y comience a entrenar el modelo y el índice.", "step3: 填写训练设置, 开始训练模型和索引": "Paso 3: complete la configuración de entrenamiento y comience a entrenar el modelo y el índice.",
"保存频率save_every_epoch": "Frecuencia de guardado (save_every_epoch)", "保存频率save_every_epoch": "Frecuencia de guardado (save_every_epoch)",
"总训练轮数total_epoch": "Total de épocas de entrenamiento (total_epoch)", "总训练轮数total_epoch": "Total de épocas de entrenamiento (total_epoch)",
"每张显卡的batch_size": "每张显卡的batch_size",
"是否仅保存最新的ckpt文件以节省硬盘空间": "Si guardar solo el archivo ckpt más reciente para ahorrar espacio en disco", "是否仅保存最新的ckpt文件以节省硬盘空间": "Si guardar solo el archivo ckpt más reciente para ahorrar espacio en disco",
"否": "否",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Si almacenar en caché todos los conjuntos de entrenamiento en la memoria de la GPU. Los conjuntos de datos pequeños (menos de 10 minutos) se pueden almacenar en caché para acelerar el entrenamiento, pero el almacenamiento en caché de conjuntos de datos grandes puede causar errores de memoria en la GPU y no aumenta la velocidad de manera significativa.", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Si almacenar en caché todos los conjuntos de entrenamiento en la memoria de la GPU. Los conjuntos de datos pequeños (menos de 10 minutos) se pueden almacenar en caché para acelerar el entrenamiento, pero el almacenamiento en caché de conjuntos de datos grandes puede causar errores de memoria en la GPU y no aumenta la velocidad de manera significativa.",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存时间点将最终小模型保存至weights文件夹",
"加载预训练底模G路径": "Cargue la ruta G del modelo base preentrenada.", "加载预训练底模G路径": "Cargue la ruta G del modelo base preentrenada.",
"加载预训练底模D路径": "Cargue la ruta del modelo D base preentrenada.", "加载预训练底模D路径": "Cargue la ruta del modelo D base preentrenada.",
"训练模型": "Entrenar Modelo", "训练模型": "Entrenar Modelo",
@@ -59,6 +76,7 @@
"模型是否带音高指导": "Si el modelo tiene guía de tono.", "模型是否带音高指导": "Si el modelo tiene guía de tono.",
"要置入的模型信息": "Información del modelo a colocar.", "要置入的模型信息": "Información del modelo a colocar.",
"保存的模型名不带后缀": "Nombre del modelo guardado sin extensión.", "保存的模型名不带后缀": "Nombre del modelo guardado sin extensión.",
"模型版本型号": "模型版本型号",
"融合": "Fusión.", "融合": "Fusión.",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modificar la información del modelo (solo admite archivos de modelos pequeños extraídos en la carpeta de pesos).", "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modificar la información del modelo (solo admite archivos de modelos pequeños extraídos en la carpeta de pesos).",
"模型路径": "Ruta del modelo", "模型路径": "Ruta del modelo",
@@ -76,6 +94,7 @@
"Onnx输出路径": "Onnx输出路径", "Onnx输出路径": "Onnx输出路径",
"MoeVS模型": "MoeVS模型", "MoeVS模型": "MoeVS模型",
"导出Onnx模型": "导出Onnx模型", "导出Onnx模型": "导出Onnx模型",
"常见问题解答": "常见问题解答",
"招募音高曲线前端编辑器": "Reclutar editores front-end para curvas de tono", "招募音高曲线前端编辑器": "Reclutar editores front-end para curvas de tono",
"加开发群联系我xxxxx": "Únase al grupo de desarrollo para contactarme en xxxxx", "加开发群联系我xxxxx": "Únase al grupo de desarrollo para contactarme en xxxxx",
"点击查看交流、问题反馈群号": "Haga clic para ver el número de grupo de comunicación y comentarios sobre problemas", "点击查看交流、问题反馈群号": "Haga clic para ver el número de grupo de comunicación y comentarios sobre problemas",

View File

@@ -1,53 +1,70 @@
{ {
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.", "很遗憾您这没有能用的显卡来支持您训练": "トレーニングに対応したGPUが動作しないのは残念です。",
"是": "はい",
"step1:正在处理数据": "step1:処理中のデータ",
"step2a:无需提取音高": "step2a:ピッチの抽出は不要",
"step2b:正在提取特征": "step2b:抽出される特徴量",
"step3a:正在训练模型": "step3a:トレーニング中のモデル",
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "トレーニング終了時に、トレーニングログやフォルダ内のtrain.logを確認することができます",
"全流程结束!": "全工程が完了!",
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本ソフトウェアはMITライセンスに基づくオープンソースであり、作者は本ソフトウェアに対していかなる強制力も持ちません。本ソフトウェアの利用者および本ソフトウェアから派生した音源(成果物)を配布する者は、本ソフトウェアに対して自身で責任を負うものとします。 <br>この条項に同意しない場合、パッケージ内のコードやファイルを使用や参照を禁じます。詳しくは<b>使用需遵守的协议-LICENSE.txt</b>をご覧ください.",
"模型推理": "モデル推論", "模型推理": "モデル推論",
"推理音色": "音源推論", "推理音色": "音源推論",
"刷新音色列表": "音源リスト更新", "刷新音色列表和索引路径": "音源リストとインデックスパスの更新",
"卸载音色省显存": "音源を削除してメモリを節約", "卸载音色省显存": "音源を削除してメモリを節約",
"请选择说话人id": "話者IDを選択してください", "请选择说话人id": "話者IDを選択してください",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性から女性へは+12キーをお勧めします。女性から男性へは-12キーをお勧めします。音域が広すぎて音質が劣化した場合は、適切な音域に自分で調整することもできます。", "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性から女性へは+12キーをお勧めします。女性から男性へは-12キーをお勧めします。音域が広すぎて音質が劣化した場合は、適切な音域に自分で調整することもできます。",
"变调(整数, 半音数量, 升八度12降八度-12)": "ピッチ変更(整数、半音数、上下オクターブ12-12)", "变调(整数, 半音数量, 升八度12降八度-12)": "ピッチ変更(整数、半音数、上下オクターブ12-12)",
"输入待处理音频文件路径(默认是正确格式示例)": "処理対象音声ファイルのパスを入力してください(デフォルトは正しいフォーマットの例です)", "输入待处理音频文件路径(默认是正确格式示例)": "処理対象音声ファイルのパスを入力してください(デフォルトは正しいフォーマットの例です)",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "ピッチ抽出アルゴリズムを選択してください。歌声の場合は、pmを使用して速度を上げることができます。低音が重要な場合は、harvestを使用できますが、非常に遅くなります。", "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
"特征检索库文件路径": "特徴量検索データベースのファイルパス", ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": ">=3 次に、harvestピッチの認識結果に対してメディアンフィルタを使用します。値はフィルター半径で、ミュートを減衰させるために使用します。",
"特征检索库文件路径,为空则使用下拉的选择结果": "特徴検索ライブラリへのパス 空の場合はドロップダウンで選択",
"自动检测index路径,下拉式选择(dropdown)": "インデックスパスの自動検出 ドロップダウンで選択",
"特征文件路径": "特徴量ファイルのパス", "特征文件路径": "特徴量ファイルのパス",
"检索特征占比": "検索特徴率",
"后处理重采样至最终采样率0为不进行重采样": "最終的なサンプリングレートへのポストプロセッシングのリサンプリング リサンプリングしない場合は0",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "入力ソースの音量エンベロープと出力音量エンベロープの融合率 1に近づくほど、出力音量エンベロープの割合が高くなる",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0(最低共振周波数)カーブファイル(オプション、1行に1ピッチ、デフォルトのF0(最低共振周波数)とエレベーションを置き換えます。)", "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0(最低共振周波数)カーブファイル(オプション、1行に1ピッチ、デフォルトのF0(最低共振周波数)とエレベーションを置き換えます。)",
"转换": "変換", "转换": "変換",
"输出信息": "出力情報", "输出信息": "出力情報",
"输出音频(右下角三个点,点了可以下载)": "出力音声(右下の三点をクリックしてダウンロードできます)", "输出音频(右下角三个点,点了可以下载)": "出力音声(右下の三点をクリックしてダウンロードできます)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "一括変換、変換する音声フォルダを入力、または複数の音声ファイルをアップロードし、指定したフォルダ(デフォルトのopt)に変換した音声を出力します。", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "一括変換、変換する音声フォルダを入力、または複数の音声ファイルをアップロードし、指定したフォルダ(デフォルトのopt)に変換した音声を出力します。",
"指定输出文件夹": "出力フォルダを指定してください", "指定输出文件夹": "出力フォルダを指定してください",
"检索特征占比": "検索特徴率",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "処理対象音声フォルダーのパスを入力してください(ファイルマネージャのアドレスバーからコピーしてください)", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "処理対象音声フォルダーのパスを入力してください(ファイルマネージャのアドレスバーからコピーしてください)",
"也可批量输入音频文件, 二选一, 优先读文件夹": "複数の音声ファイルを一括で入力することもできますが、フォルダーを優先して読み込みます", "也可批量输入音频文件, 二选一, 优先读文件夹": "複数の音声ファイルを一括で入力することもできますが、フォルダーを優先して読み込みます",
"伴奏人声分离": "伴奏とボーカルの分離", "导出文件格式": "导出文件格式",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "UVR5モデルを使用した、声帯分離バッチ処理です。<br>HP2はハーモニー、ハーモニーのあるボーカルとハーモニーのないボーカルを抽出したものはHP5を使ってください <br>フォルダーパスの形式例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(エクスプローラーのアドレスバーからコピーするだけです)", "伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
"输入待处理音频文件夹路径": "処理するオーディオファイルのフォルダパスを入力してください", "输入待处理音频文件夹路径": "処理するオーディオファイルのフォルダパスを入力してください",
"模型": "モデル", "模型": "モデル",
"指定输出人声文件夹": "人の声を出力するフォルダを指定してください", "指定输出人声文件夹": "指定输出主人声文件夹",
"指定输出乐器文件夹": "楽器の出力フォルダを指定してください", "指定输出非主人声文件夹": "指定输出非主人声文件夹",
"训练": "トレーニング", "训练": "トレーニング",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "ステップ1:実験設定を入力します。実験データはlogsに保存され、各実験にはフォルダーがあります。実験名のパスを手動で入力する必要があり、実験設定、ログ、トレーニングされたモデルファイルが含まれます。", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "ステップ1:実験設定を入力します。実験データはlogsに保存され、各実験にはフォルダーがあります。実験名のパスを手動で入力する必要があり、実験設定、ログ、トレーニングされたモデルファイルが含まれます。",
"输入实验名": "実験名を入力してください", "输入实验名": "モデル名",
"目标采样率": "目標サンプリングレート", "目标采样率": "目標サンプリングレート",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "モデルに音高ガイドがあるかどうか(歌唱には必要ですが、音声には必要ありません)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "モデルに音高ガイドがあるかどうか(歌唱には必要ですが、音声には必要ありません)",
"版本": "バージョン",
"提取音高和处理数据使用的CPU进程数": "ピッチの抽出やデータ処理に使用するCPUスレッド数",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "ステップ2a: 訓練フォルダー内のすべての音声ファイルを自動的に探索し、スライスと正規化を行い、2つのwavフォルダーを実験ディレクトリに生成します。現在は一人でのトレーニングのみをサポートしています。", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "ステップ2a: 訓練フォルダー内のすべての音声ファイルを自動的に探索し、スライスと正規化を行い、2つのwavフォルダーを実験ディレクトリに生成します。現在は一人でのトレーニングのみをサポートしています。",
"输入训练文件夹路径": "トレーニング用フォルダのパスを入力してください", "输入训练文件夹路径": "トレーニング用フォルダのパスを入力してください",
"请指定说话人id": "話者IDを指定してください", "请指定说话人id": "話者IDを指定してください",
"处理数据": "データ処理", "处理数据": "データ処理",
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "ステップ2b: CPUを使用して音高を抽出する(モデルに音高がある場合)、GPUを使用して特徴を抽出する(カード番号を選択する)", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "ステップ2b: CPUを使用して音高を抽出する(モデルに音高がある場合)、GPUを使用して特徴を抽出する(GPUの番号を選択する)",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "ハイフンで区切って使用するカード番号を入力します。例えば0-1-2はカード0、カード1、カード2を使用します", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "ハイフンで区切って使用するGPUの番号を入力します。例えば0-1-2はGPU0、GPU1、GPU2を使用します",
"显卡信息": "カード情報", "显卡信息": "GPU情報",
"提取音高使用的CPU进程数": "抽出に使用するCPUプロセス数",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "音高抽出アルゴリズムの選択:歌声を入力する場合は、pmを使用して速度を上げることができます。CPUが低い場合はdioを使用して速度を上げることができます。harvestは品質が高く、精度が高いですが、遅いです。", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "音高抽出アルゴリズムの選択:歌声を入力する場合は、pmを使用して速度を上げることができます。CPUが低い場合はdioを使用して速度を上げることができます。harvestは品質が高く、精度が高いですが、遅いです。",
"特征提取": "特徴抽出", "特征提取": "特徴抽出",
"step3: 填写训练设置, 开始训练模型和索引": "ステップ3: トレーニング設定を入力して、モデルとインデックスのトレーニングを開始します", "step3: 填写训练设置, 开始训练模型和索引": "ステップ3: トレーニング設定を入力して、モデルとインデックスのトレーニングを開始します",
"保存频率save_every_epoch": "エポックごとの保存頻度", "保存频率save_every_epoch": "エポックごとの保存頻度",
"总训练轮数total_epoch": "総トレーニング回数", "总训练轮数total_epoch": "総エポック数",
"每张显卡的batch_size": "GPUごとのバッチサイズ",
"是否仅保存最新的ckpt文件以节省硬盘空间": "ハードディスク容量を節約するため、最新のckptファイルのみを保存するかどうか", "是否仅保存最新的ckpt文件以节省硬盘空间": "ハードディスク容量を節約するため、最新のckptファイルのみを保存するかどうか",
"否": "いいえ",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "すべてのトレーニングデータをメモリにキャッシュするかどうか。10分以下の小さなデータはキャッシュしてトレーニングを高速化できますが、大きなデータをキャッシュするとメモリが破裂し、あまり速度が上がりません。", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "すべてのトレーニングデータをメモリにキャッシュするかどうか。10分以下の小さなデータはキャッシュしてトレーニングを高速化できますが、大きなデータをキャッシュするとメモリが破裂し、あまり速度が上がりません。",
"加载预训练底模G路径": "事前学習済みのGモデルのパスをロードしてください", "是否在每次保存时间点将最终小模型保存至weights文件夹": "各保存時点の小モデルを全部weightsフォルダに保存するかどうか",
"加载预训练底模D路径": "事前学習済みのDモデルのパスをロードしてください", "加载预训练底模G路径": "事前学習済みのGモデルのパス",
"加载预训练底模D路径": "事前学習済みのDモデルのパス",
"训练模型": "モデルのトレーニング", "训练模型": "モデルのトレーニング",
"训练特征索引": "特徴インデックスのトレーニング", "训练特征索引": "特徴インデックスのトレーニング",
"一键训练": "ワンクリックトレーニング", "一键训练": "ワンクリックトレーニング",
@@ -59,6 +76,7 @@
"模型是否带音高指导": "モデルに音高ガイドを付けるかどうか", "模型是否带音高指导": "モデルに音高ガイドを付けるかどうか",
"要置入的模型信息": "挿入するモデル情報", "要置入的模型信息": "挿入するモデル情報",
"保存的模型名不带后缀": "拡張子のない保存するモデル名", "保存的模型名不带后缀": "拡張子のない保存するモデル名",
"模型版本型号": "モデルのバージョン",
"融合": "フュージョン", "融合": "フュージョン",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "モデル情報の修正(weightsフォルダから抽出された小さなモデルファイルのみ対応)", "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "モデル情報の修正(weightsフォルダから抽出された小さなモデルファイルのみ対応)",
"模型路径": "モデルパス", "模型路径": "モデルパス",
@@ -72,16 +90,17 @@
"模型是否带音高指导,1是0否": "モデルに音高ガイドを付けるかどうか、1は付ける、0は付けない", "模型是否带音高指导,1是0否": "モデルに音高ガイドを付けるかどうか、1は付ける、0は付けない",
"提取": "抽出", "提取": "抽出",
"Onnx导出": "Onnx", "Onnx导出": "Onnx",
"RVC模型路径": "RVCルパス", "RVC模型路径": "RVCモデルパス",
"Onnx输出路径": "Onnx出力パス", "Onnx输出路径": "Onnx出力パス",
"MoeVS模型": "MoeSS", "MoeVS模型": "MoeSS",
"导出Onnx模型": "Onnxに変換", "导出Onnx模型": "Onnxに変換",
"常见问题解答": "よくある質問",
"招募音高曲线前端编辑器": "音高曲線フロントエンドエディターを募集", "招募音高曲线前端编辑器": "音高曲線フロントエンドエディターを募集",
"加开发群联系我xxxxx": "開発グループに参加して私に連絡してくださいxxxxx", "加开发群联系我xxxxx": "開発グループに参加して私に連絡してくださいxxxxx",
"点击查看交流、问题反馈群号": "クリックして交流、問題フィードバックグループ番号を表示", "点击查看交流、问题反馈群号": "クリックして交流、問題フィードバックグループ番号を表示",
"xxxxx": "xxxxx", "xxxxx": "xxxxx",
"加载模型": "モデルをロード", "加载模型": "モデルをロード",
"Hubert模型": "Hubert模型", "Hubert模型": "Hubertモデル",
"选择.pth文件": ".pthファイルを選択", "选择.pth文件": ".pthファイルを選択",
"选择.index文件": ".indexファイルを選択", "选择.index文件": ".indexファイルを選択",
"选择.npy文件": ".npyファイルを選択", "选择.npy文件": ".npyファイルを選択",

View File

@@ -1,36 +1,51 @@
{ {
"很遗憾您这没有能用的显卡来支持您训练": "很遗憾您这没有能用的显卡来支持您训练",
"是": "是",
"step1:正在处理数据": "step1:正在处理数据",
"step2a:无需提取音高": "step2a:无需提取音高",
"step2b:正在提取特征": "step2b:正在提取特征",
"step3a:正在训练模型": "step3a:正在训练模型",
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log",
"全流程结束!": "全流程结束!",
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.", "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.",
"模型推理": "模型推理", "模型推理": "模型推理",
"推理音色": "推理音色", "推理音色": "推理音色",
"刷新音色列表": "刷新音色列表", "刷新音色列表和索引路径": "刷新音色列表和索引路径",
"卸载音色省显存": "卸载音色省显存", "卸载音色省显存": "卸载音色省显存",
"请选择说话人id": "请选择说话人id", "请选择说话人id": "请选择说话人id",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ", "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ",
"变调(整数, 半音数量, 升八度12降八度-12)": "变调(整数, 半音数量, 升八度12降八度-12)", "变调(整数, 半音数量, 升八度12降八度-12)": "变调(整数, 半音数量, 升八度12降八度-12)",
"输入待处理音频文件路径(默认是正确格式示例)": "输入待处理音频文件路径(默认是正确格式示例)", "输入待处理音频文件路径(默认是正确格式示例)": "输入待处理音频文件路径(默认是正确格式示例)",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比", "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
"特征检索库文件路径": "特征检索库文件路径", ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音",
"特征检索库文件路径,为空则使用下拉的选择结果": "特征检索库文件路径,为空则使用下拉的选择结果",
"自动检测index路径,下拉式选择(dropdown)": "自动检测index路径,下拉式选择(dropdown)",
"特征文件路径": "特征文件路径", "特征文件路径": "特征文件路径",
"检索特征占比": "检索特征占比",
"后处理重采样至最终采样率0为不进行重采样": "后处理重采样至最终采样率0为不进行重采样",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调", "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调",
"转换": "转换", "转换": "转换",
"输出信息": "输出信息", "输出信息": "输出信息",
"输出音频(右下角三个点,点了可以下载)": "输出音频(右下角三个点,点了可以下载)", "输出音频(右下角三个点,点了可以下载)": "输出音频(右下角三个点,点了可以下载)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ",
"指定输出文件夹": "指定输出文件夹", "指定输出文件夹": "指定输出文件夹",
"检索特征占比": "检索特征占比",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)",
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹", "也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹",
"伴奏人声分离": "伴奏人声分离", "导出文件格式": "导出文件格式",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)", "伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
"输入待处理音频文件夹路径": "输入待处理音频文件夹路径", "输入待处理音频文件夹路径": "输入待处理音频文件夹路径",
"模型": "模型", "模型": "模型",
"指定输出人声文件夹": "指定输出人声文件夹", "指定输出人声文件夹": "指定输出人声文件夹",
"指定输出乐器文件夹": "指定输出乐器文件夹", "指定输出非主人声文件夹": "指定输出非主人声文件夹",
"训练": "训练", "训练": "训练",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ",
"输入实验名": "输入实验名", "输入实验名": "输入实验名",
"目标采样率": "目标采样率", "目标采样率": "目标采样率",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否带音高指导(唱歌一定要, 语音可以不要)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否带音高指导(唱歌一定要, 语音可以不要)",
"版本": "版本",
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ",
"输入训练文件夹路径": "输入训练文件夹路径", "输入训练文件夹路径": "输入训练文件夹路径",
"请指定说话人id": "请指定说话人id", "请指定说话人id": "请指定说话人id",
@@ -38,14 +53,16 @@
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2",
"显卡信息": "显卡信息", "显卡信息": "显卡信息",
"提取音高使用的CPU进程数": "提取音高使用的CPU进程数",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢",
"特征提取": "特征提取", "特征提取": "特征提取",
"step3: 填写训练设置, 开始训练模型和索引": "step3: 填写训练设置, 开始训练模型和索引", "step3: 填写训练设置, 开始训练模型和索引": "step3: 填写训练设置, 开始训练模型和索引",
"保存频率save_every_epoch": "保存频率save_every_epoch", "保存频率save_every_epoch": "保存频率save_every_epoch",
"总训练轮数total_epoch": "总训练轮数total_epoch", "总训练轮数total_epoch": "总训练轮数total_epoch",
"每张显卡的batch_size": "每张显卡的batch_size",
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否仅保存最新的ckpt文件以节省硬盘空间", "是否仅保存最新的ckpt文件以节省硬盘空间": "是否仅保存最新的ckpt文件以节省硬盘空间",
"否": "否",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存时间点将最终小模型保存至weights文件夹",
"加载预训练底模G路径": "加载预训练底模G路径", "加载预训练底模G路径": "加载预训练底模G路径",
"加载预训练底模D路径": "加载预训练底模D路径", "加载预训练底模D路径": "加载预训练底模D路径",
"训练模型": "训练模型", "训练模型": "训练模型",
@@ -59,6 +76,7 @@
"模型是否带音高指导": "模型是否带音高指导", "模型是否带音高指导": "模型是否带音高指导",
"要置入的模型信息": "要置入的模型信息", "要置入的模型信息": "要置入的模型信息",
"保存的模型名不带后缀": "保存的模型名不带后缀", "保存的模型名不带后缀": "保存的模型名不带后缀",
"模型版本型号": "模型版本型号",
"融合": "融合", "融合": "融合",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型信息(仅支持weights文件夹下提取的小模型文件)", "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型信息(仅支持weights文件夹下提取的小模型文件)",
"模型路径": "模型路径", "模型路径": "模型路径",
@@ -76,6 +94,7 @@
"Onnx输出路径": "Onnx输出路径", "Onnx输出路径": "Onnx输出路径",
"MoeVS模型": "MoeVS模型", "MoeVS模型": "MoeVS模型",
"导出Onnx模型": "导出Onnx模型", "导出Onnx模型": "导出Onnx模型",
"常见问题解答": "常见问题解答",
"招募音高曲线前端编辑器": "招募音高曲线前端编辑器", "招募音高曲线前端编辑器": "招募音高曲线前端编辑器",
"加开发群联系我xxxxx": "加开发群联系我xxxxx", "加开发群联系我xxxxx": "加开发群联系我xxxxx",
"点击查看交流、问题反馈群号": "点击查看交流、问题反馈群号", "点击查看交流、问题反馈群号": "点击查看交流、问题反馈群号",

View File

@@ -1,36 +1,51 @@
{ {
"很遗憾您这没有能用的显卡来支持您训练": "很遗憾您这没有能用的显卡来支持您训练",
"是": "是",
"step1:正在处理数据": "step1:正在处理数据",
"step2a:无需提取音高": "step2a:无需提取音高",
"step2b:正在提取特征": "step2b:正在提取特征",
"step3a:正在训练模型": "step3a:正在训练模型",
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log",
"全流程结束!": "全流程结束!",
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本軟體以MIT協議開源作者不對軟體具備任何控制力使用軟體者、傳播軟體導出的聲音者自負全責。<br>如不認可該條款,則不能使用或引用軟體包內任何程式碼和檔案。詳見根目錄<b>使用需遵守的協議-LICENSE.txt</b>。", "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本軟體以MIT協議開源作者不對軟體具備任何控制力使用軟體者、傳播軟體導出的聲音者自負全責。<br>如不認可該條款,則不能使用或引用軟體包內任何程式碼和檔案。詳見根目錄<b>使用需遵守的協議-LICENSE.txt</b>。",
"模型推理": "模型推理", "模型推理": "模型推理",
"推理音色": "推理音色", "推理音色": "推理音色",
"刷新音色列表": "重新整理音色列表", "刷新音色列表和索引路径": "刷新音色列表和索引路徑",
"卸载音色省显存": "卸載音色節省 VRAM", "卸载音色省显存": "卸載音色節省 VRAM",
"请选择说话人id": "請選擇說話人ID", "请选择说话人id": "請選擇說話人ID",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key女性轉男性推薦-12key如果音域爆炸導致音色失真也可以自己調整到合適音域。", "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key女性轉男性推薦-12key如果音域爆炸導致音色失真也可以自己調整到合適音域。",
"变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)", "变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)",
"输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)", "输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "選擇音高提取演算法輸入歌聲可用 pm 提速harvest 低音好但巨慢無比", "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
"特征检索库文件路径": "特徵檢索庫檔案路徑", ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": ">=3則使用對harvest音高識別的結果使用中值濾波數值為濾波半徑使用可以削弱啞音",
"特征检索库文件路径,为空则使用下拉的选择结果": "特徵檢索庫檔路徑,為空則使用下拉的選擇結果",
"自动检测index路径,下拉式选择(dropdown)": "自動檢測index路徑,下拉式選擇(dropdown)",
"特征文件路径": "特徵檔案路徑", "特征文件路径": "特徵檔案路徑",
"检索特征占比": "檢索特徵佔比",
"后处理重采样至最终采样率0为不进行重采样": "後處理重採樣至最終採樣率0為不進行重採樣",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例越靠近1越使用輸出包絡",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲防止電音撕裂等artifact拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案可選一行一個音高代替預設的F0及升降調", "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案可選一行一個音高代替預設的F0及升降調",
"转换": "轉換", "转换": "轉換",
"输出信息": "輸出訊息", "输出信息": "輸出訊息",
"输出音频(右下角三个点,点了可以下载)": "輸出音頻(右下角三個點,點了可以下載)", "输出音频(右下角三个点,点了可以下载)": "輸出音頻(右下角三個點,點了可以下載)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量轉換,輸入待轉換音頻資料夾,或上傳多個音頻檔案,在指定資料夾(默認opt)下輸出轉換的音頻。", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量轉換,輸入待轉換音頻資料夾,或上傳多個音頻檔案,在指定資料夾(默認opt)下輸出轉換的音頻。",
"指定输出文件夹": "指定輸出資料夾", "指定输出文件夹": "指定輸出資料夾",
"检索特征占比": "檢索特徵佔比",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)",
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾", "也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾",
"伴奏人声分离": "伴奏人聲分離", "导出文件格式": "導出檔格式",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人聲伴奏分離批量處理使用UVR5模型。<br>不帶和聲用HP2帶和聲且提取的人聲不需要和聲用HP5<br>合格的資料夾路徑格式舉例E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去檔案管理員地址欄複製就行了)", "伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑", "输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
"模型": "模型", "模型": "模型",
"指定输出人声文件夹": "指定輸出人聲資料夾", "指定输出人声文件夹": "指定输出主人声文件夹",
"指定输出乐器文件夹": "指定輸出樂器資料夾", "指定输出非主人声文件夹": "指定输出非主人声文件夹",
"训练": "訓練", "训练": "訓練",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1填寫實驗配置。實驗數據放在logs下每個實驗一個資料夾需手動輸入實驗名路徑內含實驗配置、日誌、訓練得到的模型檔案。", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1填寫實驗配置。實驗數據放在logs下每個實驗一個資料夾需手動輸入實驗名路徑內含實驗配置、日誌、訓練得到的模型檔案。",
"输入实验名": "輸入實驗名稱", "输入实验名": "輸入實驗名稱",
"目标采样率": "目標取樣率", "目标采样率": "目標取樣率",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
"版本": "版本",
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化在實驗目錄下生成2個wav資料夾暫時只支援單人訓練。", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化在實驗目錄下生成2個wav資料夾暫時只支援單人訓練。",
"输入训练文件夹路径": "輸入訓練檔案夾路徑", "输入训练文件夹路径": "輸入訓練檔案夾路徑",
"请指定说话人id": "請指定說話人id", "请指定说话人id": "請指定說話人id",
@@ -38,14 +53,16 @@
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "步驟2b: 使用CPU提取音高(如果模型帶音高), 使用GPU提取特徵(選擇卡號)", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "步驟2b: 使用CPU提取音高(如果模型帶音高), 使用GPU提取特徵(選擇卡號)",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔輸入使用的卡號, 例如 0-1-2 使用卡0和卡1和卡2", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔輸入使用的卡號, 例如 0-1-2 使用卡0和卡1和卡2",
"显卡信息": "顯示卡資訊", "显卡信息": "顯示卡資訊",
"提取音高使用的CPU进程数": "提取音高使用的CPU進程數",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "選擇音高提取算法:輸入歌聲可用pm提速,高品質語音但CPU差可用dio提速,harvest品質更好但較慢", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "選擇音高提取算法:輸入歌聲可用pm提速,高品質語音但CPU差可用dio提速,harvest品質更好但較慢",
"特征提取": "特徵提取", "特征提取": "特徵提取",
"step3: 填写训练设置, 开始训练模型和索引": "步驟3: 填寫訓練設定, 開始訓練模型和索引", "step3: 填写训练设置, 开始训练模型和索引": "步驟3: 填寫訓練設定, 開始訓練模型和索引",
"保存频率save_every_epoch": "保存頻率save_every_epoch", "保存频率save_every_epoch": "保存頻率save_every_epoch",
"总训练轮数total_epoch": "總訓練輪數total_epoch", "总训练轮数total_epoch": "總訓練輪數total_epoch",
"每张显卡的batch_size": "每张显卡的batch_size",
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間", "是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
"否": "否",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練大數據緩存會爆 VRAM 也加不了多少速度", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練大數據緩存會爆 VRAM 也加不了多少速度",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存時間點將最終小模型保存至weights檔夾",
"加载预训练底模G路径": "加載預訓練底模G路徑", "加载预训练底模G路径": "加載預訓練底模G路徑",
"加载预训练底模D路径": "加載預訓練底模D路徑", "加载预训练底模D路径": "加載預訓練底模D路徑",
"训练模型": "訓練模型", "训练模型": "訓練模型",
@@ -59,6 +76,7 @@
"模型是否带音高指导": "模型是否帶音高指導", "模型是否带音高指导": "模型是否帶音高指導",
"要置入的模型信息": "要置入的模型資訊", "要置入的模型信息": "要置入的模型資訊",
"保存的模型名不带后缀": "儲存的模型名不帶副檔名", "保存的模型名不带后缀": "儲存的模型名不帶副檔名",
"模型版本型号": "模型版本型號",
"融合": "融合", "融合": "融合",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)", "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
"模型路径": "模型路徑", "模型路径": "模型路徑",
@@ -76,6 +94,7 @@
"Onnx输出路径": "Onnx输出路径", "Onnx输出路径": "Onnx输出路径",
"MoeVS模型": "MoeSS模型", "MoeVS模型": "MoeSS模型",
"导出Onnx模型": "导出Onnx模型", "导出Onnx模型": "导出Onnx模型",
"常见问题解答": "常見問題解答",
"招募音高曲线前端编辑器": "招募音高曲線前端編輯器", "招募音高曲线前端编辑器": "招募音高曲線前端編輯器",
"加开发群联系我xxxxx": "加開發群聯繫我xxxxx", "加开发群联系我xxxxx": "加開發群聯繫我xxxxx",
"点击查看交流、问题反馈群号": "點擊查看交流、問題反饋群號", "点击查看交流、问题反馈群号": "點擊查看交流、問題反饋群號",

View File

@@ -1,36 +1,51 @@
{ {
"很遗憾您这没有能用的显卡来支持您训练": "很遗憾您这没有能用的显卡来支持您训练",
"是": "是",
"step1:正在处理数据": "step1:正在处理数据",
"step2a:无需提取音高": "step2a:无需提取音高",
"step2b:正在提取特征": "step2b:正在提取特征",
"step3a:正在训练模型": "step3a:正在训练模型",
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log",
"全流程结束!": "全流程结束!",
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本軟體以MIT協議開源作者不對軟體具備任何控制力使用軟體者、傳播軟體導出的聲音者自負全責。<br>如不認可該條款,則不能使用或引用軟體包內任何程式碼和檔案。詳見根目錄<b>使用需遵守的協議-LICENSE.txt</b>。", "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本軟體以MIT協議開源作者不對軟體具備任何控制力使用軟體者、傳播軟體導出的聲音者自負全責。<br>如不認可該條款,則不能使用或引用軟體包內任何程式碼和檔案。詳見根目錄<b>使用需遵守的協議-LICENSE.txt</b>。",
"模型推理": "模型推理", "模型推理": "模型推理",
"推理音色": "推理音色", "推理音色": "推理音色",
"刷新音色列表": "重新整理音色列表", "刷新音色列表和索引路径": "刷新音色列表和索引路徑",
"卸载音色省显存": "卸載音色節省 VRAM", "卸载音色省显存": "卸載音色節省 VRAM",
"请选择说话人id": "請選擇說話人ID", "请选择说话人id": "請選擇說話人ID",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key女性轉男性推薦-12key如果音域爆炸導致音色失真也可以自己調整到合適音域。", "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key女性轉男性推薦-12key如果音域爆炸導致音色失真也可以自己調整到合適音域。",
"变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)", "变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)",
"输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)", "输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "選擇音高提取演算法輸入歌聲可用 pm 提速harvest 低音好但巨慢無比", "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
"特征检索库文件路径": "特徵檢索庫檔案路徑", ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": ">=3則使用對harvest音高識別的結果使用中值濾波數值為濾波半徑使用可以削弱啞音",
"特征检索库文件路径,为空则使用下拉的选择结果": "特徵檢索庫檔路徑,為空則使用下拉的選擇結果",
"自动检测index路径,下拉式选择(dropdown)": "自動檢測index路徑,下拉式選擇(dropdown)",
"特征文件路径": "特徵檔案路徑", "特征文件路径": "特徵檔案路徑",
"检索特征占比": "檢索特徵佔比",
"后处理重采样至最终采样率0为不进行重采样": "後處理重採樣至最終採樣率0為不進行重採樣",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例越靠近1越使用輸出包絡",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲防止電音撕裂等artifact拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案可選一行一個音高代替預設的F0及升降調", "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案可選一行一個音高代替預設的F0及升降調",
"转换": "轉換", "转换": "轉換",
"输出信息": "輸出訊息", "输出信息": "輸出訊息",
"输出音频(右下角三个点,点了可以下载)": "輸出音頻(右下角三個點,點了可以下載)", "输出音频(右下角三个点,点了可以下载)": "輸出音頻(右下角三個點,點了可以下載)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量轉換,輸入待轉換音頻資料夾,或上傳多個音頻檔案,在指定資料夾(默認opt)下輸出轉換的音頻。", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量轉換,輸入待轉換音頻資料夾,或上傳多個音頻檔案,在指定資料夾(默認opt)下輸出轉換的音頻。",
"指定输出文件夹": "指定輸出資料夾", "指定输出文件夹": "指定輸出資料夾",
"检索特征占比": "檢索特徵佔比",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)",
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾", "也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾",
"伴奏人声分离": "伴奏人聲分離", "导出文件格式": "導出檔格式",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人聲伴奏分離批量處理使用UVR5模型。<br>不帶和聲用HP2帶和聲且提取的人聲不需要和聲用HP5<br>合格的資料夾路徑格式舉例E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去檔案管理員地址欄複製就行了)", "伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑", "输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
"模型": "模型", "模型": "模型",
"指定输出人声文件夹": "指定輸出人聲資料夾", "指定输出人声文件夹": "指定输出主人声文件夹",
"指定输出乐器文件夹": "指定輸出樂器資料夾", "指定输出非主人声文件夹": "指定输出非主人声文件夹",
"训练": "訓練", "训练": "訓練",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1填寫實驗配置。實驗數據放在logs下每個實驗一個資料夾需手動輸入實驗名路徑內含實驗配置、日誌、訓練得到的模型檔案。", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1填寫實驗配置。實驗數據放在logs下每個實驗一個資料夾需手動輸入實驗名路徑內含實驗配置、日誌、訓練得到的模型檔案。",
"输入实验名": "輸入實驗名稱", "输入实验名": "輸入實驗名稱",
"目标采样率": "目標取樣率", "目标采样率": "目標取樣率",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
"版本": "版本",
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化在實驗目錄下生成2個wav資料夾暫時只支援單人訓練。", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化在實驗目錄下生成2個wav資料夾暫時只支援單人訓練。",
"输入训练文件夹路径": "輸入訓練檔案夾路徑", "输入训练文件夹路径": "輸入訓練檔案夾路徑",
"请指定说话人id": "請指定說話人id", "请指定说话人id": "請指定說話人id",
@@ -38,14 +53,16 @@
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "步驟2b: 使用CPU提取音高(如果模型帶音高), 使用GPU提取特徵(選擇卡號)", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "步驟2b: 使用CPU提取音高(如果模型帶音高), 使用GPU提取特徵(選擇卡號)",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔輸入使用的卡號, 例如 0-1-2 使用卡0和卡1和卡2", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔輸入使用的卡號, 例如 0-1-2 使用卡0和卡1和卡2",
"显卡信息": "顯示卡資訊", "显卡信息": "顯示卡資訊",
"提取音高使用的CPU进程数": "提取音高使用的CPU進程數",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "選擇音高提取算法:輸入歌聲可用pm提速,高品質語音但CPU差可用dio提速,harvest品質更好但較慢", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "選擇音高提取算法:輸入歌聲可用pm提速,高品質語音但CPU差可用dio提速,harvest品質更好但較慢",
"特征提取": "特徵提取", "特征提取": "特徵提取",
"step3: 填写训练设置, 开始训练模型和索引": "步驟3: 填寫訓練設定, 開始訓練模型和索引", "step3: 填写训练设置, 开始训练模型和索引": "步驟3: 填寫訓練設定, 開始訓練模型和索引",
"保存频率save_every_epoch": "保存頻率save_every_epoch", "保存频率save_every_epoch": "保存頻率save_every_epoch",
"总训练轮数total_epoch": "總訓練輪數total_epoch", "总训练轮数total_epoch": "總訓練輪數total_epoch",
"每张显卡的batch_size": "每张显卡的batch_size",
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間", "是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
"否": "否",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練大數據緩存會爆 VRAM 也加不了多少速度", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練大數據緩存會爆 VRAM 也加不了多少速度",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存時間點將最終小模型保存至weights檔夾",
"加载预训练底模G路径": "加載預訓練底模G路徑", "加载预训练底模G路径": "加載預訓練底模G路徑",
"加载预训练底模D路径": "加載預訓練底模D路徑", "加载预训练底模D路径": "加載預訓練底模D路徑",
"训练模型": "訓練模型", "训练模型": "訓練模型",
@@ -59,6 +76,7 @@
"模型是否带音高指导": "模型是否帶音高指導", "模型是否带音高指导": "模型是否帶音高指導",
"要置入的模型信息": "要置入的模型資訊", "要置入的模型信息": "要置入的模型資訊",
"保存的模型名不带后缀": "儲存的模型名不帶副檔名", "保存的模型名不带后缀": "儲存的模型名不帶副檔名",
"模型版本型号": "模型版本型號",
"融合": "融合", "融合": "融合",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)", "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
"模型路径": "模型路徑", "模型路径": "模型路徑",
@@ -76,6 +94,7 @@
"Onnx输出路径": "Onnx输出路径", "Onnx输出路径": "Onnx输出路径",
"MoeVS模型": "MoeSS模型", "MoeVS模型": "MoeSS模型",
"导出Onnx模型": "导出Onnx模型", "导出Onnx模型": "导出Onnx模型",
"常见问题解答": "常見問題解答",
"招募音高曲线前端编辑器": "招募音高曲線前端編輯器", "招募音高曲线前端编辑器": "招募音高曲線前端編輯器",
"加开发群联系我xxxxx": "加開發群聯繫我xxxxx", "加开发群联系我xxxxx": "加開發群聯繫我xxxxx",
"点击查看交流、问题反馈群号": "點擊查看交流、問題反饋群號", "点击查看交流、问题反馈群号": "點擊查看交流、問題反饋群號",

View File

@@ -1,36 +1,51 @@
{ {
"很遗憾您这没有能用的显卡来支持您训练": "很遗憾您这没有能用的显卡来支持您训练",
"是": "是",
"step1:正在处理数据": "step1:正在处理数据",
"step2a:无需提取音高": "step2a:无需提取音高",
"step2b:正在提取特征": "step2b:正在提取特征",
"step3a:正在训练模型": "step3a:正在训练模型",
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log",
"全流程结束!": "全流程结束!",
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本軟體以MIT協議開源作者不對軟體具備任何控制力使用軟體者、傳播軟體導出的聲音者自負全責。<br>如不認可該條款,則不能使用或引用軟體包內任何程式碼和檔案。詳見根目錄<b>使用需遵守的協議-LICENSE.txt</b>。", "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本軟體以MIT協議開源作者不對軟體具備任何控制力使用軟體者、傳播軟體導出的聲音者自負全責。<br>如不認可該條款,則不能使用或引用軟體包內任何程式碼和檔案。詳見根目錄<b>使用需遵守的協議-LICENSE.txt</b>。",
"模型推理": "模型推理", "模型推理": "模型推理",
"推理音色": "推理音色", "推理音色": "推理音色",
"刷新音色列表": "重新整理音色列表", "刷新音色列表和索引路径": "刷新音色列表和索引路徑",
"卸载音色省显存": "卸載音色節省 VRAM", "卸载音色省显存": "卸載音色節省 VRAM",
"请选择说话人id": "請選擇說話人ID", "请选择说话人id": "請選擇說話人ID",
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key女性轉男性推薦-12key如果音域爆炸導致音色失真也可以自己調整到合適音域。", "男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性轉女性推薦+12key女性轉男性推薦-12key如果音域爆炸導致音色失真也可以自己調整到合適音域。",
"变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)", "变调(整数, 半音数量, 升八度12降八度-12)": "變調(整數、半音數量、升八度12降八度-12)",
"输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)", "输入待处理音频文件路径(默认是正确格式示例)": "輸入待處理音頻檔案路徑(預設是正確格式示例)",
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "選擇音高提取演算法輸入歌聲可用 pm 提速harvest 低音好但巨慢無比", "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
"特征检索库文件路径": "特徵檢索庫檔案路徑", ">=3则使用对harvest音高识别的结果使用中值滤波数值为滤波半径使用可以削弱哑音": ">=3則使用對harvest音高識別的結果使用中值濾波數值為濾波半徑使用可以削弱啞音",
"特征检索库文件路径,为空则使用下拉的选择结果": "特徵檢索庫檔路徑,為空則使用下拉的選擇結果",
"自动检测index路径,下拉式选择(dropdown)": "自動檢測index路徑,下拉式選擇(dropdown)",
"特征文件路径": "特徵檔案路徑", "特征文件路径": "特徵檔案路徑",
"检索特征占比": "檢索特徵佔比",
"后处理重采样至最终采样率0为不进行重采样": "後處理重採樣至最終採樣率0為不進行重採樣",
"输入源音量包络替换输出音量包络融合比例越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例越靠近1越使用輸出包絡",
"保护清辅音和呼吸声防止电音撕裂等artifact拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲防止電音撕裂等artifact拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案可選一行一個音高代替預設的F0及升降調", "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案可選一行一個音高代替預設的F0及升降調",
"转换": "轉換", "转换": "轉換",
"输出信息": "輸出訊息", "输出信息": "輸出訊息",
"输出音频(右下角三个点,点了可以下载)": "輸出音頻(右下角三個點,點了可以下載)", "输出音频(右下角三个点,点了可以下载)": "輸出音頻(右下角三個點,點了可以下載)",
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量轉換,輸入待轉換音頻資料夾,或上傳多個音頻檔案,在指定資料夾(默認opt)下輸出轉換的音頻。", "批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "批量轉換,輸入待轉換音頻資料夾,或上傳多個音頻檔案,在指定資料夾(默認opt)下輸出轉換的音頻。",
"指定输出文件夹": "指定輸出資料夾", "指定输出文件夹": "指定輸出資料夾",
"检索特征占比": "檢索特徵佔比",
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)", "输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "輸入待處理音頻資料夾路徑(去檔案管理器地址欄拷貝即可)",
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾", "也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量輸入音頻檔案,二選一,優先讀資料夾",
"伴奏人声分离": "伴奏人聲分離", "导出文件格式": "導出檔格式",
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "人聲伴奏分離批量處理使用UVR5模型。<br>不帶和聲用HP2帶和聲且提取的人聲不需要和聲用HP5<br>合格的資料夾路徑格式舉例E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去檔案管理員地址欄複製就行了)", "伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑", "输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
"模型": "模型", "模型": "模型",
"指定输出人声文件夹": "指定輸出人聲資料夾", "指定输出人声文件夹": "指定输出主人声文件夹",
"指定输出乐器文件夹": "指定輸出樂器資料夾", "指定输出非主人声文件夹": "指定输出非主人声文件夹",
"训练": "訓練", "训练": "訓練",
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1填寫實驗配置。實驗數據放在logs下每個實驗一個資料夾需手動輸入實驗名路徑內含實驗配置、日誌、訓練得到的模型檔案。", "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1填寫實驗配置。實驗數據放在logs下每個實驗一個資料夾需手動輸入實驗名路徑內含實驗配置、日誌、訓練得到的模型檔案。",
"输入实验名": "輸入實驗名稱", "输入实验名": "輸入實驗名稱",
"目标采样率": "目標取樣率", "目标采样率": "目標取樣率",
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)", "模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
"版本": "版本",
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化在實驗目錄下生成2個wav資料夾暫時只支援單人訓練。", "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化在實驗目錄下生成2個wav資料夾暫時只支援單人訓練。",
"输入训练文件夹路径": "輸入訓練檔案夾路徑", "输入训练文件夹路径": "輸入訓練檔案夾路徑",
"请指定说话人id": "請指定說話人id", "请指定说话人id": "請指定說話人id",
@@ -38,14 +53,16 @@
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "步驟2b: 使用CPU提取音高(如果模型帶音高), 使用GPU提取特徵(選擇卡號)", "step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "步驟2b: 使用CPU提取音高(如果模型帶音高), 使用GPU提取特徵(選擇卡號)",
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔輸入使用的卡號, 例如 0-1-2 使用卡0和卡1和卡2", "以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "以-分隔輸入使用的卡號, 例如 0-1-2 使用卡0和卡1和卡2",
"显卡信息": "顯示卡資訊", "显卡信息": "顯示卡資訊",
"提取音高使用的CPU进程数": "提取音高使用的CPU進程數",
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "選擇音高提取算法:輸入歌聲可用pm提速,高品質語音但CPU差可用dio提速,harvest品質更好但較慢", "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "選擇音高提取算法:輸入歌聲可用pm提速,高品質語音但CPU差可用dio提速,harvest品質更好但較慢",
"特征提取": "特徵提取", "特征提取": "特徵提取",
"step3: 填写训练设置, 开始训练模型和索引": "步驟3: 填寫訓練設定, 開始訓練模型和索引", "step3: 填写训练设置, 开始训练模型和索引": "步驟3: 填寫訓練設定, 開始訓練模型和索引",
"保存频率save_every_epoch": "保存頻率save_every_epoch", "保存频率save_every_epoch": "保存頻率save_every_epoch",
"总训练轮数total_epoch": "總訓練輪數total_epoch", "总训练轮数total_epoch": "總訓練輪數total_epoch",
"每张显卡的batch_size": "每张显卡的batch_size",
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間", "是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
"否": "否",
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練大數據緩存會爆 VRAM 也加不了多少速度", "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練大數據緩存會爆 VRAM 也加不了多少速度",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存時間點將最終小模型保存至weights檔夾",
"加载预训练底模G路径": "加載預訓練底模G路徑", "加载预训练底模G路径": "加載預訓練底模G路徑",
"加载预训练底模D路径": "加載預訓練底模D路徑", "加载预训练底模D路径": "加載預訓練底模D路徑",
"训练模型": "訓練模型", "训练模型": "訓練模型",
@@ -59,6 +76,7 @@
"模型是否带音高指导": "模型是否帶音高指導", "模型是否带音高指导": "模型是否帶音高指導",
"要置入的模型信息": "要置入的模型資訊", "要置入的模型信息": "要置入的模型資訊",
"保存的模型名不带后缀": "儲存的模型名不帶副檔名", "保存的模型名不带后缀": "儲存的模型名不帶副檔名",
"模型版本型号": "模型版本型號",
"融合": "融合", "融合": "融合",
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)", "修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
"模型路径": "模型路徑", "模型路径": "模型路徑",
@@ -76,6 +94,7 @@
"Onnx输出路径": "Onnx输出路径", "Onnx输出路径": "Onnx输出路径",
"MoeVS模型": "MoeSS模型", "MoeVS模型": "MoeSS模型",
"导出Onnx模型": "导出Onnx模型", "导出Onnx模型": "导出Onnx模型",
"常见问题解答": "常見問題解答",
"招募音高曲线前端编辑器": "招募音高曲線前端編輯器", "招募音高曲线前端编辑器": "招募音高曲線前端編輯器",
"加开发群联系我xxxxx": "加開發群聯繫我xxxxx", "加开发群联系我xxxxx": "加開發群聯繫我xxxxx",
"点击查看交流、问题反馈群号": "點擊查看交流、問題反饋群號", "点击查看交流、问题反馈群号": "點擊查看交流、問題反饋群號",

File diff suppressed because it is too large Load Diff

44
infer/train-index -v2.py Normal file
View File

@@ -0,0 +1,44 @@
"""
格式直接cid为自带的index位aid放不下了通过字典来查反正就5w个
"""
import faiss, numpy as np, os
# ###########如果是原始特征要先写save
inp_root = r"./logs/nene/3_feature768"
npys = []
listdir_res = list(os.listdir(inp_root))
for name in sorted(listdir_res):
phone = np.load("%s/%s" % (inp_root, name))
npys.append(phone)
big_npy = np.concatenate(npys, 0)
big_npy_idx = np.arange(big_npy.shape[0])
np.random.shuffle(big_npy_idx)
big_npy = big_npy[big_npy_idx]
print(big_npy.shape) # (6196072, 192)#fp32#4.43G
np.save("infer/big_src_feature_mi.npy", big_npy)
##################train+add
# big_npy=np.load("/bili-coeus/jupyter/jupyterhub-liujing04/vits_ch/inference_f0/big_src_feature_mi.npy")
n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
index = faiss.index_factory(768, "IVF%s,Flat" % n_ivf) # mi
print("training")
index_ivf = faiss.extract_index_ivf(index) #
index_ivf.nprobe = 1
index.train(big_npy)
faiss.write_index(
index, "infer/trained_IVF%s_Flat_baseline_src_feat_v2.index" % (n_ivf)
)
print("adding")
batch_size_add = 8192
for i in range(0, big_npy.shape[0], batch_size_add):
index.add(big_npy[i : i + batch_size_add])
faiss.write_index(index, "infer/added_IVF%s_Flat_mi_baseline_src_feat.index" % (n_ivf))
"""
大小都是FP32
big_src_feature 2.95G
(3098036, 256)
big_emb 4.43G
(6196072, 192)
big_emb双倍是因为求特征要repeat后再加pitch
"""

217
infer_batch_rvc.py Normal file
View File

@@ -0,0 +1,217 @@
"""
v1
runtime\python.exe myinfer-v2-0528.py 0 "E:\codes\py39\RVC-beta\todo-songs" "E:\codes\py39\logs\mi-test\added_IVF677_Flat_nprobe_7.index" harvest "E:\codes\py39\RVC-beta\output" "E:\codes\py39\test-20230416b\weights\mi-test.pth" 0.66 cuda:0 True 3 0 1 0.33
v2
runtime\python.exe myinfer-v2-0528.py 0 "E:\codes\py39\RVC-beta\todo-songs" "E:\codes\py39\test-20230416b\logs\mi-test-v2\aadded_IVF677_Flat_nprobe_1_v2.index" harvest "E:\codes\py39\RVC-beta\output_v2" "E:\codes\py39\test-20230416b\weights\mi-test-v2.pth" 0.66 cuda:0 True 3 0 1 0.33
"""
import os, sys, pdb, torch
now_dir = os.getcwd()
sys.path.append(now_dir)
import argparse
import glob
import sys
import torch
import tqdm as tq
from multiprocessing import cpu_count
class Config:
def __init__(self, device, is_half):
self.device = device
self.is_half = is_half
self.n_cpu = 0
self.gpu_name = None
self.gpu_mem = None
self.x_pad, self.x_query, self.x_center, self.x_max = self.device_config()
def device_config(self) -> tuple:
if torch.cuda.is_available():
i_device = int(self.device.split(":")[-1])
self.gpu_name = torch.cuda.get_device_name(i_device)
if (
("16" in self.gpu_name and "V100" not in self.gpu_name.upper())
or "P40" in self.gpu_name.upper()
or "1060" in self.gpu_name
or "1070" in self.gpu_name
or "1080" in self.gpu_name
):
print("16系/10系显卡和P40强制单精度")
self.is_half = False
for config_file in ["32k.json", "40k.json", "48k.json"]:
with open(f"configs/{config_file}", "r") as f:
strr = f.read().replace("true", "false")
with open(f"configs/{config_file}", "w") as f:
f.write(strr)
with open("trainset_preprocess_pipeline_print.py", "r") as f:
strr = f.read().replace("3.7", "3.0")
with open("trainset_preprocess_pipeline_print.py", "w") as f:
f.write(strr)
else:
self.gpu_name = None
self.gpu_mem = int(
torch.cuda.get_device_properties(i_device).total_memory
/ 1024
/ 1024
/ 1024
+ 0.4
)
if self.gpu_mem <= 4:
with open("trainset_preprocess_pipeline_print.py", "r") as f:
strr = f.read().replace("3.7", "3.0")
with open("trainset_preprocess_pipeline_print.py", "w") as f:
f.write(strr)
elif torch.backends.mps.is_available():
print("没有发现支持的N卡, 使用MPS进行推理")
self.device = "mps"
else:
print("没有发现支持的N卡, 使用CPU进行推理")
self.device = "cpu"
self.is_half = True
if self.n_cpu == 0:
self.n_cpu = cpu_count()
if self.is_half:
# 6G显存配置
x_pad = 3
x_query = 10
x_center = 60
x_max = 65
else:
# 5G显存配置
x_pad = 1
x_query = 6
x_center = 38
x_max = 41
if self.gpu_mem != None and self.gpu_mem <= 4:
x_pad = 1
x_query = 5
x_center = 30
x_max = 32
return x_pad, x_query, x_center, x_max
f0up_key = sys.argv[1]
input_path = sys.argv[2]
index_path = sys.argv[3]
f0method = sys.argv[4] # harvest or pm
opt_path = sys.argv[5]
model_path = sys.argv[6]
index_rate = float(sys.argv[7])
device = sys.argv[8]
is_half = bool(sys.argv[9])
filter_radius = int(sys.argv[10])
resample_sr = int(sys.argv[11])
rms_mix_rate = float(sys.argv[12])
protect = float(sys.argv[13])
print(sys.argv)
config = Config(device, is_half)
now_dir = os.getcwd()
sys.path.append(now_dir)
from vc_infer_pipeline import VC
from infer_pack.models import (
SynthesizerTrnMs256NSFsid,
SynthesizerTrnMs256NSFsid_nono,
SynthesizerTrnMs768NSFsid,
SynthesizerTrnMs768NSFsid_nono,
)
from my_utils import load_audio
from fairseq import checkpoint_utils
from scipy.io import wavfile
hubert_model = None
def load_hubert():
global hubert_model
models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
["hubert_base.pt"],
suffix="",
)
hubert_model = models[0]
hubert_model = hubert_model.to(device)
if is_half:
hubert_model = hubert_model.half()
else:
hubert_model = hubert_model.float()
hubert_model.eval()
def vc_single(sid, input_audio, f0_up_key, f0_file, f0_method, file_index, index_rate):
global tgt_sr, net_g, vc, hubert_model, version
if input_audio is None:
return "You need to upload an audio", None
f0_up_key = int(f0_up_key)
audio = load_audio(input_audio, 16000)
times = [0, 0, 0]
if hubert_model == None:
load_hubert()
if_f0 = cpt.get("f0", 1)
# audio_opt=vc.pipeline(hubert_model,net_g,sid,audio,times,f0_up_key,f0_method,file_index,file_big_npy,index_rate,if_f0,f0_file=f0_file)
audio_opt = vc.pipeline(
hubert_model,
net_g,
sid,
audio,
input_audio,
times,
f0_up_key,
f0_method,
file_index,
index_rate,
if_f0,
filter_radius,
tgt_sr,
resample_sr,
rms_mix_rate,
version,
protect,
f0_file=f0_file,
)
print(times)
return audio_opt
def get_vc(model_path):
global n_spk, tgt_sr, net_g, vc, cpt, device, is_half, version
print("loading pth %s" % model_path)
cpt = torch.load(model_path, map_location="cpu")
tgt_sr = cpt["config"][-1]
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
if_f0 = cpt.get("f0", 1)
version = cpt.get("version", "v1")
if version == "v1":
if if_f0 == 1:
net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=is_half)
else:
net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
elif version == "v2":
if if_f0 == 1: #
net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=is_half)
else:
net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
del net_g.enc_q
print(net_g.load_state_dict(cpt["weight"], strict=False)) # 不加这一行清不干净,真奇葩
net_g.eval().to(device)
if is_half:
net_g = net_g.half()
else:
net_g = net_g.float()
vc = VC(tgt_sr, config)
n_spk = cpt["config"][-3]
# return {"visible": True,"maximum": n_spk, "__type__": "update"}
get_vc(model_path)
audios = os.listdir(input_path)
for file in tq.tqdm(audios):
if file.endswith(".wav"):
file_path = input_path + "/" + file
wav_opt = vc_single(
0, file_path, f0up_key, None, f0method, index_path, index_rate
)
out_path = opt_path + "/" + file
wavfile.write(out_path, tgt_sr, wav_opt)

View File

@@ -61,7 +61,7 @@ class TextEncoder256(nn.Module):
return m, logs, x_mask return m, logs, x_mask
class TextEncoder256Sim(nn.Module): class TextEncoder768(nn.Module):
def __init__( def __init__(
self, self,
out_channels, out_channels,
@@ -81,14 +81,14 @@ class TextEncoder256Sim(nn.Module):
self.n_layers = n_layers self.n_layers = n_layers
self.kernel_size = kernel_size self.kernel_size = kernel_size
self.p_dropout = p_dropout self.p_dropout = p_dropout
self.emb_phone = nn.Linear(256, hidden_channels) self.emb_phone = nn.Linear(768, hidden_channels)
self.lrelu = nn.LeakyReLU(0.1, inplace=True) self.lrelu = nn.LeakyReLU(0.1, inplace=True)
if f0 == True: if f0 == True:
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256 self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
self.encoder = attentions.Encoder( self.encoder = attentions.Encoder(
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
) )
self.proj = nn.Conv1d(hidden_channels, out_channels, 1) self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
def forward(self, phone, pitch, lengths): def forward(self, phone, pitch, lengths):
if pitch == None: if pitch == None:
@@ -102,8 +102,10 @@ class TextEncoder256Sim(nn.Module):
x.dtype x.dtype
) )
x = self.encoder(x * x_mask, x_mask) x = self.encoder(x * x_mask, x_mask)
x = self.proj(x) * x_mask stats = self.proj(x) * x_mask
return x, x_mask
m, logs = torch.split(stats, self.out_channels, dim=1)
return m, logs, x_mask
class ResidualCouplingBlock(nn.Module): class ResidualCouplingBlock(nn.Module):
@@ -638,6 +640,117 @@ class SynthesizerTrnMs256NSFsid(nn.Module):
return o, x_mask, (z, z_p, m_p, logs_p) return o, x_mask, (z, z_p, m_p, logs_p)
class SynthesizerTrnMs768NSFsid(nn.Module):
def __init__(
self,
spec_channels,
segment_size,
inter_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
spk_embed_dim,
gin_channels,
sr,
**kwargs
):
super().__init__()
if type(sr) == type("strr"):
sr = sr2sr[sr]
self.spec_channels = spec_channels
self.inter_channels = inter_channels
self.hidden_channels = hidden_channels
self.filter_channels = filter_channels
self.n_heads = n_heads
self.n_layers = n_layers
self.kernel_size = kernel_size
self.p_dropout = p_dropout
self.resblock = resblock
self.resblock_kernel_sizes = resblock_kernel_sizes
self.resblock_dilation_sizes = resblock_dilation_sizes
self.upsample_rates = upsample_rates
self.upsample_initial_channel = upsample_initial_channel
self.upsample_kernel_sizes = upsample_kernel_sizes
self.segment_size = segment_size
self.gin_channels = gin_channels
# self.hop_length = hop_length#
self.spk_embed_dim = spk_embed_dim
self.enc_p = TextEncoder768(
inter_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
)
self.dec = GeneratorNSF(
inter_channels,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
gin_channels=gin_channels,
sr=sr,
is_half=kwargs["is_half"],
)
self.enc_q = PosteriorEncoder(
spec_channels,
inter_channels,
hidden_channels,
5,
1,
16,
gin_channels=gin_channels,
)
self.flow = ResidualCouplingBlock(
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
)
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
def remove_weight_norm(self):
self.dec.remove_weight_norm()
self.flow.remove_weight_norm()
self.enc_q.remove_weight_norm()
def forward(
self, phone, phone_lengths, pitch, pitchf, y, y_lengths, ds
): # 这里ds是id[bs,1]
# print(1,pitch.shape)#[bs,t]
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t广播的
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
z_p = self.flow(z, y_mask, g=g)
z_slice, ids_slice = commons.rand_slice_segments(
z, y_lengths, self.segment_size
)
# print(-1,pitchf.shape,ids_slice,self.segment_size,self.hop_length,self.segment_size//self.hop_length)
pitchf = commons.slice_segments2(pitchf, ids_slice, self.segment_size)
# print(-2,pitchf.shape,z_slice.shape)
o = self.dec(z_slice, pitchf, g=g)
return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
def infer(self, phone, phone_lengths, pitch, nsff0, sid, max_len=None):
g = self.emb_g(sid).unsqueeze(-1)
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
z = self.flow(z_p, x_mask, g=g, reverse=True)
o = self.dec((z * x_mask)[:, :, :max_len], nsff0, g=g)
return o, x_mask, (z, z_p, m_p, logs_p)
class SynthesizerTrnMs256NSFsid_nono(nn.Module): class SynthesizerTrnMs256NSFsid_nono(nn.Module):
def __init__( def __init__(
self, self,
@@ -740,11 +853,7 @@ class SynthesizerTrnMs256NSFsid_nono(nn.Module):
return o, x_mask, (z, z_p, m_p, logs_p) return o, x_mask, (z, z_p, m_p, logs_p)
class SynthesizerTrnMs256NSFsid_sim(nn.Module): class SynthesizerTrnMs768NSFsid_nono(nn.Module):
"""
Synthesizer for Training
"""
def __init__( def __init__(
self, self,
spec_channels, spec_channels,
@@ -763,9 +872,8 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
upsample_initial_channel, upsample_initial_channel,
upsample_kernel_sizes, upsample_kernel_sizes,
spk_embed_dim, spk_embed_dim,
# hop_length, gin_channels,
gin_channels=0, sr=None,
use_sdp=True,
**kwargs **kwargs
): ):
super().__init__() super().__init__()
@@ -787,7 +895,7 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
self.gin_channels = gin_channels self.gin_channels = gin_channels
# self.hop_length = hop_length# # self.hop_length = hop_length#
self.spk_embed_dim = spk_embed_dim self.spk_embed_dim = spk_embed_dim
self.enc_p = TextEncoder256Sim( self.enc_p = TextEncoder768(
inter_channels, inter_channels,
hidden_channels, hidden_channels,
filter_channels, filter_channels,
@@ -795,8 +903,9 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
n_layers, n_layers,
kernel_size, kernel_size,
p_dropout, p_dropout,
f0=False,
) )
self.dec = GeneratorNSF( self.dec = Generator(
inter_channels, inter_channels,
resblock, resblock,
resblock_kernel_sizes, resblock_kernel_sizes,
@@ -805,9 +914,16 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
upsample_initial_channel, upsample_initial_channel,
upsample_kernel_sizes, upsample_kernel_sizes,
gin_channels=gin_channels, gin_channels=gin_channels,
is_half=kwargs["is_half"],
) )
self.enc_q = PosteriorEncoder(
spec_channels,
inter_channels,
hidden_channels,
5,
1,
16,
gin_channels=gin_channels,
)
self.flow = ResidualCouplingBlock( self.flow = ResidualCouplingBlock(
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
) )
@@ -819,28 +935,24 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
self.flow.remove_weight_norm() self.flow.remove_weight_norm()
self.enc_q.remove_weight_norm() self.enc_q.remove_weight_norm()
def forward( def forward(self, phone, phone_lengths, y, y_lengths, ds): # 这里ds是id[bs,1]
self, phone, phone_lengths, pitch, pitchf, y_lengths, ds
): # y是spec不需要了现在
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t广播的 g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t广播的
x, x_mask = self.enc_p(phone, pitch, phone_lengths) m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
x = self.flow(x, x_mask, g=g, reverse=True) z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
z_p = self.flow(z, y_mask, g=g)
z_slice, ids_slice = commons.rand_slice_segments( z_slice, ids_slice = commons.rand_slice_segments(
x, y_lengths, self.segment_size z, y_lengths, self.segment_size
) )
o = self.dec(z_slice, g=g)
return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
pitchf = commons.slice_segments2(pitchf, ids_slice, self.segment_size) def infer(self, phone, phone_lengths, sid, max_len=None):
o = self.dec(z_slice, pitchf, g=g) g = self.emb_g(sid).unsqueeze(-1)
return o, ids_slice m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
def infer( z = self.flow(z_p, x_mask, g=g, reverse=True)
self, phone, phone_lengths, pitch, pitchf, ds, max_len=None o = self.dec((z * x_mask)[:, :, :max_len], g=g)
): # y是spec不需要了现在 return o, x_mask, (z, z_p, m_p, logs_p)
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t广播的
x, x_mask = self.enc_p(phone, pitch, phone_lengths)
x = self.flow(x, x_mask, g=g, reverse=True)
o = self.dec((x * x_mask)[:, :, :max_len], pitchf, g=g)
return o, o
class MultiPeriodDiscriminator(torch.nn.Module): class MultiPeriodDiscriminator(torch.nn.Module):
@@ -873,6 +985,36 @@ class MultiPeriodDiscriminator(torch.nn.Module):
return y_d_rs, y_d_gs, fmap_rs, fmap_gs return y_d_rs, y_d_gs, fmap_rs, fmap_gs
class MultiPeriodDiscriminatorV2(torch.nn.Module):
def __init__(self, use_spectral_norm=False):
super(MultiPeriodDiscriminatorV2, self).__init__()
# periods = [2, 3, 5, 7, 11, 17]
periods = [2, 3, 5, 7, 11, 17, 23, 37]
discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
discs = discs + [
DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
]
self.discriminators = nn.ModuleList(discs)
def forward(self, y, y_hat):
y_d_rs = [] #
y_d_gs = []
fmap_rs = []
fmap_gs = []
for i, d in enumerate(self.discriminators):
y_d_r, fmap_r = d(y)
y_d_g, fmap_g = d(y_hat)
# for j in range(len(fmap_r)):
# print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
y_d_rs.append(y_d_r)
y_d_gs.append(y_d_g)
fmap_rs.append(fmap_r)
fmap_gs.append(fmap_g)
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
class DiscriminatorS(torch.nn.Module): class DiscriminatorS(torch.nn.Module):
def __init__(self, use_spectral_norm=False): def __init__(self, use_spectral_norm=False):
super(DiscriminatorS, self).__init__() super(DiscriminatorS, self).__init__()

File diff suppressed because it is too large Load Diff

View File

@@ -1,849 +0,0 @@
import math, pdb, os
from time import time as ttime
import torch
from torch import nn
from torch.nn import functional as F
from infer_pack import modules
from infer_pack import attentions
from infer_pack import commons
from infer_pack.commons import init_weights, get_padding
from torch.nn import Conv1d, ConvTranspose1d, AvgPool1d, Conv2d
from torch.nn.utils import weight_norm, remove_weight_norm, spectral_norm
from infer_pack.commons import init_weights
import numpy as np
from infer_pack import commons
class TextEncoder256(nn.Module):
def __init__(
self,
out_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
f0=True,
):
super().__init__()
self.out_channels = out_channels
self.hidden_channels = hidden_channels
self.filter_channels = filter_channels
self.n_heads = n_heads
self.n_layers = n_layers
self.kernel_size = kernel_size
self.p_dropout = p_dropout
self.emb_phone = nn.Linear(256, hidden_channels)
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
if f0 == True:
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
self.encoder = attentions.Encoder(
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
)
self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
def forward(self, phone, pitch, lengths):
if pitch == None:
x = self.emb_phone(phone)
else:
x = self.emb_phone(phone) + self.emb_pitch(pitch)
x = x * math.sqrt(self.hidden_channels) # [b, t, h]
x = self.lrelu(x)
x = torch.transpose(x, 1, -1) # [b, h, t]
x_mask = torch.unsqueeze(commons.sequence_mask(lengths, x.size(2)), 1).to(
x.dtype
)
x = self.encoder(x * x_mask, x_mask)
stats = self.proj(x) * x_mask
m, logs = torch.split(stats, self.out_channels, dim=1)
return m, logs, x_mask
class TextEncoder256Sim(nn.Module):
def __init__(
self,
out_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
f0=True,
):
super().__init__()
self.out_channels = out_channels
self.hidden_channels = hidden_channels
self.filter_channels = filter_channels
self.n_heads = n_heads
self.n_layers = n_layers
self.kernel_size = kernel_size
self.p_dropout = p_dropout
self.emb_phone = nn.Linear(256, hidden_channels)
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
if f0 == True:
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
self.encoder = attentions.Encoder(
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
)
self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
def forward(self, phone, pitch, lengths):
if pitch == None:
x = self.emb_phone(phone)
else:
x = self.emb_phone(phone) + self.emb_pitch(pitch)
x = x * math.sqrt(self.hidden_channels) # [b, t, h]
x = self.lrelu(x)
x = torch.transpose(x, 1, -1) # [b, h, t]
x_mask = torch.unsqueeze(commons.sequence_mask(lengths, x.size(2)), 1).to(
x.dtype
)
x = self.encoder(x * x_mask, x_mask)
x = self.proj(x) * x_mask
return x, x_mask
class ResidualCouplingBlock(nn.Module):
def __init__(
self,
channels,
hidden_channels,
kernel_size,
dilation_rate,
n_layers,
n_flows=4,
gin_channels=0,
):
super().__init__()
self.channels = channels
self.hidden_channels = hidden_channels
self.kernel_size = kernel_size
self.dilation_rate = dilation_rate
self.n_layers = n_layers
self.n_flows = n_flows
self.gin_channels = gin_channels
self.flows = nn.ModuleList()
for i in range(n_flows):
self.flows.append(
modules.ResidualCouplingLayer(
channels,
hidden_channels,
kernel_size,
dilation_rate,
n_layers,
gin_channels=gin_channels,
mean_only=True,
)
)
self.flows.append(modules.Flip())
def forward(self, x, x_mask, g=None, reverse=False):
if not reverse:
for flow in self.flows:
x, _ = flow(x, x_mask, g=g, reverse=reverse)
else:
for flow in reversed(self.flows):
x = flow(x, x_mask, g=g, reverse=reverse)
return x
def remove_weight_norm(self):
for i in range(self.n_flows):
self.flows[i * 2].remove_weight_norm()
class PosteriorEncoder(nn.Module):
def __init__(
self,
in_channels,
out_channels,
hidden_channels,
kernel_size,
dilation_rate,
n_layers,
gin_channels=0,
):
super().__init__()
self.in_channels = in_channels
self.out_channels = out_channels
self.hidden_channels = hidden_channels
self.kernel_size = kernel_size
self.dilation_rate = dilation_rate
self.n_layers = n_layers
self.gin_channels = gin_channels
self.pre = nn.Conv1d(in_channels, hidden_channels, 1)
self.enc = modules.WN(
hidden_channels,
kernel_size,
dilation_rate,
n_layers,
gin_channels=gin_channels,
)
self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
def forward(self, x, x_lengths, g=None):
x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(
x.dtype
)
x = self.pre(x) * x_mask
x = self.enc(x, x_mask, g=g)
stats = self.proj(x) * x_mask
m, logs = torch.split(stats, self.out_channels, dim=1)
z = (m + torch.randn_like(m) * torch.exp(logs)) * x_mask
return z, m, logs, x_mask
def remove_weight_norm(self):
self.enc.remove_weight_norm()
class Generator(torch.nn.Module):
def __init__(
self,
initial_channel,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
gin_channels=0,
):
super(Generator, self).__init__()
self.num_kernels = len(resblock_kernel_sizes)
self.num_upsamples = len(upsample_rates)
self.conv_pre = Conv1d(
initial_channel, upsample_initial_channel, 7, 1, padding=3
)
resblock = modules.ResBlock1 if resblock == "1" else modules.ResBlock2
self.ups = nn.ModuleList()
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
self.ups.append(
weight_norm(
ConvTranspose1d(
upsample_initial_channel // (2**i),
upsample_initial_channel // (2 ** (i + 1)),
k,
u,
padding=(k - u) // 2,
)
)
)
self.resblocks = nn.ModuleList()
for i in range(len(self.ups)):
ch = upsample_initial_channel // (2 ** (i + 1))
for j, (k, d) in enumerate(
zip(resblock_kernel_sizes, resblock_dilation_sizes)
):
self.resblocks.append(resblock(ch, k, d))
self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
self.ups.apply(init_weights)
if gin_channels != 0:
self.cond = nn.Conv1d(gin_channels, upsample_initial_channel, 1)
def forward(self, x, g=None):
x = self.conv_pre(x)
if g is not None:
x = x + self.cond(g)
for i in range(self.num_upsamples):
x = F.leaky_relu(x, modules.LRELU_SLOPE)
x = self.ups[i](x)
xs = None
for j in range(self.num_kernels):
if xs is None:
xs = self.resblocks[i * self.num_kernels + j](x)
else:
xs += self.resblocks[i * self.num_kernels + j](x)
x = xs / self.num_kernels
x = F.leaky_relu(x)
x = self.conv_post(x)
x = torch.tanh(x)
return x
def remove_weight_norm(self):
for l in self.ups:
remove_weight_norm(l)
for l in self.resblocks:
l.remove_weight_norm()
class SineGen(torch.nn.Module):
"""Definition of sine generator
SineGen(samp_rate, harmonic_num = 0,
sine_amp = 0.1, noise_std = 0.003,
voiced_threshold = 0,
flag_for_pulse=False)
samp_rate: sampling rate in Hz
harmonic_num: number of harmonic overtones (default 0)
sine_amp: amplitude of sine-wavefrom (default 0.1)
noise_std: std of Gaussian noise (default 0.003)
voiced_thoreshold: F0 threshold for U/V classification (default 0)
flag_for_pulse: this SinGen is used inside PulseGen (default False)
Note: when flag_for_pulse is True, the first time step of a voiced
segment is always sin(np.pi) or cos(0)
"""
def __init__(
self,
samp_rate,
harmonic_num=0,
sine_amp=0.1,
noise_std=0.003,
voiced_threshold=0,
flag_for_pulse=False,
):
super(SineGen, self).__init__()
self.sine_amp = sine_amp
self.noise_std = noise_std
self.harmonic_num = harmonic_num
self.dim = self.harmonic_num + 1
self.sampling_rate = samp_rate
self.voiced_threshold = voiced_threshold
def _f02uv(self, f0):
# generate uv signal
uv = torch.ones_like(f0)
uv = uv * (f0 > self.voiced_threshold)
return uv
def forward(self, f0, upp):
"""sine_tensor, uv = forward(f0)
input F0: tensor(batchsize=1, length, dim=1)
f0 for unvoiced steps should be 0
output sine_tensor: tensor(batchsize=1, length, dim)
output uv: tensor(batchsize=1, length, 1)
"""
with torch.no_grad():
f0 = f0[:, None].transpose(1, 2)
f0_buf = torch.zeros(f0.shape[0], f0.shape[1], self.dim, device=f0.device)
# fundamental component
f0_buf[:, :, 0] = f0[:, :, 0]
for idx in np.arange(self.harmonic_num):
f0_buf[:, :, idx + 1] = f0_buf[:, :, 0] * (
idx + 2
) # idx + 2: the (idx+1)-th overtone, (idx+2)-th harmonic
rad_values = (f0_buf / self.sampling_rate) % 1 ###%1意味着n_har的乘积无法后处理优化
rand_ini = torch.rand(
f0_buf.shape[0], f0_buf.shape[2], device=f0_buf.device
)
rand_ini[:, 0] = 0
rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini
tmp_over_one = torch.cumsum(rad_values, 1) # % 1 #####%1意味着后面的cumsum无法再优化
tmp_over_one *= upp
tmp_over_one = F.interpolate(
tmp_over_one.transpose(2, 1),
scale_factor=upp,
mode="linear",
align_corners=True,
).transpose(2, 1)
rad_values = F.interpolate(
rad_values.transpose(2, 1), scale_factor=upp, mode="nearest"
).transpose(
2, 1
) #######
tmp_over_one %= 1
tmp_over_one_idx = (tmp_over_one[:, 1:, :] - tmp_over_one[:, :-1, :]) < 0
cumsum_shift = torch.zeros_like(rad_values)
cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
sine_waves = torch.sin(
torch.cumsum(rad_values + cumsum_shift, dim=1) * 2 * np.pi
)
sine_waves = sine_waves * self.sine_amp
uv = self._f02uv(f0)
uv = F.interpolate(
uv.transpose(2, 1), scale_factor=upp, mode="nearest"
).transpose(2, 1)
noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
noise = noise_amp * torch.randn_like(sine_waves)
sine_waves = sine_waves * uv + noise
return sine_waves, uv, noise
class SourceModuleHnNSF(torch.nn.Module):
"""SourceModule for hn-nsf
SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
add_noise_std=0.003, voiced_threshod=0)
sampling_rate: sampling_rate in Hz
harmonic_num: number of harmonic above F0 (default: 0)
sine_amp: amplitude of sine source signal (default: 0.1)
add_noise_std: std of additive Gaussian noise (default: 0.003)
note that amplitude of noise in unvoiced is decided
by sine_amp
voiced_threshold: threhold to set U/V given F0 (default: 0)
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
F0_sampled (batchsize, length, 1)
Sine_source (batchsize, length, 1)
noise_source (batchsize, length 1)
uv (batchsize, length, 1)
"""
def __init__(
self,
sampling_rate,
harmonic_num=0,
sine_amp=0.1,
add_noise_std=0.003,
voiced_threshod=0,
is_half=True,
):
super(SourceModuleHnNSF, self).__init__()
self.sine_amp = sine_amp
self.noise_std = add_noise_std
self.is_half = is_half
# to produce sine waveforms
self.l_sin_gen = SineGen(
sampling_rate, harmonic_num, sine_amp, add_noise_std, voiced_threshod
)
# to merge source harmonics into a single excitation
self.l_linear = torch.nn.Linear(harmonic_num + 1, 1)
self.l_tanh = torch.nn.Tanh()
def forward(self, x, upp=None):
sine_wavs, uv, _ = self.l_sin_gen(x, upp)
if self.is_half:
sine_wavs = sine_wavs.half()
sine_merge = self.l_tanh(self.l_linear(sine_wavs))
return sine_merge, None, None # noise, uv
class GeneratorNSF(torch.nn.Module):
def __init__(
self,
initial_channel,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
gin_channels,
sr,
is_half=False,
):
super(GeneratorNSF, self).__init__()
self.num_kernels = len(resblock_kernel_sizes)
self.num_upsamples = len(upsample_rates)
self.f0_upsamp = torch.nn.Upsample(scale_factor=np.prod(upsample_rates))
self.m_source = SourceModuleHnNSF(
sampling_rate=sr, harmonic_num=0, is_half=is_half
)
self.noise_convs = nn.ModuleList()
self.conv_pre = Conv1d(
initial_channel, upsample_initial_channel, 7, 1, padding=3
)
resblock = modules.ResBlock1 if resblock == "1" else modules.ResBlock2
self.ups = nn.ModuleList()
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
c_cur = upsample_initial_channel // (2 ** (i + 1))
self.ups.append(
weight_norm(
ConvTranspose1d(
upsample_initial_channel // (2**i),
upsample_initial_channel // (2 ** (i + 1)),
k,
u,
padding=(k - u) // 2,
)
)
)
if i + 1 < len(upsample_rates):
stride_f0 = np.prod(upsample_rates[i + 1 :])
self.noise_convs.append(
Conv1d(
1,
c_cur,
kernel_size=stride_f0 * 2,
stride=stride_f0,
padding=stride_f0 // 2,
)
)
else:
self.noise_convs.append(Conv1d(1, c_cur, kernel_size=1))
self.resblocks = nn.ModuleList()
for i in range(len(self.ups)):
ch = upsample_initial_channel // (2 ** (i + 1))
for j, (k, d) in enumerate(
zip(resblock_kernel_sizes, resblock_dilation_sizes)
):
self.resblocks.append(resblock(ch, k, d))
self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
self.ups.apply(init_weights)
if gin_channels != 0:
self.cond = nn.Conv1d(gin_channels, upsample_initial_channel, 1)
self.upp = np.prod(upsample_rates)
def forward(self, x, f0, g=None):
har_source, noi_source, uv = self.m_source(f0, self.upp)
har_source = har_source.transpose(1, 2)
x = self.conv_pre(x)
if g is not None:
x = x + self.cond(g)
for i in range(self.num_upsamples):
x = F.leaky_relu(x, modules.LRELU_SLOPE)
x = self.ups[i](x)
x_source = self.noise_convs[i](har_source)
x = x + x_source
xs = None
for j in range(self.num_kernels):
if xs is None:
xs = self.resblocks[i * self.num_kernels + j](x)
else:
xs += self.resblocks[i * self.num_kernels + j](x)
x = xs / self.num_kernels
x = F.leaky_relu(x)
x = self.conv_post(x)
x = torch.tanh(x)
return x
def remove_weight_norm(self):
for l in self.ups:
remove_weight_norm(l)
for l in self.resblocks:
l.remove_weight_norm()
sr2sr = {
"32k": 32000,
"40k": 40000,
"48k": 48000,
}
class SynthesizerTrnMs256NSFsidM(nn.Module):
def __init__(
self,
spec_channels,
segment_size,
inter_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
spk_embed_dim,
gin_channels,
sr,
**kwargs
):
super().__init__()
if type(sr) == type("strr"):
sr = sr2sr[sr]
self.spec_channels = spec_channels
self.inter_channels = inter_channels
self.hidden_channels = hidden_channels
self.filter_channels = filter_channels
self.n_heads = n_heads
self.n_layers = n_layers
self.kernel_size = kernel_size
self.p_dropout = p_dropout
self.resblock = resblock
self.resblock_kernel_sizes = resblock_kernel_sizes
self.resblock_dilation_sizes = resblock_dilation_sizes
self.upsample_rates = upsample_rates
self.upsample_initial_channel = upsample_initial_channel
self.upsample_kernel_sizes = upsample_kernel_sizes
self.segment_size = segment_size
self.gin_channels = gin_channels
# self.hop_length = hop_length#
self.spk_embed_dim = spk_embed_dim
self.enc_p = TextEncoder256(
inter_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
)
self.dec = GeneratorNSF(
inter_channels,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
gin_channels=gin_channels,
sr=sr,
is_half=kwargs["is_half"],
)
self.enc_q = PosteriorEncoder(
spec_channels,
inter_channels,
hidden_channels,
5,
1,
16,
gin_channels=gin_channels,
)
self.flow = ResidualCouplingBlock(
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
)
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
def remove_weight_norm(self):
self.dec.remove_weight_norm()
self.flow.remove_weight_norm()
self.enc_q.remove_weight_norm()
def forward(self, phone, phone_lengths, pitch, nsff0, sid, rnd, max_len=None):
g = self.emb_g(sid).unsqueeze(-1)
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
z_p = (m_p + torch.exp(logs_p) * rnd) * x_mask
z = self.flow(z_p, x_mask, g=g, reverse=True)
o = self.dec((z * x_mask)[:, :, :max_len], nsff0, g=g)
return o
class SynthesizerTrnMs256NSFsid_sim(nn.Module):
"""
Synthesizer for Training
"""
def __init__(
self,
spec_channels,
segment_size,
inter_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
spk_embed_dim,
# hop_length,
gin_channels=0,
use_sdp=True,
**kwargs
):
super().__init__()
self.spec_channels = spec_channels
self.inter_channels = inter_channels
self.hidden_channels = hidden_channels
self.filter_channels = filter_channels
self.n_heads = n_heads
self.n_layers = n_layers
self.kernel_size = kernel_size
self.p_dropout = p_dropout
self.resblock = resblock
self.resblock_kernel_sizes = resblock_kernel_sizes
self.resblock_dilation_sizes = resblock_dilation_sizes
self.upsample_rates = upsample_rates
self.upsample_initial_channel = upsample_initial_channel
self.upsample_kernel_sizes = upsample_kernel_sizes
self.segment_size = segment_size
self.gin_channels = gin_channels
# self.hop_length = hop_length#
self.spk_embed_dim = spk_embed_dim
self.enc_p = TextEncoder256Sim(
inter_channels,
hidden_channels,
filter_channels,
n_heads,
n_layers,
kernel_size,
p_dropout,
)
self.dec = GeneratorNSF(
inter_channels,
resblock,
resblock_kernel_sizes,
resblock_dilation_sizes,
upsample_rates,
upsample_initial_channel,
upsample_kernel_sizes,
gin_channels=gin_channels,
is_half=kwargs["is_half"],
)
self.flow = ResidualCouplingBlock(
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
)
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
def remove_weight_norm(self):
self.dec.remove_weight_norm()
self.flow.remove_weight_norm()
self.enc_q.remove_weight_norm()
def forward(
self, phone, phone_lengths, pitch, pitchf, ds, max_len=None
): # y是spec不需要了现在
g = self.emb_g(ds.unsqueeze(0)).unsqueeze(-1) # [b, 256, 1]##1是t广播的
x, x_mask = self.enc_p(phone, pitch, phone_lengths)
x = self.flow(x, x_mask, g=g, reverse=True)
o = self.dec((x * x_mask)[:, :, :max_len], pitchf, g=g)
return o
class MultiPeriodDiscriminator(torch.nn.Module):
def __init__(self, use_spectral_norm=False):
super(MultiPeriodDiscriminator, self).__init__()
periods = [2, 3, 5, 7, 11, 17]
# periods = [3, 5, 7, 11, 17, 23, 37]
discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
discs = discs + [
DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
]
self.discriminators = nn.ModuleList(discs)
def forward(self, y, y_hat):
y_d_rs = [] #
y_d_gs = []
fmap_rs = []
fmap_gs = []
for i, d in enumerate(self.discriminators):
y_d_r, fmap_r = d(y)
y_d_g, fmap_g = d(y_hat)
# for j in range(len(fmap_r)):
# print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
y_d_rs.append(y_d_r)
y_d_gs.append(y_d_g)
fmap_rs.append(fmap_r)
fmap_gs.append(fmap_g)
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
class DiscriminatorS(torch.nn.Module):
def __init__(self, use_spectral_norm=False):
super(DiscriminatorS, self).__init__()
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
self.convs = nn.ModuleList(
[
norm_f(Conv1d(1, 16, 15, 1, padding=7)),
norm_f(Conv1d(16, 64, 41, 4, groups=4, padding=20)),
norm_f(Conv1d(64, 256, 41, 4, groups=16, padding=20)),
norm_f(Conv1d(256, 1024, 41, 4, groups=64, padding=20)),
norm_f(Conv1d(1024, 1024, 41, 4, groups=256, padding=20)),
norm_f(Conv1d(1024, 1024, 5, 1, padding=2)),
]
)
self.conv_post = norm_f(Conv1d(1024, 1, 3, 1, padding=1))
def forward(self, x):
fmap = []
for l in self.convs:
x = l(x)
x = F.leaky_relu(x, modules.LRELU_SLOPE)
fmap.append(x)
x = self.conv_post(x)
fmap.append(x)
x = torch.flatten(x, 1, -1)
return x, fmap
class DiscriminatorP(torch.nn.Module):
def __init__(self, period, kernel_size=5, stride=3, use_spectral_norm=False):
super(DiscriminatorP, self).__init__()
self.period = period
self.use_spectral_norm = use_spectral_norm
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
self.convs = nn.ModuleList(
[
norm_f(
Conv2d(
1,
32,
(kernel_size, 1),
(stride, 1),
padding=(get_padding(kernel_size, 1), 0),
)
),
norm_f(
Conv2d(
32,
128,
(kernel_size, 1),
(stride, 1),
padding=(get_padding(kernel_size, 1), 0),
)
),
norm_f(
Conv2d(
128,
512,
(kernel_size, 1),
(stride, 1),
padding=(get_padding(kernel_size, 1), 0),
)
),
norm_f(
Conv2d(
512,
1024,
(kernel_size, 1),
(stride, 1),
padding=(get_padding(kernel_size, 1), 0),
)
),
norm_f(
Conv2d(
1024,
1024,
(kernel_size, 1),
1,
padding=(get_padding(kernel_size, 1), 0),
)
),
]
)
self.conv_post = norm_f(Conv2d(1024, 1, (3, 1), 1, padding=(1, 0)))
def forward(self, x):
fmap = []
# 1d to 2d
b, c, t = x.shape
if t % self.period != 0: # pad first
n_pad = self.period - (t % self.period)
x = F.pad(x, (0, n_pad), "reflect")
t = t + n_pad
x = x.view(b, c, t // self.period, self.period)
for l in self.convs:
x = l(x)
x = F.leaky_relu(x, modules.LRELU_SLOPE)
fmap.append(x)
x = self.conv_post(x)
fmap.append(x)
x = torch.flatten(x, 1, -1)
return x, fmap

View File

@@ -0,0 +1,90 @@
from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
import pyworld
import numpy as np
class DioF0Predictor(F0Predictor):
def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
self.hop_length = hop_length
self.f0_min = f0_min
self.f0_max = f0_max
self.sampling_rate = sampling_rate
def interpolate_f0(self, f0):
"""
对F0进行插值处理
"""
data = np.reshape(f0, (f0.size, 1))
vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
vuv_vector[data > 0.0] = 1.0
vuv_vector[data <= 0.0] = 0.0
ip_data = data
frame_number = data.size
last_value = 0.0
for i in range(frame_number):
if data[i] <= 0.0:
j = i + 1
for j in range(i + 1, frame_number):
if data[j] > 0.0:
break
if j < frame_number - 1:
if last_value > 0.0:
step = (data[j] - data[i - 1]) / float(j - i)
for k in range(i, j):
ip_data[k] = data[i - 1] + step * (k - i + 1)
else:
for k in range(i, j):
ip_data[k] = data[j]
else:
for k in range(i, frame_number):
ip_data[k] = last_value
else:
ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
last_value = data[i]
return ip_data[:, 0], vuv_vector[:, 0]
def resize_f0(self, x, target_len):
source = np.array(x)
source[source < 0.001] = np.nan
target = np.interp(
np.arange(0, len(source) * target_len, len(source)) / target_len,
np.arange(0, len(source)),
source,
)
res = np.nan_to_num(target)
return res
def compute_f0(self, wav, p_len=None):
if p_len is None:
p_len = wav.shape[0] // self.hop_length
f0, t = pyworld.dio(
wav.astype(np.double),
fs=self.sampling_rate,
f0_floor=self.f0_min,
f0_ceil=self.f0_max,
frame_period=1000 * self.hop_length / self.sampling_rate,
)
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
for index, pitch in enumerate(f0):
f0[index] = round(pitch, 1)
return self.interpolate_f0(self.resize_f0(f0, p_len))[0]
def compute_f0_uv(self, wav, p_len=None):
if p_len is None:
p_len = wav.shape[0] // self.hop_length
f0, t = pyworld.dio(
wav.astype(np.double),
fs=self.sampling_rate,
f0_floor=self.f0_min,
f0_ceil=self.f0_max,
frame_period=1000 * self.hop_length / self.sampling_rate,
)
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
for index, pitch in enumerate(f0):
f0[index] = round(pitch, 1)
return self.interpolate_f0(self.resize_f0(f0, p_len))

View File

@@ -0,0 +1,16 @@
class F0Predictor(object):
def compute_f0(self, wav, p_len):
"""
input: wav:[signal_length]
p_len:int
output: f0:[signal_length//hop_length]
"""
pass
def compute_f0_uv(self, wav, p_len):
"""
input: wav:[signal_length]
p_len:int
output: f0:[signal_length//hop_length],uv:[signal_length//hop_length]
"""
pass

View File

@@ -0,0 +1,86 @@
from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
import pyworld
import numpy as np
class HarvestF0Predictor(F0Predictor):
def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
self.hop_length = hop_length
self.f0_min = f0_min
self.f0_max = f0_max
self.sampling_rate = sampling_rate
def interpolate_f0(self, f0):
"""
对F0进行插值处理
"""
data = np.reshape(f0, (f0.size, 1))
vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
vuv_vector[data > 0.0] = 1.0
vuv_vector[data <= 0.0] = 0.0
ip_data = data
frame_number = data.size
last_value = 0.0
for i in range(frame_number):
if data[i] <= 0.0:
j = i + 1
for j in range(i + 1, frame_number):
if data[j] > 0.0:
break
if j < frame_number - 1:
if last_value > 0.0:
step = (data[j] - data[i - 1]) / float(j - i)
for k in range(i, j):
ip_data[k] = data[i - 1] + step * (k - i + 1)
else:
for k in range(i, j):
ip_data[k] = data[j]
else:
for k in range(i, frame_number):
ip_data[k] = last_value
else:
ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
last_value = data[i]
return ip_data[:, 0], vuv_vector[:, 0]
def resize_f0(self, x, target_len):
source = np.array(x)
source[source < 0.001] = np.nan
target = np.interp(
np.arange(0, len(source) * target_len, len(source)) / target_len,
np.arange(0, len(source)),
source,
)
res = np.nan_to_num(target)
return res
def compute_f0(self, wav, p_len=None):
if p_len is None:
p_len = wav.shape[0] // self.hop_length
f0, t = pyworld.harvest(
wav.astype(np.double),
fs=self.hop_length,
f0_ceil=self.f0_max,
f0_floor=self.f0_min,
frame_period=1000 * self.hop_length / self.sampling_rate,
)
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.fs)
return self.interpolate_f0(self.resize_f0(f0, p_len))[0]
def compute_f0_uv(self, wav, p_len=None):
if p_len is None:
p_len = wav.shape[0] // self.hop_length
f0, t = pyworld.harvest(
wav.astype(np.double),
fs=self.sampling_rate,
f0_floor=self.f0_min,
f0_ceil=self.f0_max,
frame_period=1000 * self.hop_length / self.sampling_rate,
)
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
return self.interpolate_f0(self.resize_f0(f0, p_len))

View File

@@ -0,0 +1,97 @@
from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
import parselmouth
import numpy as np
class PMF0Predictor(F0Predictor):
def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
self.hop_length = hop_length
self.f0_min = f0_min
self.f0_max = f0_max
self.sampling_rate = sampling_rate
def interpolate_f0(self, f0):
"""
对F0进行插值处理
"""
data = np.reshape(f0, (f0.size, 1))
vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
vuv_vector[data > 0.0] = 1.0
vuv_vector[data <= 0.0] = 0.0
ip_data = data
frame_number = data.size
last_value = 0.0
for i in range(frame_number):
if data[i] <= 0.0:
j = i + 1
for j in range(i + 1, frame_number):
if data[j] > 0.0:
break
if j < frame_number - 1:
if last_value > 0.0:
step = (data[j] - data[i - 1]) / float(j - i)
for k in range(i, j):
ip_data[k] = data[i - 1] + step * (k - i + 1)
else:
for k in range(i, j):
ip_data[k] = data[j]
else:
for k in range(i, frame_number):
ip_data[k] = last_value
else:
ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
last_value = data[i]
return ip_data[:, 0], vuv_vector[:, 0]
def compute_f0(self, wav, p_len=None):
x = wav
if p_len is None:
p_len = x.shape[0] // self.hop_length
else:
assert abs(p_len - x.shape[0] // self.hop_length) < 4, "pad length error"
time_step = self.hop_length / self.sampling_rate * 1000
f0 = (
parselmouth.Sound(x, self.sampling_rate)
.to_pitch_ac(
time_step=time_step / 1000,
voicing_threshold=0.6,
pitch_floor=self.f0_min,
pitch_ceiling=self.f0_max,
)
.selected_array["frequency"]
)
pad_size = (p_len - len(f0) + 1) // 2
if pad_size > 0 or p_len - len(f0) - pad_size > 0:
f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
f0, uv = self.interpolate_f0(f0)
return f0
def compute_f0_uv(self, wav, p_len=None):
x = wav
if p_len is None:
p_len = x.shape[0] // self.hop_length
else:
assert abs(p_len - x.shape[0] // self.hop_length) < 4, "pad length error"
time_step = self.hop_length / self.sampling_rate * 1000
f0 = (
parselmouth.Sound(x, self.sampling_rate)
.to_pitch_ac(
time_step=time_step / 1000,
voicing_threshold=0.6,
pitch_floor=self.f0_min,
pitch_ceiling=self.f0_max,
)
.selected_array["frequency"]
)
pad_size = (p_len - len(f0) + 1) // 2
if pad_size > 0 or p_len - len(f0) - pad_size > 0:
f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
f0, uv = self.interpolate_f0(f0)
return f0, uv

View File

@@ -0,0 +1,143 @@
import onnxruntime
import librosa
import numpy as np
import soundfile
class ContentVec:
def __init__(self, vec_path="pretrained/vec-768-layer-12.onnx", device=None):
print("load model(s) from {}".format(vec_path))
if device == "cpu" or device is None:
providers = ["CPUExecutionProvider"]
elif device == "cuda":
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
elif device == "dml":
providers = ["DmlExecutionProvider"]
else:
raise RuntimeError("Unsportted Device")
self.model = onnxruntime.InferenceSession(vec_path, providers=providers)
def __call__(self, wav):
return self.forward(wav)
def forward(self, wav):
feats = wav
if feats.ndim == 2: # double channels
feats = feats.mean(-1)
assert feats.ndim == 1, feats.ndim
feats = np.expand_dims(np.expand_dims(feats, 0), 0)
onnx_input = {self.model.get_inputs()[0].name: feats}
logits = self.model.run(None, onnx_input)[0]
return logits.transpose(0, 2, 1)
def get_f0_predictor(f0_predictor, hop_length, sampling_rate, **kargs):
if f0_predictor == "pm":
from infer_pack.modules.F0Predictor.PMF0Predictor import PMF0Predictor
f0_predictor_object = PMF0Predictor(
hop_length=hop_length, sampling_rate=sampling_rate
)
elif f0_predictor == "harvest":
from infer_pack.modules.F0Predictor.HarvestF0Predictor import HarvestF0Predictor
f0_predictor_object = HarvestF0Predictor(
hop_length=hop_length, sampling_rate=sampling_rate
)
elif f0_predictor == "dio":
from infer_pack.modules.F0Predictor.DioF0Predictor import DioF0Predictor
f0_predictor_object = DioF0Predictor(
hop_length=hop_length, sampling_rate=sampling_rate
)
else:
raise Exception("Unknown f0 predictor")
return f0_predictor_object
class OnnxRVC:
def __init__(
self,
model_path,
sr=40000,
hop_size=512,
vec_path="vec-768-layer-12",
device="cpu",
):
vec_path = f"pretrained/{vec_path}.onnx"
self.vec_model = ContentVec(vec_path, device)
if device == "cpu" or device is None:
providers = ["CPUExecutionProvider"]
elif device == "cuda":
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
elif device == "dml":
providers = ["DmlExecutionProvider"]
else:
raise RuntimeError("Unsportted Device")
self.model = onnxruntime.InferenceSession(model_path, providers=providers)
self.sampling_rate = sr
self.hop_size = hop_size
def forward(self, hubert, hubert_length, pitch, pitchf, ds, rnd):
onnx_input = {
self.model.get_inputs()[0].name: hubert,
self.model.get_inputs()[1].name: hubert_length,
self.model.get_inputs()[2].name: pitch,
self.model.get_inputs()[3].name: pitchf,
self.model.get_inputs()[4].name: ds,
self.model.get_inputs()[5].name: rnd,
}
return (self.model.run(None, onnx_input)[0] * 32767).astype(np.int16)
def inference(
self,
raw_path,
sid,
f0_method="dio",
f0_up_key=0,
pad_time=0.5,
cr_threshold=0.02,
):
f0_min = 50
f0_max = 1100
f0_mel_min = 1127 * np.log(1 + f0_min / 700)
f0_mel_max = 1127 * np.log(1 + f0_max / 700)
f0_predictor = get_f0_predictor(
f0_method,
hop_length=self.hop_size,
sampling_rate=self.sampling_rate,
threshold=cr_threshold,
)
wav, sr = librosa.load(raw_path, sr=self.sampling_rate)
org_length = len(wav)
if org_length / sr > 50.0:
raise RuntimeError("Reached Max Length")
wav16k = librosa.resample(wav, orig_sr=self.sampling_rate, target_sr=16000)
wav16k = wav16k
hubert = self.vec_model(wav16k)
hubert = np.repeat(hubert, 2, axis=2).transpose(0, 2, 1).astype(np.float32)
hubert_length = hubert.shape[1]
pitchf = f0_predictor.compute_f0(wav, hubert_length)
pitchf = pitchf * 2 ** (f0_up_key / 12)
pitch = pitchf.copy()
f0_mel = 1127 * np.log(1 + pitch / 700)
f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - f0_mel_min) * 254 / (
f0_mel_max - f0_mel_min
) + 1
f0_mel[f0_mel <= 1] = 1
f0_mel[f0_mel > 255] = 255
pitch = np.rint(f0_mel).astype(np.int64)
pitchf = pitchf.reshape(1, len(pitchf)).astype(np.float32)
pitch = pitch.reshape(1, len(pitch))
ds = np.array([sid]).astype(np.int64)
rnd = np.random.randn(1, 192, hubert_length).astype(np.float32)
hubert_length = np.array([hubert_length]).astype(np.int64)
out_wav = self.forward(hubert, hubert_length, pitch, pitchf, ds, rnd).squeeze()
out_wav = np.pad(out_wav, (0, 2 * self.hop_size), "constant")
return out_wav[0:org_length]

View File

@@ -1,5 +1,9 @@
import os, sys, torch, warnings, pdb import os, sys, torch, warnings, pdb
now_dir = os.getcwd()
sys.path.append(now_dir)
from json import load as ll
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")
import librosa import librosa
import importlib import importlib
@@ -9,11 +13,13 @@ from tqdm import tqdm
from uvr5_pack.lib_v5 import spec_utils from uvr5_pack.lib_v5 import spec_utils
from uvr5_pack.utils import _get_name_params, inference from uvr5_pack.utils import _get_name_params, inference
from uvr5_pack.lib_v5.model_param_init import ModelParameters from uvr5_pack.lib_v5.model_param_init import ModelParameters
from scipy.io import wavfile import soundfile as sf
from uvr5_pack.lib_v5.nets_new import CascadedNet
from uvr5_pack.lib_v5 import nets_61968KB as nets
class _audio_pre_: class _audio_pre_:
def __init__(self, agg,model_path, device, is_half): def __init__(self, agg, model_path, device, is_half):
self.model_path = model_path self.model_path = model_path
self.device = device self.device = device
self.data = { self.data = {
@@ -25,28 +31,7 @@ class _audio_pre_:
"agg": agg, "agg": agg,
"high_end_process": "mirroring", "high_end_process": "mirroring",
} }
nn_arch_sizes = [ mp = ModelParameters("uvr5_pack/lib_v5/modelparams/4band_v2.json")
31191, # default
33966,
61968,
123821,
123812,
537238, # custom
]
self.nn_architecture = list("{}KB".format(s) for s in nn_arch_sizes)
model_size = math.ceil(os.stat(model_path).st_size / 1024)
nn_architecture = "{}KB".format(
min(nn_arch_sizes, key=lambda x: abs(x - model_size))
)
nets = importlib.import_module(
"uvr5_pack.lib_v5.nets"
+ f"_{nn_architecture}".replace("_{}KB".format(nn_arch_sizes[0]), ""),
package=None,
)
model_hash = hashlib.md5(open(model_path, "rb").read()).hexdigest()
param_name, model_params_d = _get_name_params(model_path, model_hash)
mp = ModelParameters(model_params_d)
model = nets.CascadedASPPNet(mp.param["bins"] * 2) model = nets.CascadedASPPNet(mp.param["bins"] * 2)
cpk = torch.load(model_path, map_location="cpu") cpk = torch.load(model_path, map_location="cpu")
model.load_state_dict(cpk) model.load_state_dict(cpk)
@@ -59,7 +44,7 @@ class _audio_pre_:
self.mp = mp self.mp = mp
self.model = model self.model = model
def _path_audio_(self, music_file, ins_root=None, vocal_root=None): def _path_audio_(self, music_file, ins_root=None, vocal_root=None, format="flac"):
if ins_root is None and vocal_root is None: if ins_root is None and vocal_root is None:
return "No save root." return "No save root."
name = os.path.basename(music_file) name = os.path.basename(music_file)
@@ -138,11 +123,29 @@ class _audio_pre_:
else: else:
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp) wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
print("%s instruments done" % name) print("%s instruments done" % name)
wavfile.write( if format in ["wav", "flac"]:
os.path.join(ins_root, "instrument_{}_{}.wav".format(name,self.data["agg"])), sf.write(
self.mp.param["sr"], os.path.join(
(np.array(wav_instrument) * 32768).astype("int16"), ins_root,
) # "instrument_{}_{}.{}".format(name, self.data["agg"], format),
),
(np.array(wav_instrument) * 32768).astype("int16"),
self.mp.param["sr"],
) #
else:
path = os.path.join(
ins_root, "instrument_{}_{}.wav".format(name, self.data["agg"])
)
sf.write(
path,
(np.array(wav_instrument) * 32768).astype("int16"),
self.mp.param["sr"],
)
if os.path.exists(path):
os.system(
"ffmpeg -i %s -vn %s -q:a 2 -y"
% (path, path[:-4] + ".%s" % format)
)
if vocal_root is not None: if vocal_root is not None:
if self.data["high_end_process"].startswith("mirroring"): if self.data["high_end_process"].startswith("mirroring"):
input_high_end_ = spec_utils.mirroring( input_high_end_ = spec_utils.mirroring(
@@ -154,18 +157,207 @@ class _audio_pre_:
else: else:
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp) wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
print("%s vocals done" % name) print("%s vocals done" % name)
wavfile.write( if format in ["wav", "flac"]:
os.path.join(vocal_root, "vocal_{}_{}.wav".format(name,self.data["agg"])), sf.write(
self.mp.param["sr"], os.path.join(
(np.array(wav_vocals) * 32768).astype("int16"), vocal_root,
"vocal_{}_{}.{}".format(name, self.data["agg"], format),
),
(np.array(wav_vocals) * 32768).astype("int16"),
self.mp.param["sr"],
)
else:
path = os.path.join(
vocal_root, "vocal_{}_{}.wav".format(name, self.data["agg"])
)
sf.write(
path,
(np.array(wav_vocals) * 32768).astype("int16"),
self.mp.param["sr"],
)
if os.path.exists(path):
os.system(
"ffmpeg -i %s -vn %s -q:a 2 -y"
% (path, path[:-4] + ".%s" % format)
)
class _audio_pre_new:
def __init__(self, agg, model_path, device, is_half):
self.model_path = model_path
self.device = device
self.data = {
# Processing Options
"postprocess": False,
"tta": False,
# Constants
"window_size": 512,
"agg": agg,
"high_end_process": "mirroring",
}
mp = ModelParameters("uvr5_pack/lib_v5/modelparams/4band_v3.json")
nout = 64 if "DeReverb" in model_path else 48
model = CascadedNet(mp.param["bins"] * 2, nout)
cpk = torch.load(model_path, map_location="cpu")
model.load_state_dict(cpk)
model.eval()
if is_half:
model = model.half().to(device)
else:
model = model.to(device)
self.mp = mp
self.model = model
def _path_audio_(
self, music_file, vocal_root=None, ins_root=None, format="flac"
): # 3个VR模型vocal和ins是反的
if ins_root is None and vocal_root is None:
return "No save root."
name = os.path.basename(music_file)
if ins_root is not None:
os.makedirs(ins_root, exist_ok=True)
if vocal_root is not None:
os.makedirs(vocal_root, exist_ok=True)
X_wave, y_wave, X_spec_s, y_spec_s = {}, {}, {}, {}
bands_n = len(self.mp.param["band"])
# print(bands_n)
for d in range(bands_n, 0, -1):
bp = self.mp.param["band"][d]
if d == bands_n: # high-end band
(
X_wave[d],
_,
) = librosa.core.load( # 理论上librosa读取可能对某些音频有bug应该上ffmpeg读取但是太麻烦了弃坑
music_file,
bp["sr"],
False,
dtype=np.float32,
res_type=bp["res_type"],
)
if X_wave[d].ndim == 1:
X_wave[d] = np.asfortranarray([X_wave[d], X_wave[d]])
else: # lower bands
X_wave[d] = librosa.core.resample(
X_wave[d + 1],
self.mp.param["band"][d + 1]["sr"],
bp["sr"],
res_type=bp["res_type"],
)
# Stft of wave source
X_spec_s[d] = spec_utils.wave_to_spectrogram_mt(
X_wave[d],
bp["hl"],
bp["n_fft"],
self.mp.param["mid_side"],
self.mp.param["mid_side_b2"],
self.mp.param["reverse"],
) )
# pdb.set_trace()
if d == bands_n and self.data["high_end_process"] != "none":
input_high_end_h = (bp["n_fft"] // 2 - bp["crop_stop"]) + (
self.mp.param["pre_filter_stop"] - self.mp.param["pre_filter_start"]
)
input_high_end = X_spec_s[d][
:, bp["n_fft"] // 2 - input_high_end_h : bp["n_fft"] // 2, :
]
X_spec_m = spec_utils.combine_spectrograms(X_spec_s, self.mp)
aggresive_set = float(self.data["agg"] / 100)
aggressiveness = {
"value": aggresive_set,
"split_bin": self.mp.param["band"][1]["crop_stop"],
}
with torch.no_grad():
pred, X_mag, X_phase = inference(
X_spec_m, self.device, self.model, aggressiveness, self.data
)
# Postprocess
if self.data["postprocess"]:
pred_inv = np.clip(X_mag - pred, 0, np.inf)
pred = spec_utils.mask_silence(pred, pred_inv)
y_spec_m = pred * X_phase
v_spec_m = X_spec_m - y_spec_m
if ins_root is not None:
if self.data["high_end_process"].startswith("mirroring"):
input_high_end_ = spec_utils.mirroring(
self.data["high_end_process"], y_spec_m, input_high_end, self.mp
)
wav_instrument = spec_utils.cmb_spectrogram_to_wave(
y_spec_m, self.mp, input_high_end_h, input_high_end_
)
else:
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
print("%s instruments done" % name)
if format in ["wav", "flac"]:
sf.write(
os.path.join(
ins_root,
"instrument_{}_{}.{}".format(name, self.data["agg"], format),
),
(np.array(wav_instrument) * 32768).astype("int16"),
self.mp.param["sr"],
) #
else:
path = os.path.join(
ins_root, "instrument_{}_{}.wav".format(name, self.data["agg"])
)
sf.write(
path,
(np.array(wav_instrument) * 32768).astype("int16"),
self.mp.param["sr"],
)
if os.path.exists(path):
os.system(
"ffmpeg -i %s -vn %s -q:a 2 -y"
% (path, path[:-4] + ".%s" % format)
)
if vocal_root is not None:
if self.data["high_end_process"].startswith("mirroring"):
input_high_end_ = spec_utils.mirroring(
self.data["high_end_process"], v_spec_m, input_high_end, self.mp
)
wav_vocals = spec_utils.cmb_spectrogram_to_wave(
v_spec_m, self.mp, input_high_end_h, input_high_end_
)
else:
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
print("%s vocals done" % name)
if format in ["wav", "flac"]:
sf.write(
os.path.join(
vocal_root,
"vocal_{}_{}.{}".format(name, self.data["agg"], format),
),
(np.array(wav_vocals) * 32768).astype("int16"),
self.mp.param["sr"],
)
else:
path = os.path.join(
vocal_root, "vocal_{}_{}.wav".format(name, self.data["agg"])
)
sf.write(
path,
(np.array(wav_vocals) * 32768).astype("int16"),
self.mp.param["sr"],
)
if os.path.exists(path):
os.system(
"ffmpeg -i %s -vn %s -q:a 2 -y"
% (path, path[:-4] + ".%s" % format)
)
if __name__ == "__main__": if __name__ == "__main__":
device = "cuda" device = "cuda"
is_half = True is_half = True
model_path = "uvr5_weights/2_HP-UVR.pth" # model_path = "uvr5_weights/2_HP-UVR.pth"
pre_fun = _audio_pre_(model_path=model_path, device=device, is_half=True) # model_path = "uvr5_weights/VR-DeEchoDeReverb.pth"
audio_path = "神女劈观.aac" # model_path = "uvr5_weights/VR-DeEchoNormal.pth"
model_path = "uvr5_weights/DeEchoNormal.pth"
# pre_fun = _audio_pre_(model_path=model_path, device=device, is_half=True,agg=10)
pre_fun = _audio_pre_new(model_path=model_path, device=device, is_half=True, agg=10)
audio_path = "雪雪伴奏对消HP5.wav"
save_path = "opt" save_path = "opt"
pre_fun._path_audio_(audio_path, save_path, save_path) pre_fun._path_audio_(audio_path, save_path, save_path)

Binary file not shown.

20
onnx_inference_demo.py Normal file
View File

@@ -0,0 +1,20 @@
import soundfile
from infer_pack.onnx_inference import OnnxRVC
hop_size = 512
sampling_rate = 40000 # 采样率
f0_up_key = 0 # 升降调
sid = 0 # 角色ID
f0_method = "dio" # F0提取算法
model_path = "ShirohaRVC.onnx" # 模型的完整路径
vec_name = "vec-256-layer-9" # 内部自动补齐为 f"pretrained/{vec_name}.onnx" 需要onnx的vec模型
wav_path = "123.wav" # 输入路径或ByteIO实例
out_path = "out.wav" # 输出路径或ByteIO实例
model = OnnxRVC(
model_path, vec_path=vec_name, sr=sampling_rate, hop_size=hop_size, device="cuda"
)
audio = model.inference(wav_path, sid, f0_method=f0_method, f0_up_key=f0_up_key)
soundfile.write(out_path, audio, sampling_rate)

4129
poetry.lock generated

File diff suppressed because it is too large Load Diff

2
pretrained_v2/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -30,17 +30,17 @@ numba = "0.56.4"
numpy = "1.23.5" numpy = "1.23.5"
scipy = "1.9.3" scipy = "1.9.3"
praat-parselmouth = "^0.4.3" praat-parselmouth = "^0.4.3"
Pillow = "9.1.1" Pillow = "9.3.0"
pyworld = "^0.3.2" pyworld = "^0.3.2"
resampy = "^0.4.2" resampy = "^0.4.2"
scikit-learn = "^1.2.2" scikit-learn = "^1.2.2"
starlette = "^0.26.1" starlette = "^0.27.0"
tensorboard = "^2.12.1" tensorboard = "^2.12.1"
tensorboard-data-server = "^0.7.0" tensorboard-data-server = "^0.7.0"
tensorboard-plugin-wit = "^1.8.1" tensorboard-plugin-wit = "^1.8.1"
torchgen = "^0.0.1" torchgen = "^0.0.1"
tqdm = "^4.65.0" tqdm = "^4.65.0"
tornado = "^6.2" tornado = "^6.3"
Werkzeug = "^2.2.3" Werkzeug = "^2.2.3"
uc-micro-py = "^1.0.1" uc-micro-py = "^1.0.1"
sympy = "^1.11.1" sympy = "^1.11.1"

View File

@@ -1,45 +1,43 @@
joblib>=1.1.0
numba==0.56.4 numba==0.56.4
numpy==1.23.5 numpy==1.23.5
scipy==1.9.3 scipy==1.9.3
librosa==0.9.2 librosa==0.9.1
llvmlite==0.39.0 llvmlite==0.39.0
fairseq==0.12.2 fairseq==0.12.2
faiss-cpu==1.7.0; sys_platform == "darwin" faiss-cpu==1.7.3
faiss-cpu==1.7.2; sys_platform != "darwin" gradio==3.14.0
gradio
Cython Cython
future>=0.18.3
pydub>=0.25.1 pydub>=0.25.1
soundfile>=0.12.1 soundfile>=0.12.1
ffmpeg-python>=0.2.0 ffmpeg-python>=0.2.0
tensorboardX tensorboardX
functorch>=2.0.0
Jinja2>=3.1.2 Jinja2>=3.1.2
json5>=0.9.11 json5
Markdown Markdown
matplotlib>=3.7.1 matplotlib>=3.7.0
matplotlib-inline>=0.1.6 matplotlib-inline>=0.1.3
praat-parselmouth>=0.4.3 praat-parselmouth>=0.4.2
Pillow>=9.1.1 Pillow>=9.1.1
pyworld>=0.3.2
resampy>=0.4.2 resampy>=0.4.2
scikit-learn>=1.2.2 scikit-learn
starlette>=0.26.1 starlette>=0.25.0
tensorboard tensorboard
tensorboard-data-server tqdm>=4.63.1
tensorboard-plugin-wit tornado>=6.1
torchgen>=0.0.1
tqdm>=4.65.0
tornado>=6.2
Werkzeug>=2.2.3 Werkzeug>=2.2.3
uc-micro-py>=1.0.1 uc-micro-py>=1.0.1
sympy>=1.11.1 sympy>=1.11.1
tabulate>=0.9.0 tabulate>=0.8.10
PyYAML>=6.0 PyYAML>=6.0
pyasn1>=0.4.8 pyasn1>=0.4.8
pyasn1-modules>=0.2.8 pyasn1-modules>=0.2.8
fsspec>=2023.3.0 fsspec>=2022.11.0
absl-py>=1.4.0 absl-py>=1.2.0
audioread audioread
uvicorn>=0.21.1 uvicorn>=0.21.1
colorama>=0.4.6 colorama>=0.4.5
pyworld>=0.3.2
httpx==0.23.0
onnxruntime-gpu
torchcrepe==0.0.20

View File

@@ -38,7 +38,7 @@ class TextAudioLoaderMultiNSFsid(torch.utils.data.Dataset):
for audiopath, text, pitch, pitchf, dv in self.audiopaths_and_text: for audiopath, text, pitch, pitchf, dv in self.audiopaths_and_text:
if self.min_text_len <= len(text) and len(text) <= self.max_text_len: if self.min_text_len <= len(text) and len(text) <= self.max_text_len:
audiopaths_and_text_new.append([audiopath, text, pitch, pitchf, dv]) audiopaths_and_text_new.append([audiopath, text, pitch, pitchf, dv])
lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length)) lengths.append(os.path.getsize(audiopath) // (3 * self.hop_length))
self.audiopaths_and_text = audiopaths_and_text_new self.audiopaths_and_text = audiopaths_and_text_new
self.lengths = lengths self.lengths = lengths
@@ -246,7 +246,7 @@ class TextAudioLoader(torch.utils.data.Dataset):
for audiopath, text, dv in self.audiopaths_and_text: for audiopath, text, dv in self.audiopaths_and_text:
if self.min_text_len <= len(text) and len(text) <= self.max_text_len: if self.min_text_len <= len(text) and len(text) <= self.max_text_len:
audiopaths_and_text_new.append([audiopath, text, dv]) audiopaths_and_text_new.append([audiopath, text, dv])
lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length)) lengths.append(os.path.getsize(audiopath) // (3 * self.hop_length))
self.audiopaths_and_text = audiopaths_and_text_new self.audiopaths_and_text = audiopaths_and_text_new
self.lengths = lengths self.lengths = lengths

View File

@@ -51,9 +51,9 @@ def spectrogram_torch(y, n_fft, sampling_rate, hop_size, win_size, center=False)
:: (B, Freq, Frame) - Linear-frequency Linear-amplitude spectrogram :: (B, Freq, Frame) - Linear-frequency Linear-amplitude spectrogram
""" """
# Validation # Validation
if torch.min(y) < -1.0: if torch.min(y) < -1.07:
print("min value is ", torch.min(y)) print("min value is ", torch.min(y))
if torch.max(y) > 1.0: if torch.max(y) > 1.07:
print("max value is ", torch.max(y)) print("max value is ", torch.max(y))
# Window - Cache if needed # Window - Cache if needed

View File

@@ -1,248 +1,215 @@
import torch, traceback, os, pdb import torch, traceback, os, pdb, sys
from collections import OrderedDict
now_dir = os.getcwd()
sys.path.append(now_dir)
def savee(ckpt, sr, if_f0, name, epoch): from collections import OrderedDict
try: from i18n import I18nAuto
opt = OrderedDict()
opt["weight"] = {} i18n = I18nAuto()
for key in ckpt.keys():
if "enc_q" in key:
continue def savee(ckpt, sr, if_f0, name, epoch, version, hps):
opt["weight"][key] = ckpt[key].half() try:
if sr == "40k": opt = OrderedDict()
opt["config"] = [ opt["weight"] = {}
1025, for key in ckpt.keys():
32, if "enc_q" in key:
192, continue
192, opt["weight"][key] = ckpt[key].half()
768, opt["config"] = [
2, hps.data.filter_length // 2 + 1,
6, 32,
3, hps.model.inter_channels,
0, hps.model.hidden_channels,
"1", hps.model.filter_channels,
[3, 7, 11], hps.model.n_heads,
[[1, 3, 5], [1, 3, 5], [1, 3, 5]], hps.model.n_layers,
[10, 10, 2, 2], hps.model.kernel_size,
512, hps.model.p_dropout,
[16, 16, 4, 4], hps.model.resblock,
109, hps.model.resblock_kernel_sizes,
256, hps.model.resblock_dilation_sizes,
40000, hps.model.upsample_rates,
] hps.model.upsample_initial_channel,
elif sr == "48k": hps.model.upsample_kernel_sizes,
opt["config"] = [ hps.model.spk_embed_dim,
1025, hps.model.gin_channels,
32, hps.data.sampling_rate,
192, ]
192, opt["info"] = "%sepoch" % epoch
768, opt["sr"] = sr
2, opt["f0"] = if_f0
6, opt["version"] = version
3, torch.save(opt, "weights/%s.pth" % name)
0, return "Success."
"1", except:
[3, 7, 11], return traceback.format_exc()
[[1, 3, 5], [1, 3, 5], [1, 3, 5]],
[10, 6, 2, 2, 2],
512, def show_info(path):
[16, 16, 4, 4, 4], try:
109, a = torch.load(path, map_location="cpu")
256, return "模型信息:%s\n采样率:%s\n模型是否输入音高引导:%s\n版本:%s" % (
48000, a.get("info", "None"),
] a.get("sr", "None"),
elif sr == "32k": a.get("f0", "None"),
opt["config"] = [ a.get("version", "None"),
513, )
32, except:
192, return traceback.format_exc()
192,
768,
2, def extract_small_model(path, name, sr, if_f0, info, version):
6, try:
3, ckpt = torch.load(path, map_location="cpu")
0, if "model" in ckpt:
"1", ckpt = ckpt["model"]
[3, 7, 11], opt = OrderedDict()
[[1, 3, 5], [1, 3, 5], [1, 3, 5]], opt["weight"] = {}
[10, 4, 2, 2, 2], for key in ckpt.keys():
512, if "enc_q" in key:
[16, 16, 4, 4, 4], continue
109, opt["weight"][key] = ckpt[key].half()
256, if sr == "40k":
32000, opt["config"] = [
] 1025,
opt["info"] = "%sepoch" % epoch 32,
opt["sr"] = sr 192,
opt["f0"] = if_f0 192,
torch.save(opt, "weights/%s.pth" % name) 768,
return "Success." 2,
except: 6,
return traceback.format_exc() 3,
0,
"1",
def show_info(path): [3, 7, 11],
try: [[1, 3, 5], [1, 3, 5], [1, 3, 5]],
a = torch.load(path, map_location="cpu") [10, 10, 2, 2],
return "模型信息:%s\n采样率:%s\n模型是否输入音高引导:%s" % ( 512,
a.get("info", "None"), [16, 16, 4, 4],
a.get("sr", "None"), 109,
a.get("f0", "None"), 256,
) 40000,
except: ]
return traceback.format_exc() elif sr == "48k":
opt["config"] = [
1025,
def extract_small_model(path, name, sr, if_f0, info): 32,
try: 192,
ckpt = torch.load(path, map_location="cpu") 192,
if "model" in ckpt: 768,
ckpt = ckpt["model"] 2,
opt = OrderedDict() 6,
opt["weight"] = {} 3,
for key in ckpt.keys(): 0,
if "enc_q" in key: "1",
continue [3, 7, 11],
opt["weight"][key] = ckpt[key].half() [[1, 3, 5], [1, 3, 5], [1, 3, 5]],
if sr == "40k": [10, 6, 2, 2, 2],
opt["config"] = [ 512,
1025, [16, 16, 4, 4, 4],
32, 109,
192, 256,
192, 48000,
768, ]
2, elif sr == "32k":
6, opt["config"] = [
3, 513,
0, 32,
"1", 192,
[3, 7, 11], 192,
[[1, 3, 5], [1, 3, 5], [1, 3, 5]], 768,
[10, 10, 2, 2], 2,
512, 6,
[16, 16, 4, 4], 3,
109, 0,
256, "1",
40000, [3, 7, 11],
] [[1, 3, 5], [1, 3, 5], [1, 3, 5]],
elif sr == "48k": [10, 4, 2, 2, 2],
opt["config"] = [ 512,
1025, [16, 16, 4, 4, 4],
32, 109,
192, 256,
192, 32000,
768, ]
2, if info == "":
6, info = "Extracted model."
3, opt["info"] = info
0, opt["version"] = version
"1", opt["sr"] = sr
[3, 7, 11], opt["f0"] = int(if_f0)
[[1, 3, 5], [1, 3, 5], [1, 3, 5]], torch.save(opt, "weights/%s.pth" % name)
[10, 6, 2, 2, 2], return "Success."
512, except:
[16, 16, 4, 4, 4], return traceback.format_exc()
109,
256,
48000, def change_info(path, info, name):
] try:
elif sr == "32k": ckpt = torch.load(path, map_location="cpu")
opt["config"] = [ ckpt["info"] = info
513, if name == "":
32, name = os.path.basename(path)
192, torch.save(ckpt, "weights/%s" % name)
192, return "Success."
768, except:
2, return traceback.format_exc()
6,
3,
0, def merge(path1, path2, alpha1, sr, f0, info, name, version):
"1", try:
[3, 7, 11],
[[1, 3, 5], [1, 3, 5], [1, 3, 5]], def extract(ckpt):
[10, 4, 2, 2, 2], a = ckpt["model"]
512, opt = OrderedDict()
[16, 16, 4, 4, 4], opt["weight"] = {}
109, for key in a.keys():
256, if "enc_q" in key:
32000, continue
] opt["weight"][key] = a[key]
if info == "": return opt
info = "Extracted model."
opt["info"] = info ckpt1 = torch.load(path1, map_location="cpu")
opt["sr"] = sr ckpt2 = torch.load(path2, map_location="cpu")
opt["f0"] = int(if_f0) cfg = ckpt1["config"]
torch.save(opt, "weights/%s.pth" % name) if "model" in ckpt1:
return "Success." ckpt1 = extract(ckpt1)
except: else:
return traceback.format_exc() ckpt1 = ckpt1["weight"]
if "model" in ckpt2:
ckpt2 = extract(ckpt2)
def change_info(path, info, name): else:
try: ckpt2 = ckpt2["weight"]
ckpt = torch.load(path, map_location="cpu") if sorted(list(ckpt1.keys())) != sorted(list(ckpt2.keys())):
ckpt["info"] = info return "Fail to merge the models. The model architectures are not the same."
if name == "": opt = OrderedDict()
name = os.path.basename(path) opt["weight"] = {}
torch.save(ckpt, "weights/%s" % name) for key in ckpt1.keys():
return "Success." # try:
except: if key == "emb_g.weight" and ckpt1[key].shape != ckpt2[key].shape:
return traceback.format_exc() min_shape0 = min(ckpt1[key].shape[0], ckpt2[key].shape[0])
opt["weight"][key] = (
alpha1 * (ckpt1[key][:min_shape0].float())
def merge(path1, path2, alpha1, sr, f0, info, name): + (1 - alpha1) * (ckpt2[key][:min_shape0].float())
try: ).half()
else:
def extract(ckpt): opt["weight"][key] = (
a = ckpt["model"] alpha1 * (ckpt1[key].float()) + (1 - alpha1) * (ckpt2[key].float())
opt = OrderedDict() ).half()
opt["weight"] = {} # except:
for key in a.keys(): # pdb.set_trace()
if "enc_q" in key: opt["config"] = cfg
continue """
opt["weight"][key] = a[key] if(sr=="40k"):opt["config"] = [1025, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10, 10, 2, 2], 512, [16, 16, 4, 4,4], 109, 256, 40000]
return opt elif(sr=="48k"):opt["config"] = [1025, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10,6,2,2,2], 512, [16, 16, 4, 4], 109, 256, 48000]
elif(sr=="32k"):opt["config"] = [513, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10, 4, 2, 2, 2], 512, [16, 16, 4, 4,4], 109, 256, 32000]
ckpt1 = torch.load(path1, map_location="cpu") """
ckpt2 = torch.load(path2, map_location="cpu") opt["sr"] = sr
cfg = ckpt1["config"] opt["f0"] = 1 if f0 == i18n("") else 0
if "model" in ckpt1: opt["version"] = version
ckpt1 = extract(ckpt1) opt["info"] = info
else: torch.save(opt, "weights/%s.pth" % name)
ckpt1 = ckpt1["weight"] return "Success."
if "model" in ckpt2: except:
ckpt2 = extract(ckpt2) return traceback.format_exc()
else:
ckpt2 = ckpt2["weight"]
if sorted(list(ckpt1.keys())) != sorted(list(ckpt2.keys())):
return "Fail to merge the models. The model architectures are not the same."
opt = OrderedDict()
opt["weight"] = {}
for key in ckpt1.keys():
# try:
if key == "emb_g.weight" and ckpt1[key].shape != ckpt2[key].shape:
min_shape0 = min(ckpt1[key].shape[0], ckpt2[key].shape[0])
opt["weight"][key] = (
alpha1 * (ckpt1[key][:min_shape0].float())
+ (1 - alpha1) * (ckpt2[key][:min_shape0].float())
).half()
else:
opt["weight"][key] = (
alpha1 * (ckpt1[key].float()) + (1 - alpha1) * (ckpt2[key].float())
).half()
# except:
# pdb.set_trace()
opt["config"] = cfg
"""
if(sr=="40k"):opt["config"] = [1025, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10, 10, 2, 2], 512, [16, 16, 4, 4,4], 109, 256, 40000]
elif(sr=="48k"):opt["config"] = [1025, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10,6,2,2,2], 512, [16, 16, 4, 4], 109, 256, 48000]
elif(sr=="32k"):opt["config"] = [513, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10, 4, 2, 2, 2], 512, [16, 16, 4, 4,4], 109, 256, 32000]
"""
opt["sr"] = sr
opt["f0"] = 1 if f0 == "" else 0
opt["info"] = info
torch.save(opt, "weights/%s.pth" % name)
return "Success."
except:
return traceback.format_exc()

View File

@@ -284,8 +284,8 @@ def get_hparams(init=True):
bs done bs done
pretrainG、pretrainD done pretrainG、pretrainD done
卡号os.en["CUDA_VISIBLE_DEVICES"] done 卡号os.en["CUDA_VISIBLE_DEVICES"] done
if_latest todo if_latest done
模型if_f0 todo 模型if_f0 done
采样率自动选择config done 采样率自动选择config done
是否缓存数据集进GPU:if_cache_data_in_gpu done 是否缓存数据集进GPU:if_cache_data_in_gpu done
@@ -321,6 +321,16 @@ def get_hparams(init=True):
parser.add_argument( parser.add_argument(
"-sr", "--sample_rate", type=str, required=True, help="sample rate, 32k/40k/48k" "-sr", "--sample_rate", type=str, required=True, help="sample rate, 32k/40k/48k"
) )
parser.add_argument(
"-sw",
"--save_every_weights",
type=str,
default="0",
help="save the extracted model in weights directory when saving checkpoints",
)
parser.add_argument(
"-v", "--version", type=str, required=True, help="model version"
)
parser.add_argument( parser.add_argument(
"-f0", "-f0",
"--if_f0", "--if_f0",
@@ -350,7 +360,10 @@ def get_hparams(init=True):
if not os.path.exists(experiment_dir): if not os.path.exists(experiment_dir):
os.makedirs(experiment_dir) os.makedirs(experiment_dir)
config_path = "configs/%s.json" % args.sample_rate if args.version == "v1" or args.sample_rate == "40k":
config_path = "configs/%s.json" % args.sample_rate
else:
config_path = "configs/%s_v2.json" % args.sample_rate
config_save_path = os.path.join(experiment_dir, "config.json") config_save_path = os.path.join(experiment_dir, "config.json")
if init: if init:
with open(config_path, "r") as f: with open(config_path, "r") as f:
@@ -369,11 +382,13 @@ def get_hparams(init=True):
hparams.total_epoch = args.total_epoch hparams.total_epoch = args.total_epoch
hparams.pretrainG = args.pretrainG hparams.pretrainG = args.pretrainG
hparams.pretrainD = args.pretrainD hparams.pretrainD = args.pretrainD
hparams.version = args.version
hparams.gpus = args.gpus hparams.gpus = args.gpus
hparams.train.batch_size = args.batch_size hparams.train.batch_size = args.batch_size
hparams.sample_rate = args.sample_rate hparams.sample_rate = args.sample_rate
hparams.if_f0 = args.if_f0 hparams.if_f0 = args.if_f0
hparams.if_latest = args.if_latest hparams.if_latest = args.if_latest
hparams.save_every_weights = args.save_every_weights
hparams.if_cache_data_in_gpu = args.if_cache_data_in_gpu hparams.if_cache_data_in_gpu = args.if_cache_data_in_gpu
hparams.data.training_files = "%s/filelist.txt" % experiment_dir hparams.data.training_files = "%s/filelist.txt" % experiment_dir
return hparams return hparams

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +1,139 @@
import sys, os, multiprocessing import sys, os, multiprocessing
from scipy import signal from scipy import signal
now_dir = os.getcwd() now_dir = os.getcwd()
sys.path.append(now_dir) sys.path.append(now_dir)
inp_root = sys.argv[1] inp_root = sys.argv[1]
sr = int(sys.argv[2]) sr = int(sys.argv[2])
n_p = int(sys.argv[3]) n_p = int(sys.argv[3])
exp_dir = sys.argv[4] exp_dir = sys.argv[4]
noparallel = sys.argv[5] == "True" noparallel = sys.argv[5] == "True"
import numpy as np, os, traceback import numpy as np, os, traceback
from slicer2 import Slicer from slicer2 import Slicer
import librosa, traceback import librosa, traceback
from scipy.io import wavfile from scipy.io import wavfile
import multiprocessing import multiprocessing
from my_utils import load_audio from my_utils import load_audio
mutex = multiprocessing.Lock() mutex = multiprocessing.Lock()
f = open("%s/preprocess.log" % exp_dir, "a+") f = open("%s/preprocess.log" % exp_dir, "a+")
def println(strr): def println(strr):
mutex.acquire() mutex.acquire()
print(strr) print(strr)
f.write("%s\n" % strr) f.write("%s\n" % strr)
f.flush() f.flush()
mutex.release() mutex.release()
class PreProcess: class PreProcess:
def __init__(self, sr, exp_dir): def __init__(self, sr, exp_dir):
self.slicer = Slicer( self.slicer = Slicer(
sr=sr, sr=sr,
threshold=-40, threshold=-42,
min_length=800, min_length=1500,
min_interval=400, min_interval=400,
hop_size=15, hop_size=15,
max_sil_kept=150, max_sil_kept=500,
) )
self.sr = sr 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.per = 3.7
self.overlap = 0.3 self.overlap = 0.3
self.tail = self.per + self.overlap self.tail = self.per + self.overlap
self.max = 0.95 self.max = 0.9
self.alpha = 0.8 self.alpha = 0.75
self.exp_dir = exp_dir self.exp_dir = exp_dir
self.gt_wavs_dir = "%s/0_gt_wavs" % exp_dir self.gt_wavs_dir = "%s/0_gt_wavs" % exp_dir
self.wavs16k_dir = "%s/1_16k_wavs" % exp_dir self.wavs16k_dir = "%s/1_16k_wavs" % exp_dir
os.makedirs(self.exp_dir, exist_ok=True) os.makedirs(self.exp_dir, exist_ok=True)
os.makedirs(self.gt_wavs_dir, exist_ok=True) os.makedirs(self.gt_wavs_dir, exist_ok=True)
os.makedirs(self.wavs16k_dir, exist_ok=True) os.makedirs(self.wavs16k_dir, exist_ok=True)
def norm_write(self, tmp_audio, idx0, idx1): def norm_write(self, tmp_audio, idx0, idx1):
tmp_audio = (tmp_audio / np.abs(tmp_audio).max() * (self.max * self.alpha)) + ( tmp_max = np.abs(tmp_audio).max()
1 - self.alpha if tmp_max > 2.5:
) * tmp_audio print("%s-%s-%s-filtered" % (idx0, idx1, tmp_max))
wavfile.write( return
"%s/%s_%s.wav" % (self.gt_wavs_dir, idx0, idx1), tmp_audio = (tmp_audio / tmp_max * (self.max * self.alpha)) + (
self.sr, 1 - self.alpha
tmp_audio.astype(np.float32), ) * tmp_audio
) wavfile.write(
tmp_audio = librosa.resample( "%s/%s_%s.wav" % (self.gt_wavs_dir, idx0, idx1),
tmp_audio, orig_sr=self.sr, target_sr=16000 self.sr,
) # , res_type="soxr_vhq" tmp_audio.astype(np.float32),
wavfile.write( )
"%s/%s_%s.wav" % (self.wavs16k_dir, idx0, idx1), tmp_audio = librosa.resample(
16000, tmp_audio, orig_sr=self.sr, target_sr=16000
tmp_audio.astype(np.float32), ) # , res_type="soxr_vhq"
) wavfile.write(
"%s/%s_%s.wav" % (self.wavs16k_dir, idx0, idx1),
def pipeline(self, path, idx0): 16000,
try: tmp_audio.astype(np.float32),
audio = load_audio(path, self.sr) )
# zero phased digital filter cause pre-ringing noise...
# audio = signal.filtfilt(self.bh, self.ah, audio) def pipeline(self, path, idx0):
audio = signal.lfilter(self.bh, self.ah, audio) try:
audio = load_audio(path, self.sr)
idx1 = 0 # zero phased digital filter cause pre-ringing noise...
for audio in self.slicer.slice(audio): # audio = signal.filtfilt(self.bh, self.ah, audio)
i = 0 audio = signal.lfilter(self.bh, self.ah, audio)
while 1:
start = int(self.sr * (self.per - self.overlap) * i) idx1 = 0
i += 1 for audio in self.slicer.slice(audio):
if len(audio[start:]) > self.tail * self.sr: i = 0
tmp_audio = audio[start : start + int(self.per * self.sr)] while 1:
self.norm_write(tmp_audio, idx0, idx1) start = int(self.sr * (self.per - self.overlap) * i)
idx1 += 1 i += 1
else: if len(audio[start:]) > self.tail * self.sr:
tmp_audio = audio[start:] tmp_audio = audio[start : start + int(self.per * self.sr)]
idx1 += 1 self.norm_write(tmp_audio, idx0, idx1)
break idx1 += 1
self.norm_write(tmp_audio, idx0, idx1) else:
println("%s->Suc." % path) tmp_audio = audio[start:]
except: idx1 += 1
println("%s->%s" % (path, traceback.format_exc())) break
self.norm_write(tmp_audio, idx0, idx1)
def pipeline_mp(self, infos): println("%s->Suc." % path)
for path, idx0 in infos: except:
self.pipeline(path, idx0) println("%s->%s" % (path, traceback.format_exc()))
def pipeline_mp_inp_dir(self, inp_root, n_p): def pipeline_mp(self, infos):
try: for path, idx0 in infos:
infos = [ self.pipeline(path, idx0)
("%s/%s" % (inp_root, name), idx)
for idx, name in enumerate(sorted(list(os.listdir(inp_root)))) def pipeline_mp_inp_dir(self, inp_root, n_p):
] try:
if noparallel: infos = [
for i in range(n_p): ("%s/%s" % (inp_root, name), idx)
self.pipeline_mp(infos[i::n_p]) for idx, name in enumerate(sorted(list(os.listdir(inp_root))))
else: ]
ps = [] if noparallel:
for i in range(n_p): for i in range(n_p):
p = multiprocessing.Process( self.pipeline_mp(infos[i::n_p])
target=self.pipeline_mp, args=(infos[i::n_p],) else:
) ps = []
p.start() for i in range(n_p):
ps.append(p) p = multiprocessing.Process(
for p in ps: target=self.pipeline_mp, args=(infos[i::n_p],)
p.join() )
except: ps.append(p)
println("Fail. %s" % traceback.format_exc()) p.start()
for i in range(n_p):
ps[i].join()
def preprocess_trainset(inp_root, sr, n_p, exp_dir): except:
pp = PreProcess(sr, exp_dir) println("Fail. %s" % traceback.format_exc())
println("start preprocess")
println(sys.argv)
pp.pipeline_mp_inp_dir(inp_root, n_p) def preprocess_trainset(inp_root, sr, n_p, exp_dir):
println("end preprocess") pp = PreProcess(sr, exp_dir)
println("start preprocess")
println(sys.argv)
if __name__ == "__main__": pp.pipeline_mp_inp_dir(inp_root, n_p)
preprocess_trainset(inp_root, sr, n_p, exp_dir) println("end preprocess")
if __name__ == "__main__":
preprocess_trainset(inp_root, sr, n_p, exp_dir)

View File

@@ -0,0 +1,125 @@
import torch
from torch import nn
import torch.nn.functional as F
from uvr5_pack.lib_v5 import spec_utils
class Conv2DBNActiv(nn.Module):
def __init__(self, nin, nout, ksize=3, stride=1, pad=1, dilation=1, activ=nn.ReLU):
super(Conv2DBNActiv, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(
nin,
nout,
kernel_size=ksize,
stride=stride,
padding=pad,
dilation=dilation,
bias=False,
),
nn.BatchNorm2d(nout),
activ(),
)
def __call__(self, x):
return self.conv(x)
class Encoder(nn.Module):
def __init__(self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.LeakyReLU):
super(Encoder, self).__init__()
self.conv1 = Conv2DBNActiv(nin, nout, ksize, stride, pad, activ=activ)
self.conv2 = Conv2DBNActiv(nout, nout, ksize, 1, pad, activ=activ)
def __call__(self, x):
h = self.conv1(x)
h = self.conv2(h)
return h
class Decoder(nn.Module):
def __init__(
self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.ReLU, dropout=False
):
super(Decoder, self).__init__()
self.conv1 = Conv2DBNActiv(nin, nout, ksize, 1, pad, activ=activ)
# self.conv2 = Conv2DBNActiv(nout, nout, ksize, 1, pad, activ=activ)
self.dropout = nn.Dropout2d(0.1) if dropout else None
def __call__(self, x, skip=None):
x = F.interpolate(x, scale_factor=2, mode="bilinear", align_corners=True)
if skip is not None:
skip = spec_utils.crop_center(skip, x)
x = torch.cat([x, skip], dim=1)
h = self.conv1(x)
# h = self.conv2(h)
if self.dropout is not None:
h = self.dropout(h)
return h
class ASPPModule(nn.Module):
def __init__(self, nin, nout, dilations=(4, 8, 12), activ=nn.ReLU, dropout=False):
super(ASPPModule, self).__init__()
self.conv1 = nn.Sequential(
nn.AdaptiveAvgPool2d((1, None)),
Conv2DBNActiv(nin, nout, 1, 1, 0, activ=activ),
)
self.conv2 = Conv2DBNActiv(nin, nout, 1, 1, 0, activ=activ)
self.conv3 = Conv2DBNActiv(
nin, nout, 3, 1, dilations[0], dilations[0], activ=activ
)
self.conv4 = Conv2DBNActiv(
nin, nout, 3, 1, dilations[1], dilations[1], activ=activ
)
self.conv5 = Conv2DBNActiv(
nin, nout, 3, 1, dilations[2], dilations[2], activ=activ
)
self.bottleneck = Conv2DBNActiv(nout * 5, nout, 1, 1, 0, activ=activ)
self.dropout = nn.Dropout2d(0.1) if dropout else None
def forward(self, x):
_, _, h, w = x.size()
feat1 = F.interpolate(
self.conv1(x), size=(h, w), mode="bilinear", align_corners=True
)
feat2 = self.conv2(x)
feat3 = self.conv3(x)
feat4 = self.conv4(x)
feat5 = self.conv5(x)
out = torch.cat((feat1, feat2, feat3, feat4, feat5), dim=1)
out = self.bottleneck(out)
if self.dropout is not None:
out = self.dropout(out)
return out
class LSTMModule(nn.Module):
def __init__(self, nin_conv, nin_lstm, nout_lstm):
super(LSTMModule, self).__init__()
self.conv = Conv2DBNActiv(nin_conv, 1, 1, 1, 0)
self.lstm = nn.LSTM(
input_size=nin_lstm, hidden_size=nout_lstm // 2, bidirectional=True
)
self.dense = nn.Sequential(
nn.Linear(nout_lstm, nin_lstm), nn.BatchNorm1d(nin_lstm), nn.ReLU()
)
def forward(self, x):
N, _, nbins, nframes = x.size()
h = self.conv(x)[:, 0] # N, nbins, nframes
h = h.permute(2, 0, 1) # nframes, N, nbins
h, _ = self.lstm(h)
h = self.dense(h.reshape(-1, h.size()[-1])) # nframes * N, nbins
h = h.reshape(nframes, N, 1, nbins)
h = h.permute(1, 2, 3, 0)
return h

View File

@@ -0,0 +1,54 @@
{
"bins": 672,
"unstable_bins": 8,
"reduction_bins": 530,
"band": {
"1": {
"sr": 7350,
"hl": 80,
"n_fft": 640,
"crop_start": 0,
"crop_stop": 85,
"lpf_start": 25,
"lpf_stop": 53,
"res_type": "polyphase"
},
"2": {
"sr": 7350,
"hl": 80,
"n_fft": 320,
"crop_start": 4,
"crop_stop": 87,
"hpf_start": 25,
"hpf_stop": 12,
"lpf_start": 31,
"lpf_stop": 62,
"res_type": "polyphase"
},
"3": {
"sr": 14700,
"hl": 160,
"n_fft": 512,
"crop_start": 17,
"crop_stop": 216,
"hpf_start": 48,
"hpf_stop": 24,
"lpf_start": 139,
"lpf_stop": 210,
"res_type": "polyphase"
},
"4": {
"sr": 44100,
"hl": 480,
"n_fft": 960,
"crop_start": 78,
"crop_stop": 383,
"hpf_start": 130,
"hpf_stop": 86,
"res_type": "kaiser_fast"
}
},
"sr": 44100,
"pre_filter_start": 668,
"pre_filter_stop": 672
}

View File

@@ -0,0 +1,132 @@
import torch
from torch import nn
import torch.nn.functional as F
from uvr5_pack.lib_v5 import layers_new as layers
class BaseNet(nn.Module):
def __init__(
self, nin, nout, nin_lstm, nout_lstm, dilations=((4, 2), (8, 4), (12, 6))
):
super(BaseNet, self).__init__()
self.enc1 = layers.Conv2DBNActiv(nin, nout, 3, 1, 1)
self.enc2 = layers.Encoder(nout, nout * 2, 3, 2, 1)
self.enc3 = layers.Encoder(nout * 2, nout * 4, 3, 2, 1)
self.enc4 = layers.Encoder(nout * 4, nout * 6, 3, 2, 1)
self.enc5 = layers.Encoder(nout * 6, nout * 8, 3, 2, 1)
self.aspp = layers.ASPPModule(nout * 8, nout * 8, dilations, dropout=True)
self.dec4 = layers.Decoder(nout * (6 + 8), nout * 6, 3, 1, 1)
self.dec3 = layers.Decoder(nout * (4 + 6), nout * 4, 3, 1, 1)
self.dec2 = layers.Decoder(nout * (2 + 4), nout * 2, 3, 1, 1)
self.lstm_dec2 = layers.LSTMModule(nout * 2, nin_lstm, nout_lstm)
self.dec1 = layers.Decoder(nout * (1 + 2) + 1, nout * 1, 3, 1, 1)
def __call__(self, x):
e1 = self.enc1(x)
e2 = self.enc2(e1)
e3 = self.enc3(e2)
e4 = self.enc4(e3)
e5 = self.enc5(e4)
h = self.aspp(e5)
h = self.dec4(h, e4)
h = self.dec3(h, e3)
h = self.dec2(h, e2)
h = torch.cat([h, self.lstm_dec2(h)], dim=1)
h = self.dec1(h, e1)
return h
class CascadedNet(nn.Module):
def __init__(self, n_fft, nout=32, nout_lstm=128):
super(CascadedNet, self).__init__()
self.max_bin = n_fft // 2
self.output_bin = n_fft // 2 + 1
self.nin_lstm = self.max_bin // 2
self.offset = 64
self.stg1_low_band_net = nn.Sequential(
BaseNet(2, nout // 2, self.nin_lstm // 2, nout_lstm),
layers.Conv2DBNActiv(nout // 2, nout // 4, 1, 1, 0),
)
self.stg1_high_band_net = BaseNet(
2, nout // 4, self.nin_lstm // 2, nout_lstm // 2
)
self.stg2_low_band_net = nn.Sequential(
BaseNet(nout // 4 + 2, nout, self.nin_lstm // 2, nout_lstm),
layers.Conv2DBNActiv(nout, nout // 2, 1, 1, 0),
)
self.stg2_high_band_net = BaseNet(
nout // 4 + 2, nout // 2, self.nin_lstm // 2, nout_lstm // 2
)
self.stg3_full_band_net = BaseNet(
3 * nout // 4 + 2, nout, self.nin_lstm, nout_lstm
)
self.out = nn.Conv2d(nout, 2, 1, bias=False)
self.aux_out = nn.Conv2d(3 * nout // 4, 2, 1, bias=False)
def forward(self, x):
x = x[:, :, : self.max_bin]
bandw = x.size()[2] // 2
l1_in = x[:, :, :bandw]
h1_in = x[:, :, bandw:]
l1 = self.stg1_low_band_net(l1_in)
h1 = self.stg1_high_band_net(h1_in)
aux1 = torch.cat([l1, h1], dim=2)
l2_in = torch.cat([l1_in, l1], dim=1)
h2_in = torch.cat([h1_in, h1], dim=1)
l2 = self.stg2_low_band_net(l2_in)
h2 = self.stg2_high_band_net(h2_in)
aux2 = torch.cat([l2, h2], dim=2)
f3_in = torch.cat([x, aux1, aux2], dim=1)
f3 = self.stg3_full_band_net(f3_in)
mask = torch.sigmoid(self.out(f3))
mask = F.pad(
input=mask,
pad=(0, 0, 0, self.output_bin - mask.size()[2]),
mode="replicate",
)
if self.training:
aux = torch.cat([aux1, aux2], dim=1)
aux = torch.sigmoid(self.aux_out(aux))
aux = F.pad(
input=aux,
pad=(0, 0, 0, self.output_bin - aux.size()[2]),
mode="replicate",
)
return mask, aux
else:
return mask
def predict_mask(self, x):
mask = self.forward(x)
if self.offset > 0:
mask = mask[:, :, :, self.offset : -self.offset]
assert mask.size()[3] > 0
return mask
def predict(self, x, aggressiveness=None):
mask = self.forward(x)
pred_mag = x * mask
if self.offset > 0:
pred_mag = pred_mag[:, :, :, self.offset : -self.offset]
assert pred_mag.size()[3] > 0
return pred_mag

View File

@@ -1,28 +1,82 @@
import numpy as np, parselmouth, torch, pdb import numpy as np, parselmouth, torch, pdb
from time import time as ttime from time import time as ttime
import torch.nn.functional as F import torch.nn.functional as F
from config import x_pad, x_query, x_center, x_max
import scipy.signal as signal import scipy.signal as signal
import pyworld, os, traceback, faiss import pyworld, os, traceback, faiss, librosa, torchcrepe
from scipy import signal from scipy import signal
from functools import lru_cache
bh, ah = signal.butter(N=5, Wn=48, btype="high", fs=16000) bh, ah = signal.butter(N=5, Wn=48, btype="high", fs=16000)
input_audio_path2wav = {}
@lru_cache
def cache_harvest_f0(input_audio_path, fs, f0max, f0min, frame_period):
audio = input_audio_path2wav[input_audio_path]
f0, t = pyworld.harvest(
audio,
fs=fs,
f0_ceil=f0max,
f0_floor=f0min,
frame_period=frame_period,
)
f0 = pyworld.stonemask(audio, f0, t, fs)
return f0
def change_rms(data1, sr1, data2, sr2, rate): # 1是输入音频2是输出音频,rate是2的占比
# print(data1.max(),data2.max())
rms1 = librosa.feature.rms(
y=data1, frame_length=sr1 // 2 * 2, hop_length=sr1 // 2
) # 每半秒一个点
rms2 = librosa.feature.rms(y=data2, frame_length=sr2 // 2 * 2, hop_length=sr2 // 2)
rms1 = torch.from_numpy(rms1)
rms1 = F.interpolate(
rms1.unsqueeze(0), size=data2.shape[0], mode="linear"
).squeeze()
rms2 = torch.from_numpy(rms2)
rms2 = F.interpolate(
rms2.unsqueeze(0), size=data2.shape[0], mode="linear"
).squeeze()
rms2 = torch.max(rms2, torch.zeros_like(rms2) + 1e-6)
data2 *= (
torch.pow(rms1, torch.tensor(1 - rate))
* torch.pow(rms2, torch.tensor(rate - 1))
).numpy()
return data2
class VC(object): class VC(object):
def __init__(self, tgt_sr, device, is_half): def __init__(self, tgt_sr, config):
self.x_pad, self.x_query, self.x_center, self.x_max, self.is_half = (
config.x_pad,
config.x_query,
config.x_center,
config.x_max,
config.is_half,
)
self.sr = 16000 # hubert输入采样率 self.sr = 16000 # hubert输入采样率
self.window = 160 # 每帧点数 self.window = 160 # 每帧点数
self.t_pad = self.sr * x_pad # 每条前后pad时间 self.t_pad = self.sr * self.x_pad # 每条前后pad时间
self.t_pad_tgt = tgt_sr * x_pad self.t_pad_tgt = tgt_sr * self.x_pad
self.t_pad2 = self.t_pad * 2 self.t_pad2 = self.t_pad * 2
self.t_query = self.sr * x_query # 查询切点前后查询时间 self.t_query = self.sr * self.x_query # 查询切点前后查询时间
self.t_center = self.sr * x_center # 查询切点位置 self.t_center = self.sr * self.x_center # 查询切点位置
self.t_max = self.sr * x_max # 免查询时长阈值 self.t_max = self.sr * self.x_max # 免查询时长阈值
self.device = device self.device = config.device
self.is_half = is_half
def get_f0(self, x, p_len, f0_up_key, f0_method, inp_f0=None): def get_f0(
self,
input_audio_path,
x,
p_len,
f0_up_key,
f0_method,
filter_radius,
inp_f0=None,
):
global input_audio_path2wav
time_step = self.window / self.sr * 1000 time_step = self.window / self.sr * 1000
f0_min = 50 f0_min = 50
f0_max = 1100 f0_max = 1100
@@ -45,15 +99,31 @@ class VC(object):
f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant" f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant"
) )
elif f0_method == "harvest": elif f0_method == "harvest":
f0, t = pyworld.harvest( input_audio_path2wav[input_audio_path] = x.astype(np.double)
x.astype(np.double), f0 = cache_harvest_f0(input_audio_path, self.sr, f0_max, f0_min, 10)
fs=self.sr, if filter_radius > 2:
f0_ceil=f0_max, f0 = signal.medfilt(f0, 3)
f0_floor=f0_min, elif f0_method == "crepe":
frame_period=10, model = "full"
# Pick a batch size that doesn't cause memory errors on your gpu
batch_size = 512
# Compute pitch using first gpu
audio = torch.tensor(np.copy(x))[None].float()
f0, pd = torchcrepe.predict(
audio,
self.sr,
self.window,
f0_min,
f0_max,
model,
batch_size=batch_size,
device=self.device,
return_periodicity=True,
) )
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.sr) pd = torchcrepe.filter.median(pd, 3)
f0 = signal.medfilt(f0, 3) f0 = torchcrepe.filter.mean(f0, 3)
f0[pd < 0.1] = 0
f0 = f0[0].cpu().numpy()
f0 *= pow(2, f0_up_key / 12) f0 *= pow(2, f0_up_key / 12)
# with open("test.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()])) # with open("test.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()]))
tf0 = self.sr // self.window # 每秒f0点数 tf0 = self.sr // self.window # 每秒f0点数
@@ -64,8 +134,10 @@ class VC(object):
replace_f0 = np.interp( replace_f0 = np.interp(
list(range(delta_t)), inp_f0[:, 0] * 100, inp_f0[:, 1] list(range(delta_t)), inp_f0[:, 0] * 100, inp_f0[:, 1]
) )
shape = f0[x_pad * tf0 : x_pad * tf0 + len(replace_f0)].shape[0] shape = f0[self.x_pad * tf0 : self.x_pad * tf0 + len(replace_f0)].shape[0]
f0[x_pad * tf0 : x_pad * tf0 + len(replace_f0)] = replace_f0[:shape] f0[self.x_pad * tf0 : self.x_pad * tf0 + len(replace_f0)] = replace_f0[
:shape
]
# with open("test_opt.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()])) # with open("test_opt.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()]))
f0bak = f0.copy() f0bak = f0.copy()
f0_mel = 1127 * np.log(1 + f0 / 700) f0_mel = 1127 * np.log(1 + f0 / 700)
@@ -89,6 +161,8 @@ class VC(object):
index, index,
big_npy, big_npy,
index_rate, index_rate,
version,
protect,
): # ,file_index,file_big_npy ): # ,file_index,file_big_npy
feats = torch.from_numpy(audio0) feats = torch.from_numpy(audio0)
if self.is_half: if self.is_half:
@@ -104,13 +178,14 @@ class VC(object):
inputs = { inputs = {
"source": feats.to(self.device), "source": feats.to(self.device),
"padding_mask": padding_mask, "padding_mask": padding_mask,
"output_layer": 9, # layer 9 "output_layer": 9 if version == "v1" else 12,
} }
t0 = ttime() t0 = ttime()
with torch.no_grad(): with torch.no_grad():
logits = model.extract_features(**inputs) logits = model.extract_features(**inputs)
feats = model.final_proj(logits[0]) feats = model.final_proj(logits[0]) if version == "v1" else logits[0]
if protect < 0.5 and pitch != None and pitchf != None:
feats0 = feats.clone()
if ( if (
isinstance(index, type(None)) == False isinstance(index, type(None)) == False
and isinstance(big_npy, type(None)) == False and isinstance(big_npy, type(None)) == False
@@ -136,6 +211,10 @@ class VC(object):
) )
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1) feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
if protect < 0.5 and pitch != None and pitchf != None:
feats0 = F.interpolate(feats0.permute(0, 2, 1), scale_factor=2).permute(
0, 2, 1
)
t1 = ttime() t1 = ttime()
p_len = audio0.shape[0] // self.window p_len = audio0.shape[0] // self.window
if feats.shape[1] < p_len: if feats.shape[1] < p_len:
@@ -143,23 +222,26 @@ class VC(object):
if pitch != None and pitchf != None: if pitch != None and pitchf != None:
pitch = pitch[:, :p_len] pitch = pitch[:, :p_len]
pitchf = pitchf[:, :p_len] pitchf = pitchf[:, :p_len]
if protect < 0.5 and pitch != None and pitchf != None:
pitchff = pitchf.clone()
pitchff[pitchf > 0] = 1
pitchff[pitchf < 1] = protect
pitchff = pitchff.unsqueeze(-1)
feats = feats * pitchff + feats0 * (1 - pitchff)
feats = feats.to(feats0.dtype)
p_len = torch.tensor([p_len], device=self.device).long() p_len = torch.tensor([p_len], device=self.device).long()
with torch.no_grad(): with torch.no_grad():
if pitch != None and pitchf != None: if pitch != None and pitchf != None:
audio1 = ( audio1 = (
(net_g.infer(feats, p_len, pitch, pitchf, sid)[0][0, 0] * 32768) (net_g.infer(feats, p_len, pitch, pitchf, sid)[0][0, 0])
.data.cpu() .data.cpu()
.float() .float()
.numpy() .numpy()
.astype(np.int16)
) )
else: else:
audio1 = ( audio1 = (
(net_g.infer(feats, p_len, sid)[0][0, 0] * 32768) (net_g.infer(feats, p_len, sid)[0][0, 0]).data.cpu().float().numpy()
.data.cpu()
.float()
.numpy()
.astype(np.int16)
) )
del feats, p_len, padding_mask del feats, p_len, padding_mask
if torch.cuda.is_available(): if torch.cuda.is_available():
@@ -175,6 +257,7 @@ class VC(object):
net_g, net_g,
sid, sid,
audio, audio,
input_audio_path,
times, times,
f0_up_key, f0_up_key,
f0_method, f0_method,
@@ -182,6 +265,12 @@ class VC(object):
# file_big_npy, # file_big_npy,
index_rate, index_rate,
if_f0, if_f0,
filter_radius,
tgt_sr,
resample_sr,
rms_mix_rate,
version,
protect,
f0_file=None, f0_file=None,
): ):
if ( if (
@@ -236,9 +325,19 @@ class VC(object):
sid = torch.tensor(sid, device=self.device).unsqueeze(0).long() sid = torch.tensor(sid, device=self.device).unsqueeze(0).long()
pitch, pitchf = None, None pitch, pitchf = None, None
if if_f0 == 1: if if_f0 == 1:
pitch, pitchf = self.get_f0(audio_pad, p_len, f0_up_key, f0_method, inp_f0) pitch, pitchf = self.get_f0(
input_audio_path,
audio_pad,
p_len,
f0_up_key,
f0_method,
filter_radius,
inp_f0,
)
pitch = pitch[:p_len] pitch = pitch[:p_len]
pitchf = pitchf[:p_len] pitchf = pitchf[:p_len]
if self.device == "mps":
pitchf = pitchf.astype(np.float32)
pitch = torch.tensor(pitch, device=self.device).unsqueeze(0).long() pitch = torch.tensor(pitch, device=self.device).unsqueeze(0).long()
pitchf = torch.tensor(pitchf, device=self.device).unsqueeze(0).float() pitchf = torch.tensor(pitchf, device=self.device).unsqueeze(0).float()
t2 = ttime() t2 = ttime()
@@ -258,6 +357,8 @@ class VC(object):
index, index,
big_npy, big_npy,
index_rate, index_rate,
version,
protect,
)[self.t_pad_tgt : -self.t_pad_tgt] )[self.t_pad_tgt : -self.t_pad_tgt]
) )
else: else:
@@ -273,6 +374,8 @@ class VC(object):
index, index,
big_npy, big_npy,
index_rate, index_rate,
version,
protect,
)[self.t_pad_tgt : -self.t_pad_tgt] )[self.t_pad_tgt : -self.t_pad_tgt]
) )
s = t s = t
@@ -289,6 +392,8 @@ class VC(object):
index, index,
big_npy, big_npy,
index_rate, index_rate,
version,
protect,
)[self.t_pad_tgt : -self.t_pad_tgt] )[self.t_pad_tgt : -self.t_pad_tgt]
) )
else: else:
@@ -304,9 +409,22 @@ class VC(object):
index, index,
big_npy, big_npy,
index_rate, index_rate,
version,
protect,
)[self.t_pad_tgt : -self.t_pad_tgt] )[self.t_pad_tgt : -self.t_pad_tgt]
) )
audio_opt = np.concatenate(audio_opt) audio_opt = np.concatenate(audio_opt)
if rms_mix_rate != 1:
audio_opt = change_rms(audio, 16000, audio_opt, tgt_sr, rms_mix_rate)
if resample_sr >= 16000 and tgt_sr != resample_sr:
audio_opt = librosa.resample(
audio_opt, orig_sr=tgt_sr, target_sr=resample_sr
)
audio_max = np.abs(audio_opt).max() / 0.99
max_int16 = 32768
if audio_max > 1:
max_int16 /= audio_max
audio_opt = (audio_opt * max_int16).astype(np.int16)
del pitch, pitchf, sid del pitch, pitchf, sid
if torch.cuda.is_available(): if torch.cuda.is_available():
torch.cuda.empty_cache() torch.cuda.empty_cache()