niomataalfin commited on
Commit
d86197b
1 Parent(s): 0757d74
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .env +8 -0
  2. .github/PULL_REQUEST_TEMPLATE.md +30 -0
  3. .github/workflows/docker.yml +70 -0
  4. .github/workflows/genlocale.yml +33 -0
  5. .github/workflows/pull_format.yml +38 -0
  6. .github/workflows/push_format.yml +56 -0
  7. .github/workflows/unitest.yml +36 -0
  8. .gitignore +23 -0
  9. Dockerfile +29 -0
  10. GUI.py +1410 -0
  11. LICENSE +23 -0
  12. MIT协议暨相关引用库协议 +45 -0
  13. README.md +32 -13
  14. Retrieval_based_Voice_Conversion_WebUI.ipynb +403 -0
  15. Retrieval_based_Voice_Conversion_WebUI_v2.ipynb +422 -0
  16. a.png +0 -0
  17. app.py +1463 -0
  18. assets/hubert/.gitignore +2 -0
  19. assets/pretrained/.gitignore +2 -0
  20. assets/pretrained_v2/.gitignore +2 -0
  21. assets/rmvpe/.gitignore +2 -0
  22. assets/uvr5_weights/.gitignore +2 -0
  23. assets/weights/.gitignore +2 -0
  24. audios/somegirl.mp3 +0 -0
  25. audios/someguy.mp3 +0 -0
  26. audios/unachica.mp3 +0 -0
  27. audios/unchico.mp3 +0 -0
  28. configs/config.json +15 -0
  29. configs/config.py +237 -0
  30. configs/v1/32k.json +46 -0
  31. configs/v1/40k.json +46 -0
  32. configs/v1/48k.json +46 -0
  33. configs/v2/32k.json +46 -0
  34. configs/v2/48k.json +46 -0
  35. docker-compose.yml +13 -0
  36. docs/cn/Changelog_CN.md +96 -0
  37. docs/cn/faq.md +108 -0
  38. docs/en/Changelog_EN.md +100 -0
  39. docs/en/README.en.md +155 -0
  40. docs/en/faiss_tips_en.md +102 -0
  41. docs/en/faq_en.md +119 -0
  42. docs/en/training_tips_en.md +65 -0
  43. docs/fr/Changelog_FR.md +102 -0
  44. docs/fr/README.fr.md +146 -0
  45. docs/fr/faiss_tips_fr.md +105 -0
  46. docs/fr/faq_fr.md +169 -0
  47. docs/fr/training_tips_fr.md +65 -0
  48. docs/jp/README.ja.md +109 -0
  49. docs/jp/faiss_tips_ja.md +101 -0
  50. docs/jp/training_tips_ja.md +64 -0
.env ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ OPENBLAS_NUM_THREADS = 1
2
+ no_proxy = localhost, 127.0.0.1, ::1
3
+
4
+ # You can change the location of the model, etc. by changing here
5
+ weight_root = assets/weights
6
+ weight_uvr5_root = assets/uvr5_weights
7
+ index_root = logs
8
+ rmvpe_root = assets/rmvpe
.github/PULL_REQUEST_TEMPLATE.md ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Pull request checklist
2
+
3
+ - [ ] The PR has a proper title. Use [Semantic Commit Messages](https://seesparkbox.com/foundry/semantic_commit_messages). (No more branch-name title please)
4
+ - [ ] Make sure you are requesting the right branch.
5
+ - [ ] Make sure this is ready to be merged into the relevant branch. Please don't create a PR and let it hang for a few days.
6
+ - [ ] Ensure all tests are passing.
7
+ - [ ] Ensure linting is passing.
8
+
9
+ # PR type
10
+
11
+ - Bug fix / new feature / chore
12
+
13
+ # Description
14
+
15
+ - Describe what this pull request is for.
16
+ - What will it affect.
17
+
18
+ # Screenshot
19
+
20
+ - Please include a screenshot if applicable
21
+
22
+ # Localhost url to test on
23
+
24
+ - Please include a url on localhost to test.
25
+
26
+ # Jira Link
27
+
28
+ - Please include a link to the ticket if applicable.
29
+
30
+ [Ticket]()
.github/workflows/docker.yml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Build And Push Docker Image
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ # Sequence of patterns matched against refs/tags
7
+ tags:
8
+ - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ packages: write
15
+ contents: read
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+ - name: Set time zone
19
+ uses: szenius/[email protected]
20
+ with:
21
+ timezoneLinux: "Asia/Shanghai"
22
+ timezoneMacos: "Asia/Shanghai"
23
+ timezoneWindows: "China Standard Time"
24
+
25
+ # # 如果有 dockerhub 账户,可以在github的secrets中配置下面两个,然后取消下面注释的这几行,并在meta步骤的images增加一行 ${{ github.repository }}
26
+ # - name: Login to DockerHub
27
+ # uses: docker/login-action@v1
28
+ # with:
29
+ # username: ${{ secrets.DOCKERHUB_USERNAME }}
30
+ # password: ${{ secrets.DOCKERHUB_TOKEN }}
31
+
32
+ - name: Login to GHCR
33
+ uses: docker/login-action@v2
34
+ with:
35
+ registry: ghcr.io
36
+ username: ${{ github.repository_owner }}
37
+ password: ${{ secrets.GITHUB_TOKEN }}
38
+
39
+ - name: Extract metadata (tags, labels) for Docker
40
+ id: meta
41
+ uses: docker/metadata-action@v4
42
+ with:
43
+ images: |
44
+ ghcr.io/${{ github.repository }}
45
+ # generate Docker tags based on the following events/attributes
46
+ # nightly, master, pr-2, 1.2.3, 1.2, 1
47
+ tags: |
48
+ type=schedule,pattern=nightly
49
+ type=edge
50
+ type=ref,event=branch
51
+ type=ref,event=pr
52
+ type=semver,pattern={{version}}
53
+ type=semver,pattern={{major}}.{{minor}}
54
+ type=semver,pattern={{major}}
55
+
56
+ - name: Set up QEMU
57
+ uses: docker/setup-qemu-action@v2
58
+
59
+ - name: Set up Docker Buildx
60
+ uses: docker/setup-buildx-action@v2
61
+
62
+ - name: Build and push
63
+ id: docker_build
64
+ uses: docker/build-push-action@v4
65
+ with:
66
+ context: .
67
+ platforms: linux/amd64,linux/arm64
68
+ push: true
69
+ tags: ${{ steps.meta.outputs.tags }}
70
+ labels: ${{ steps.meta.outputs.labels }}
.github/workflows/genlocale.yml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: genlocale
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ jobs:
7
+ genlocale:
8
+ name: genlocale
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Check out
12
+ uses: actions/checkout@master
13
+
14
+ - name: Run locale generation
15
+ run: |
16
+ python3 i18n/scan_i18n.py
17
+ cd i18n
18
+ python3 locale_diff.py
19
+
20
+ - name: Commit back
21
+ if: ${{ !github.head_ref }}
22
+ continue-on-error: true
23
+ run: |
24
+ git config --local user.name 'github-actions[bot]'
25
+ git config --local user.email 'github-actions[bot]@users.noreply.github.com'
26
+ git add --all
27
+ git commit -m "🎨 同步 locale"
28
+
29
+ - name: Create Pull Request
30
+ if: ${{ !github.head_ref }}
31
+ continue-on-error: true
32
+ uses: peter-evans/create-pull-request@v4
33
+
.github/workflows/pull_format.yml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: pull format
2
+
3
+ on: [pull_request]
4
+
5
+ permissions:
6
+ contents: write
7
+
8
+ jobs:
9
+ pull_format:
10
+ runs-on: ${{ matrix.os }}
11
+
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10"]
15
+ os: [ubuntu-latest]
16
+ fail-fast: false
17
+
18
+ continue-on-error: true
19
+
20
+ steps:
21
+ - name: checkout
22
+ continue-on-error: true
23
+ uses: actions/checkout@v3
24
+ with:
25
+ ref: ${{ github.head_ref }}
26
+ fetch-depth: 0
27
+
28
+ - name: Set up Python ${{ matrix.python-version }}
29
+ uses: actions/setup-python@v4
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+
33
+ - name: Install Black
34
+ run: pip install "black[jupyter]"
35
+
36
+ - name: Run Black
37
+ # run: black $(git ls-files '*.py')
38
+ run: black .
.github/workflows/push_format.yml ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: push format
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: write
10
+ pull-requests: write
11
+
12
+ jobs:
13
+ push_format:
14
+ runs-on: ${{ matrix.os }}
15
+
16
+ strategy:
17
+ matrix:
18
+ python-version: ["3.10"]
19
+ os: [ubuntu-latest]
20
+ fail-fast: false
21
+
22
+ steps:
23
+ - uses: actions/checkout@v3
24
+ with:
25
+ ref: ${{github.ref_name}}
26
+
27
+ - name: Set up Python ${{ matrix.python-version }}
28
+ uses: actions/setup-python@v4
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+
32
+ - name: Install Black
33
+ run: pip install "black[jupyter]"
34
+
35
+ - name: Run Black
36
+ # run: black $(git ls-files '*.py')
37
+ run: black .
38
+
39
+ - name: Commit Back
40
+ continue-on-error: true
41
+ id: commitback
42
+ run: |
43
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
44
+ git config --local user.name "github-actions[bot]"
45
+ git add --all
46
+ git commit -m "Format code"
47
+
48
+ - name: Create Pull Request
49
+ if: steps.commitback.outcome == 'success'
50
+ continue-on-error: true
51
+ uses: peter-evans/create-pull-request@v5
52
+ with:
53
+ delete-branch: true
54
+ body: Apply Code Formatter Change
55
+ title: Apply Code Formatter Change
56
+ commit-message: Automatic code format
.github/workflows/unitest.yml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: unitest
2
+ on: [ push, pull_request ]
3
+ jobs:
4
+ build:
5
+ runs-on: ${{ matrix.os }}
6
+ strategy:
7
+ matrix:
8
+ python-version: ["3.8", "3.9", "3.10"]
9
+ os: [ubuntu-latest]
10
+ fail-fast: false
11
+
12
+ steps:
13
+ - uses: actions/checkout@master
14
+ - name: Set up Python ${{ matrix.python-version }}
15
+ uses: actions/setup-python@v4
16
+ with:
17
+ python-version: ${{ matrix.python-version }}
18
+ - name: Install dependencies
19
+ run: |
20
+ sudo apt update
21
+ sudo apt -y install ffmpeg
22
+ sudo apt -y install -qq aria2
23
+ aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d ./ -o hubert_base.pt
24
+ python -m pip install --upgrade pip
25
+ python -m pip install --upgrade setuptools
26
+ python -m pip install --upgrade wheel
27
+ pip install torch torchvision torchaudio
28
+ pip install -r requirements.txt
29
+ - name: Test step 1 & 2
30
+ run: |
31
+ mkdir -p logs/mi-test
32
+ touch logs/mi-test/preprocess.log
33
+ python infer/modules/train/preprocess.py logs/mute/0_gt_wavs 48000 8 logs/mi-test True 3.7
34
+ touch logs/mi-test/extract_f0_feature.log
35
+ python infer/modules/train/extract/extract_f0_print.py logs/mi-test $(nproc) pm
36
+ python infer/modules/train/extract_feature_print.py cpu 1 0 0 logs/mi-test v1
.gitignore ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ __pycache__
3
+ /TEMP
4
+ *.pyd
5
+ .venv
6
+ /opt
7
+ tools/aria2c/
8
+ tools/flag.txt
9
+
10
+ # Imported from huggingface.co/lj1995/VoiceConversionWebUI
11
+ /pretrained
12
+ /pretrained_v2
13
+ /uvr5_weights
14
+ hubert_base.pt
15
+ rmvpe.onnx
16
+ rmvpe.pt
17
+
18
+ # Generated by RVC
19
+ /logs
20
+ /weights
21
+
22
+ # To set a Python version for the project
23
+ .tool-versions
Dockerfile ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM python:3.10-bullseye
4
+
5
+ EXPOSE 7865
6
+
7
+ WORKDIR /app
8
+
9
+ COPY . .
10
+
11
+ RUN apt update && apt install -y -qq ffmpeg aria2 && apt clean
12
+
13
+ RUN pip3 install --no-cache-dir -r requirements.txt
14
+
15
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d assets/pretrained_v2/ -o D40k.pth
16
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d assets/pretrained_v2/ -o G40k.pth
17
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -d assets/pretrained_v2/ -o f0D40k.pth
18
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -d assets/pretrained_v2/ -o f0G40k.pth
19
+
20
+ RUN 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 assets/uvr5_weights/ -o HP2-人声vocals+非人声instrumentals.pth
21
+ RUN 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 assets/uvr5_weights/ -o HP5-主旋律人声vocals+其他instrumentals.pth
22
+
23
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d assets/hubert -o hubert_base.pt
24
+
25
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d assets/hubert -o rmvpe.pt
26
+
27
+ VOLUME [ "/app/weights", "/app/opt" ]
28
+
29
+ CMD ["python3", "infer-web.py"]
GUI.py ADDED
@@ -0,0 +1,1410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ import datetime, subprocess
3
+ from mega import Mega
4
+ now_dir = os.getcwd()
5
+ sys.path.append(now_dir)
6
+ import logging
7
+ import shutil
8
+ import threading
9
+ import traceback
10
+ import warnings
11
+ from random import shuffle
12
+ from subprocess import Popen
13
+ from time import sleep
14
+ import json
15
+ import pathlib
16
+
17
+ import fairseq
18
+ import faiss
19
+ import gradio as gr
20
+ import numpy as np
21
+ import torch
22
+ from dotenv import load_dotenv
23
+ from sklearn.cluster import MiniBatchKMeans
24
+
25
+ from configs.config import Config
26
+ from i18n.i18n import I18nAuto
27
+ from infer.lib.train.process_ckpt import (
28
+ change_info,
29
+ extract_small_model,
30
+ merge,
31
+ show_info,
32
+ )
33
+ from infer.modules.uvr5.modules import uvr
34
+ from infer.modules.vc.modules import VC
35
+ logging.getLogger("numba").setLevel(logging.WARNING)
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ tmp = os.path.join(now_dir, "TEMP")
40
+ shutil.rmtree(tmp, ignore_errors=True)
41
+ shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)
42
+ shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)
43
+ os.makedirs(tmp, exist_ok=True)
44
+ os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)
45
+ os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)
46
+ os.environ["TEMP"] = tmp
47
+ warnings.filterwarnings("ignore")
48
+ torch.manual_seed(114514)
49
+
50
+
51
+ load_dotenv()
52
+ config = Config()
53
+ vc = VC(config)
54
+
55
+ if config.dml == True:
56
+
57
+ def forward_dml(ctx, x, scale):
58
+ ctx.scale = scale
59
+ res = x.clone().detach()
60
+ return res
61
+
62
+ fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml
63
+ i18n = I18nAuto()
64
+ logger.info(i18n)
65
+ # 判断是否有能用来训练和加速推理的N卡
66
+ ngpu = torch.cuda.device_count()
67
+ gpu_infos = []
68
+ mem = []
69
+ if_gpu_ok = False
70
+
71
+ if torch.cuda.is_available() or ngpu != 0:
72
+ for i in range(ngpu):
73
+ gpu_name = torch.cuda.get_device_name(i)
74
+ if any(
75
+ value in gpu_name.upper()
76
+ for value in [
77
+ "10",
78
+ "16",
79
+ "20",
80
+ "30",
81
+ "40",
82
+ "A2",
83
+ "A3",
84
+ "A4",
85
+ "P4",
86
+ "A50",
87
+ "500",
88
+ "A60",
89
+ "70",
90
+ "80",
91
+ "90",
92
+ "M4",
93
+ "T4",
94
+ "TITAN",
95
+ ]
96
+ ):
97
+ # A10#A100#V100#A40#P40#M40#K80#A4500
98
+ if_gpu_ok = True # 至少有一张能用的N卡
99
+ gpu_infos.append("%s\t%s" % (i, gpu_name))
100
+ mem.append(
101
+ int(
102
+ torch.cuda.get_device_properties(i).total_memory
103
+ / 1024
104
+ / 1024
105
+ / 1024
106
+ + 0.4
107
+ )
108
+ )
109
+ if if_gpu_ok and len(gpu_infos) > 0:
110
+ gpu_info = "\n".join(gpu_infos)
111
+ default_batch_size = min(mem) // 2
112
+ else:
113
+ gpu_info = i18n("很遗憾您这没有能用的显卡来支持您训练")
114
+ default_batch_size = 1
115
+ gpus = "-".join([i[0] for i in gpu_infos])
116
+
117
+
118
+ class ToolButton(gr.Button, gr.components.FormComponent):
119
+ """Small button with single emoji as text, fits inside gradio forms"""
120
+
121
+ def __init__(self, **kwargs):
122
+ super().__init__(variant="tool", **kwargs)
123
+
124
+ def get_block_name(self):
125
+ return "button"
126
+
127
+
128
+ weight_root = os.getenv("weight_root")
129
+ weight_uvr5_root = os.getenv("weight_uvr5_root")
130
+ index_root = os.getenv("index_root")
131
+
132
+ names = []
133
+ for name in os.listdir(weight_root):
134
+ if name.endswith(".pth"):
135
+ names.append(name)
136
+ index_paths = []
137
+ for root, dirs, files in os.walk(index_root, topdown=False):
138
+ for name in files:
139
+ if name.endswith(".index") and "trained" not in name:
140
+ index_paths.append("%s/%s" % (root, name))
141
+ uvr5_names = []
142
+ for name in os.listdir(weight_uvr5_root):
143
+ if name.endswith(".pth") or "onnx" in name:
144
+ uvr5_names.append(name.replace(".pth", ""))
145
+
146
+
147
+ def change_choices():
148
+ names = []
149
+ for name in os.listdir(weight_root):
150
+ if name.endswith(".pth"):
151
+ names.append(name)
152
+ index_paths = []
153
+ for root, dirs, files in os.walk(index_root, topdown=False):
154
+ for name in files:
155
+ if name.endswith(".index") and "trained" not in name:
156
+ index_paths.append("%s/%s" % (root, name))
157
+ audio_files=[]
158
+ for filename in os.listdir("./audios"):
159
+ if filename.endswith(('.wav','.mp3','.ogg')):
160
+ audio_files.append('./audios/'+filename)
161
+ return {"choices": sorted(names), "__type__": "update"}, {
162
+ "choices": sorted(index_paths),
163
+ "__type__": "update",
164
+ }, {"choices": sorted(audio_files), "__type__": "update"}
165
+
166
+ def clean():
167
+ return {"value": "", "__type__": "update"}
168
+
169
+
170
+ def export_onnx():
171
+ from infer.modules.onnx.export import export_onnx as eo
172
+
173
+ eo()
174
+
175
+
176
+ sr_dict = {
177
+ "32k": 32000,
178
+ "40k": 40000,
179
+ "48k": 48000,
180
+ }
181
+
182
+
183
+ def if_done(done, p):
184
+ while 1:
185
+ if p.poll() is None:
186
+ sleep(0.5)
187
+ else:
188
+ break
189
+ done[0] = True
190
+
191
+
192
+ def if_done_multi(done, ps):
193
+ while 1:
194
+ # poll==None代表进程未结束
195
+ # 只要有一个进程未结束都不停
196
+ flag = 1
197
+ for p in ps:
198
+ if p.poll() is None:
199
+ flag = 0
200
+ sleep(0.5)
201
+ break
202
+ if flag == 1:
203
+ break
204
+ done[0] = True
205
+
206
+
207
+ def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):
208
+ sr = sr_dict[sr]
209
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
210
+ f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")
211
+ f.close()
212
+ per = 3.0 if config.is_half else 3.7
213
+ cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (
214
+ config.python_cmd,
215
+ trainset_dir,
216
+ sr,
217
+ n_p,
218
+ now_dir,
219
+ exp_dir,
220
+ config.noparallel,
221
+ per,
222
+ )
223
+ logger.info(cmd)
224
+ p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir
225
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
226
+ done = [False]
227
+ threading.Thread(
228
+ target=if_done,
229
+ args=(
230
+ done,
231
+ p,
232
+ ),
233
+ ).start()
234
+ while 1:
235
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
236
+ yield (f.read())
237
+ sleep(1)
238
+ if done[0]:
239
+ break
240
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
241
+ log = f.read()
242
+ logger.info(log)
243
+ yield log
244
+
245
+
246
+ # but2.click(extract_f0,[gpus6,np7,f0method8,if_f0_3,trainset_dir4],[info2])
247
+ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, gpus_rmvpe):
248
+ gpus = gpus.split("-")
249
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
250
+ f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")
251
+ f.close()
252
+ if if_f0:
253
+ if f0method != "rmvpe_gpu":
254
+ cmd = (
255
+ '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'
256
+ % (
257
+ config.python_cmd,
258
+ now_dir,
259
+ exp_dir,
260
+ n_p,
261
+ f0method,
262
+ )
263
+ )
264
+ logger.info(cmd)
265
+ p = Popen(
266
+ cmd, shell=True, cwd=now_dir
267
+ ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE
268
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
269
+ done = [False]
270
+ threading.Thread(
271
+ target=if_done,
272
+ args=(
273
+ done,
274
+ p,
275
+ ),
276
+ ).start()
277
+ else:
278
+ if gpus_rmvpe != "-":
279
+ gpus_rmvpe = gpus_rmvpe.split("-")
280
+ leng = len(gpus_rmvpe)
281
+ ps = []
282
+ for idx, n_g in enumerate(gpus_rmvpe):
283
+ cmd = (
284
+ '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '
285
+ % (
286
+ config.python_cmd,
287
+ leng,
288
+ idx,
289
+ n_g,
290
+ now_dir,
291
+ exp_dir,
292
+ config.is_half,
293
+ )
294
+ )
295
+ logger.info(cmd)
296
+ p = Popen(
297
+ cmd, shell=True, cwd=now_dir
298
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
299
+ ps.append(p)
300
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
301
+ done = [False]
302
+ threading.Thread(
303
+ target=if_done_multi, #
304
+ args=(
305
+ done,
306
+ ps,
307
+ ),
308
+ ).start()
309
+ else:
310
+ cmd = (
311
+ config.python_cmd
312
+ + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '
313
+ % (
314
+ now_dir,
315
+ exp_dir,
316
+ )
317
+ )
318
+ logger.info(cmd)
319
+ p = Popen(
320
+ cmd, shell=True, cwd=now_dir
321
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
322
+ p.wait()
323
+ done = [True]
324
+ while 1:
325
+ with open(
326
+ "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"
327
+ ) as f:
328
+ yield (f.read())
329
+ sleep(1)
330
+ if done[0]:
331
+ break
332
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
333
+ log = f.read()
334
+ logger.info(log)
335
+ yield log
336
+ ####对不同part分别开多进程
337
+ """
338
+ n_part=int(sys.argv[1])
339
+ i_part=int(sys.argv[2])
340
+ i_gpu=sys.argv[3]
341
+ exp_dir=sys.argv[4]
342
+ os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)
343
+ """
344
+ leng = len(gpus)
345
+ ps = []
346
+ for idx, n_g in enumerate(gpus):
347
+ cmd = (
348
+ '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'
349
+ % (
350
+ config.python_cmd,
351
+ config.device,
352
+ leng,
353
+ idx,
354
+ n_g,
355
+ now_dir,
356
+ exp_dir,
357
+ version19,
358
+ )
359
+ )
360
+ logger.info(cmd)
361
+ p = Popen(
362
+ cmd, shell=True, cwd=now_dir
363
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
364
+ ps.append(p)
365
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
366
+ done = [False]
367
+ threading.Thread(
368
+ target=if_done_multi,
369
+ args=(
370
+ done,
371
+ ps,
372
+ ),
373
+ ).start()
374
+ while 1:
375
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
376
+ yield (f.read())
377
+ sleep(1)
378
+ if done[0]:
379
+ break
380
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
381
+ log = f.read()
382
+ logger.info(log)
383
+ yield log
384
+
385
+
386
+ def get_pretrained_models(path_str, f0_str, sr2):
387
+ if_pretrained_generator_exist = os.access(
388
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
389
+ )
390
+ if_pretrained_discriminator_exist = os.access(
391
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
392
+ )
393
+ if not if_pretrained_generator_exist:
394
+ logger.warn(
395
+ "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",
396
+ path_str,
397
+ f0_str,
398
+ sr2,
399
+ )
400
+ if not if_pretrained_discriminator_exist:
401
+ logger.warn(
402
+ "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",
403
+ path_str,
404
+ f0_str,
405
+ sr2,
406
+ )
407
+ return (
408
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
409
+ if if_pretrained_generator_exist
410
+ else "",
411
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
412
+ if if_pretrained_discriminator_exist
413
+ else "",
414
+ )
415
+
416
+
417
+ def change_sr2(sr2, if_f0_3, version19):
418
+ path_str = "" if version19 == "v1" else "_v2"
419
+ f0_str = "f0" if if_f0_3 else ""
420
+ return get_pretrained_models(path_str, f0_str, sr2)
421
+
422
+
423
+ def change_version19(sr2, if_f0_3, version19):
424
+ path_str = "" if version19 == "v1" else "_v2"
425
+ if sr2 == "32k" and version19 == "v1":
426
+ sr2 = "40k"
427
+ to_return_sr2 = (
428
+ {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}
429
+ if version19 == "v1"
430
+ else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}
431
+ )
432
+ f0_str = "f0" if if_f0_3 else ""
433
+ return (
434
+ *get_pretrained_models(path_str, f0_str, sr2),
435
+ to_return_sr2,
436
+ )
437
+
438
+
439
+ def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15
440
+ path_str = "" if version19 == "v1" else "_v2"
441
+ return (
442
+ {"visible": if_f0_3, "__type__": "update"},
443
+ *get_pretrained_models(path_str, "f0", sr2),
444
+ )
445
+
446
+
447
+ # but3.click(click_train,[exp_dir1,sr2,if_f0_3,save_epoch10,total_epoch11,batch_size12,if_save_latest13,pretrained_G14,pretrained_D15,gpus16])
448
+ def click_train(
449
+ exp_dir1,
450
+ sr2,
451
+ if_f0_3,
452
+ spk_id5,
453
+ save_epoch10,
454
+ total_epoch11,
455
+ batch_size12,
456
+ if_save_latest13,
457
+ pretrained_G14,
458
+ pretrained_D15,
459
+ gpus16,
460
+ if_cache_gpu17,
461
+ if_save_every_weights18,
462
+ version19,
463
+ ):
464
+ # 生成filelist
465
+ exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
466
+ os.makedirs(exp_dir, exist_ok=True)
467
+ gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)
468
+ feature_dir = (
469
+ "%s/3_feature256" % (exp_dir)
470
+ if version19 == "v1"
471
+ else "%s/3_feature768" % (exp_dir)
472
+ )
473
+ if if_f0_3:
474
+ f0_dir = "%s/2a_f0" % (exp_dir)
475
+ f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)
476
+ names = (
477
+ set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])
478
+ & set([name.split(".")[0] for name in os.listdir(feature_dir)])
479
+ & set([name.split(".")[0] for name in os.listdir(f0_dir)])
480
+ & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])
481
+ )
482
+ else:
483
+ names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(
484
+ [name.split(".")[0] for name in os.listdir(feature_dir)]
485
+ )
486
+ opt = []
487
+ for name in names:
488
+ if if_f0_3:
489
+ opt.append(
490
+ "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"
491
+ % (
492
+ gt_wavs_dir.replace("\\", "\\\\"),
493
+ name,
494
+ feature_dir.replace("\\", "\\\\"),
495
+ name,
496
+ f0_dir.replace("\\", "\\\\"),
497
+ name,
498
+ f0nsf_dir.replace("\\", "\\\\"),
499
+ name,
500
+ spk_id5,
501
+ )
502
+ )
503
+ else:
504
+ opt.append(
505
+ "%s/%s.wav|%s/%s.npy|%s"
506
+ % (
507
+ gt_wavs_dir.replace("\\", "\\\\"),
508
+ name,
509
+ feature_dir.replace("\\", "\\\\"),
510
+ name,
511
+ spk_id5,
512
+ )
513
+ )
514
+ fea_dim = 256 if version19 == "v1" else 768
515
+ if if_f0_3:
516
+ for _ in range(2):
517
+ opt.append(
518
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s/logs/mute/2a_f0/mute.wav.npy|%s/logs/mute/2b-f0nsf/mute.wav.npy|%s"
519
+ % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)
520
+ )
521
+ else:
522
+ for _ in range(2):
523
+ opt.append(
524
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"
525
+ % (now_dir, sr2, now_dir, fea_dim, spk_id5)
526
+ )
527
+ shuffle(opt)
528
+ with open("%s/filelist.txt" % exp_dir, "w") as f:
529
+ f.write("\n".join(opt))
530
+ logger.debug("Write filelist done")
531
+ # 生成config#无需生成config
532
+ # cmd = python_cmd + " train_nsf_sim_cache_sid_load_pretrain.py -e mi-test -sr 40k -f0 1 -bs 4 -g 0 -te 10 -se 5 -pg pretrained/f0G40k.pth -pd pretrained/f0D40k.pth -l 1 -c 0"
533
+ logger.info("Use gpus: %s", str(gpus16))
534
+ if pretrained_G14 == "":
535
+ logger.info("No pretrained Generator")
536
+ if pretrained_D15 == "":
537
+ logger.info("No pretrained Discriminator")
538
+ if version19 == "v1" or sr2 == "40k":
539
+ config_path = "v1/%s.json" % sr2
540
+ else:
541
+ config_path = "v2/%s.json" % sr2
542
+ config_save_path = os.path.join(exp_dir, "config.json")
543
+ if not pathlib.Path(config_save_path).exists():
544
+ with open(config_save_path, "w", encoding="utf-8") as f:
545
+ json.dump(
546
+ config.json_config[config_path],
547
+ f,
548
+ ensure_ascii=False,
549
+ indent=4,
550
+ sort_keys=True,
551
+ )
552
+ f.write("\n")
553
+ if gpus16:
554
+ cmd = (
555
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
556
+ % (
557
+ config.python_cmd,
558
+ exp_dir1,
559
+ sr2,
560
+ 1 if if_f0_3 else 0,
561
+ batch_size12,
562
+ gpus16,
563
+ total_epoch11,
564
+ save_epoch10,
565
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
566
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
567
+ 1 if if_save_latest13 == i18n("是") else 0,
568
+ 1 if if_cache_gpu17 == i18n("是") else 0,
569
+ 1 if if_save_every_weights18 == i18n("是") else 0,
570
+ version19,
571
+ )
572
+ )
573
+ else:
574
+ cmd = (
575
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
576
+ % (
577
+ config.python_cmd,
578
+ exp_dir1,
579
+ sr2,
580
+ 1 if if_f0_3 else 0,
581
+ batch_size12,
582
+ total_epoch11,
583
+ save_epoch10,
584
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
585
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
586
+ 1 if if_save_latest13 == i18n("是") else 0,
587
+ 1 if if_cache_gpu17 == i18n("是") else 0,
588
+ 1 if if_save_every_weights18 == i18n("是") else 0,
589
+ version19,
590
+ )
591
+ )
592
+ logger.info(cmd)
593
+ p = Popen(cmd, shell=True, cwd=now_dir)
594
+ p.wait()
595
+ return "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"
596
+
597
+
598
+ # but4.click(train_index, [exp_dir1], info3)
599
+ def train_index(exp_dir1, version19):
600
+ # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
601
+ exp_dir = "logs/%s" % (exp_dir1)
602
+ os.makedirs(exp_dir, exist_ok=True)
603
+ feature_dir = (
604
+ "%s/3_feature256" % (exp_dir)
605
+ if version19 == "v1"
606
+ else "%s/3_feature768" % (exp_dir)
607
+ )
608
+ if not os.path.exists(feature_dir):
609
+ return "请先进行特征提取!"
610
+ listdir_res = list(os.listdir(feature_dir))
611
+ if len(listdir_res) == 0:
612
+ return "请先进行特征提取!"
613
+ infos = []
614
+ npys = []
615
+ for name in sorted(listdir_res):
616
+ phone = np.load("%s/%s" % (feature_dir, name))
617
+ npys.append(phone)
618
+ big_npy = np.concatenate(npys, 0)
619
+ big_npy_idx = np.arange(big_npy.shape[0])
620
+ np.random.shuffle(big_npy_idx)
621
+ big_npy = big_npy[big_npy_idx]
622
+ if big_npy.shape[0] > 2e5:
623
+ infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
624
+ yield "\n".join(infos)
625
+ try:
626
+ big_npy = (
627
+ MiniBatchKMeans(
628
+ n_clusters=10000,
629
+ verbose=True,
630
+ batch_size=256 * config.n_cpu,
631
+ compute_labels=False,
632
+ init="random",
633
+ )
634
+ .fit(big_npy)
635
+ .cluster_centers_
636
+ )
637
+ except:
638
+ info = traceback.format_exc()
639
+ logger.info(info)
640
+ infos.append(info)
641
+ yield "\n".join(infos)
642
+
643
+ np.save("%s/total_fea.npy" % exp_dir, big_npy)
644
+ n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
645
+ infos.append("%s,%s" % (big_npy.shape, n_ivf))
646
+ yield "\n".join(infos)
647
+ index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
648
+ # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)
649
+ infos.append("training")
650
+ yield "\n".join(infos)
651
+ index_ivf = faiss.extract_index_ivf(index) #
652
+ index_ivf.nprobe = 1
653
+ index.train(big_npy)
654
+ faiss.write_index(
655
+ index,
656
+ "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"
657
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
658
+ )
659
+
660
+ infos.append("adding")
661
+ yield "\n".join(infos)
662
+ batch_size_add = 8192
663
+ for i in range(0, big_npy.shape[0], batch_size_add):
664
+ index.add(big_npy[i : i + batch_size_add])
665
+ faiss.write_index(
666
+ index,
667
+ "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"
668
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
669
+ )
670
+ infos.append(
671
+ "成功构建索引,added_IVF%s_Flat_nprobe_%s_%s_%s.index"
672
+ % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
673
+ )
674
+ # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))
675
+ # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))
676
+ yield "\n".join(infos)
677
+
678
+
679
+ # but5.click(train1key, [exp_dir1, sr2, if_f0_3, trainset_dir4, spk_id5, gpus6, np7, f0method8, save_epoch10, total_epoch11, batch_size12, if_save_latest13, pretrained_G14, pretrained_D15, gpus16, if_cache_gpu17], info3)
680
+ def train1key(
681
+ exp_dir1,
682
+ sr2,
683
+ if_f0_3,
684
+ trainset_dir4,
685
+ spk_id5,
686
+ np7,
687
+ f0method8,
688
+ save_epoch10,
689
+ total_epoch11,
690
+ batch_size12,
691
+ if_save_latest13,
692
+ pretrained_G14,
693
+ pretrained_D15,
694
+ gpus16,
695
+ if_cache_gpu17,
696
+ if_save_every_weights18,
697
+ version19,
698
+ gpus_rmvpe,
699
+ ):
700
+ infos = []
701
+
702
+ def get_info_str(strr):
703
+ infos.append(strr)
704
+ return "\n".join(infos)
705
+
706
+ ####### step1:处理数据
707
+ yield get_info_str(i18n("step1:正在处理数据"))
708
+ [get_info_str(_) for _ in preprocess_dataset(trainset_dir4, exp_dir1, sr2, np7)]
709
+
710
+ ####### step2a:提取音高
711
+ yield get_info_str(i18n("step2:正在提取音高&正在提取特征"))
712
+ [
713
+ get_info_str(_)
714
+ for _ in extract_f0_feature(
715
+ gpus16, np7, f0method8, if_f0_3, exp_dir1, version19, gpus_rmvpe
716
+ )
717
+ ]
718
+
719
+ ####### step3a:训练模型
720
+ yield get_info_str(i18n("step3a:正在训练模型"))
721
+ click_train(
722
+ exp_dir1,
723
+ sr2,
724
+ if_f0_3,
725
+ spk_id5,
726
+ save_epoch10,
727
+ total_epoch11,
728
+ batch_size12,
729
+ if_save_latest13,
730
+ pretrained_G14,
731
+ pretrained_D15,
732
+ gpus16,
733
+ if_cache_gpu17,
734
+ if_save_every_weights18,
735
+ version19,
736
+ )
737
+ yield get_info_str(i18n("训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"))
738
+
739
+ ####### step3b:训练索引
740
+ [get_info_str(_) for _ in train_index(exp_dir1, version19)]
741
+ yield get_info_str(i18n("全流程结束!"))
742
+
743
+
744
+ # ckpt_path2.change(change_info_,[ckpt_path2],[sr__,if_f0__])
745
+ def change_info_(ckpt_path):
746
+ if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):
747
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
748
+ try:
749
+ with open(
750
+ ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"
751
+ ) as f:
752
+ info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])
753
+ sr, f0 = info["sample_rate"], info["if_f0"]
754
+ version = "v2" if ("version" in info and info["version"] == "v2") else "v1"
755
+ return sr, str(f0), version
756
+ except:
757
+ traceback.print_exc()
758
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
759
+
760
+
761
+ F0GPUVisible = config.dml == False
762
+
763
+
764
+ def change_f0_method(f0method8):
765
+ if f0method8 == "rmvpe_gpu":
766
+ visible = F0GPUVisible
767
+ else:
768
+ visible = False
769
+ return {"visible": visible, "__type__": "update"}
770
+
771
+ def find_model():
772
+ if len(names) > 0:
773
+ vc.get_vc(sorted(names)[0],None,None)
774
+ return sorted(names)[0]
775
+ else:
776
+ try:
777
+ gr.Info("Do not forget to choose a model.")
778
+ except:
779
+ pass
780
+ return ''
781
+
782
+ def find_audios(index=False):
783
+ audio_files=[]
784
+ if not os.path.exists('./audios'): os.mkdir("./audios")
785
+ for filename in os.listdir("./audios"):
786
+ if filename.endswith(('.wav','.mp3','.ogg')):
787
+ audio_files.append("./audios/"+filename)
788
+ if index:
789
+ if len(audio_files) > 0: return sorted(audio_files)[0]
790
+ else: return ""
791
+ elif len(audio_files) > 0: return sorted(audio_files)
792
+ else: return []
793
+
794
+ def get_index():
795
+ if find_model() != '':
796
+ chosen_model=sorted(names)[0].split(".")[0]
797
+ logs_path="./logs/"+chosen_model
798
+ if os.path.exists(logs_path):
799
+ for file in os.listdir(logs_path):
800
+ if file.endswith(".index"):
801
+ return os.path.join(logs_path, file)
802
+ return ''
803
+ else:
804
+ return ''
805
+
806
+ def get_indexes():
807
+ indexes_list=[]
808
+ for dirpath, dirnames, filenames in os.walk("./logs/"):
809
+ for filename in filenames:
810
+ if filename.endswith(".index"):
811
+ indexes_list.append(os.path.join(dirpath,filename))
812
+ if len(indexes_list) > 0:
813
+ return indexes_list
814
+ else:
815
+ return ''
816
+
817
+ def save_wav(file):
818
+ try:
819
+ file_path=file.name
820
+ shutil.move(file_path,'./audios')
821
+ return './audios/'+os.path.basename(file_path)
822
+ except AttributeError:
823
+ try:
824
+ new_name = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")+'.wav'
825
+ new_path='./audios/'+new_name
826
+ shutil.move(file,new_path)
827
+ return new_path
828
+ except TypeError:
829
+ return None
830
+
831
+ def download_from_url(url, model):
832
+ if url == '':
833
+ return "URL cannot be left empty."
834
+ if model =='':
835
+ return "You need to name your model. For example: My-Model"
836
+ url = url.strip()
837
+ zip_dirs = ["zips", "unzips"]
838
+ for directory in zip_dirs:
839
+ if os.path.exists(directory):
840
+ shutil.rmtree(directory)
841
+ os.makedirs("zips", exist_ok=True)
842
+ os.makedirs("unzips", exist_ok=True)
843
+ zipfile = model + '.zip'
844
+ zipfile_path = './zips/' + zipfile
845
+ try:
846
+ if "drive.google.com" in url:
847
+ subprocess.run(["gdown", url, "--fuzzy", "-O", zipfile_path])
848
+ elif "mega.nz" in url:
849
+ m = Mega()
850
+ m.download_url(url, './zips')
851
+ else:
852
+ subprocess.run(["wget", url, "-O", zipfile_path])
853
+ for filename in os.listdir("./zips"):
854
+ if filename.endswith(".zip"):
855
+ zipfile_path = os.path.join("./zips/",filename)
856
+ shutil.unpack_archive(zipfile_path, "./unzips", 'zip')
857
+ else:
858
+ return "No zipfile found."
859
+ for root, dirs, files in os.walk('./unzips'):
860
+ for file in files:
861
+ file_path = os.path.join(root, file)
862
+ if file.endswith(".index"):
863
+ os.mkdir(f'./logs/{model}')
864
+ shutil.copy2(file_path,f'./logs/{model}')
865
+ elif "G_" not in file and "D_" not in file and file.endswith(".pth"):
866
+ shutil.copy(file_path,f'./assets/weights/{model}.pth')
867
+ shutil.rmtree("zips")
868
+ shutil.rmtree("unzips")
869
+ return "Success."
870
+ except:
871
+ return "There's been an error."
872
+
873
+ def upload_to_dataset(files, dir):
874
+ if dir == '':
875
+ dir = './dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
876
+ if not os.path.exists(dir):
877
+ os.makedirs(dir)
878
+ for file in files:
879
+ path=file.name
880
+ shutil.copy2(path,dir)
881
+ try:
882
+ gr.Info(i18n("处理数据"))
883
+ except:
884
+ pass
885
+ return i18n("处理数据"), {"value":dir,"__type__":"update"}
886
+
887
+ with gr.Blocks(title="EasyGUI v2.9",theme=gr.themes.Base()) as app:
888
+ gr.HTML("<h1> EasyGUI v2.9 </h1>")
889
+ with gr.Tabs():
890
+ with gr.TabItem(i18n("模型推理")):
891
+ with gr.Row():
892
+ sid0 = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names), value=find_model())
893
+ refresh_button = gr.Button(i18n("刷新音色列表和索引路径"), variant="primary")
894
+ #clean_button = gr.Button(i18n("卸载音色省显存"), variant="primary")
895
+ spk_item = gr.Slider(
896
+ minimum=0,
897
+ maximum=2333,
898
+ step=1,
899
+ label=i18n("请选择说话人id"),
900
+ value=0,
901
+ visible=False,
902
+ interactive=True,
903
+ )
904
+ #clean_button.click(
905
+ # fn=clean, inputs=[], outputs=[sid0], api_name="infer_clean"
906
+ #)
907
+ vc_transform0 = gr.Number(
908
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
909
+ )
910
+ but0 = gr.Button(i18n("转换"), variant="primary")
911
+ with gr.Row():
912
+ with gr.Column():
913
+ with gr.Row():
914
+ dropbox = gr.File(label="Drop your audio here & hit the Reload button.")
915
+ with gr.Row():
916
+ record_button=gr.Audio(source="microphone", label="OR Record audio.", type="filepath")
917
+ with gr.Row():
918
+ input_audio0 = gr.Dropdown(
919
+ label=i18n("输入待处理音频文件路径(默认是正确格式示例)"),
920
+ value=find_audios(True),
921
+ choices=find_audios()
922
+ )
923
+ record_button.change(fn=save_wav, inputs=[record_button], outputs=[input_audio0])
924
+ dropbox.upload(fn=save_wav, inputs=[dropbox], outputs=[input_audio0])
925
+ with gr.Column():
926
+ with gr.Accordion(label=i18n("自动检测index路径,下拉式选择(dropdown)"), open=False):
927
+ file_index2 = gr.Dropdown(
928
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
929
+ choices=get_indexes(),
930
+ interactive=True,
931
+ value=get_index()
932
+ )
933
+ index_rate1 = gr.Slider(
934
+ minimum=0,
935
+ maximum=1,
936
+ label=i18n("检索特征占比"),
937
+ value=0.66,
938
+ interactive=True,
939
+ )
940
+ vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
941
+ with gr.Accordion(label=i18n("常规设置"), open=False):
942
+ f0method0 = gr.Radio(
943
+ label=i18n(
944
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
945
+ ),
946
+ choices=["pm", "harvest", "crepe", "rmvpe"]
947
+ if config.dml == False
948
+ else ["pm", "harvest", "rmvpe"],
949
+ value="rmvpe",
950
+ interactive=True,
951
+ )
952
+ filter_radius0 = gr.Slider(
953
+ minimum=0,
954
+ maximum=7,
955
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
956
+ value=3,
957
+ step=1,
958
+ interactive=True,
959
+ )
960
+ resample_sr0 = gr.Slider(
961
+ minimum=0,
962
+ maximum=48000,
963
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
964
+ value=0,
965
+ step=1,
966
+ interactive=True,
967
+ )
968
+ rms_mix_rate0 = gr.Slider(
969
+ minimum=0,
970
+ maximum=1,
971
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
972
+ value=0.21,
973
+ interactive=True,
974
+ )
975
+ protect0 = gr.Slider(
976
+ minimum=0,
977
+ maximum=0.5,
978
+ label=i18n(
979
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
980
+ ),
981
+ value=0.33,
982
+ step=0.01,
983
+ interactive=True,
984
+ )
985
+ file_index1 = gr.Textbox(
986
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
987
+ value="",
988
+ interactive=True,
989
+ visible=False
990
+ )
991
+ refresh_button.click(
992
+ fn=change_choices,
993
+ inputs=[],
994
+ outputs=[sid0, file_index2, input_audio0],
995
+ api_name="infer_refresh",
996
+ )
997
+ # file_big_npy1 = gr.Textbox(
998
+ # label=i18n("特征文件路径"),
999
+ # value="E:\\codes\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1000
+ # interactive=True,
1001
+ # )
1002
+ with gr.Row():
1003
+ f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"), visible=False)
1004
+ with gr.Row():
1005
+ vc_output1 = gr.Textbox(label=i18n("输出信息"))
1006
+ but0.click(
1007
+ vc.vc_single,
1008
+ [
1009
+ spk_item,
1010
+ input_audio0,
1011
+ vc_transform0,
1012
+ f0_file,
1013
+ f0method0,
1014
+ file_index1,
1015
+ file_index2,
1016
+ # file_big_npy1,
1017
+ index_rate1,
1018
+ filter_radius0,
1019
+ resample_sr0,
1020
+ rms_mix_rate0,
1021
+ protect0,
1022
+ ],
1023
+ [vc_output1, vc_output2],
1024
+ api_name="infer_convert",
1025
+ )
1026
+ with gr.Row():
1027
+ with gr.Accordion(open=False, label=i18n("批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ")):
1028
+ with gr.Column():
1029
+ vc_transform1 = gr.Number(
1030
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
1031
+ )
1032
+ opt_input = gr.Textbox(label=i18n("指定输出文件夹"), value="opt")
1033
+ f0method1 = gr.Radio(
1034
+ label=i18n(
1035
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
1036
+ ),
1037
+ choices=["pm", "harvest", "crepe", "rmvpe"]
1038
+ if config.dml == False
1039
+ else ["pm", "harvest", "rmvpe"],
1040
+ value="pm",
1041
+ interactive=True,
1042
+ )
1043
+ filter_radius1 = gr.Slider(
1044
+ minimum=0,
1045
+ maximum=7,
1046
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
1047
+ value=3,
1048
+ step=1,
1049
+ interactive=True,
1050
+ )
1051
+ with gr.Column():
1052
+ file_index3 = gr.Textbox(
1053
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
1054
+ value="",
1055
+ interactive=True,
1056
+ visible=False
1057
+ )
1058
+ file_index4 = gr.Dropdown(
1059
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
1060
+ choices=sorted(index_paths),
1061
+ interactive=True,
1062
+ )
1063
+ refresh_button.click(
1064
+ fn=lambda: change_choices()[1],
1065
+ inputs=[],
1066
+ outputs=file_index4,
1067
+ api_name="infer_refresh_batch",
1068
+ )
1069
+ # file_big_npy2 = gr.Textbox(
1070
+ # label=i18n("特征文件路径"),
1071
+ # value="E:\\codes\\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1072
+ # interactive=True,
1073
+ # )
1074
+ index_rate2 = gr.Slider(
1075
+ minimum=0,
1076
+ maximum=1,
1077
+ label=i18n("检索特征占比"),
1078
+ value=1,
1079
+ interactive=True,
1080
+ )
1081
+ with gr.Column():
1082
+ resample_sr1 = gr.Slider(
1083
+ minimum=0,
1084
+ maximum=48000,
1085
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
1086
+ value=0,
1087
+ step=1,
1088
+ interactive=True,
1089
+ )
1090
+ rms_mix_rate1 = gr.Slider(
1091
+ minimum=0,
1092
+ maximum=1,
1093
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
1094
+ value=1,
1095
+ interactive=True,
1096
+ )
1097
+ protect1 = gr.Slider(
1098
+ minimum=0,
1099
+ maximum=0.5,
1100
+ label=i18n(
1101
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
1102
+ ),
1103
+ value=0.33,
1104
+ step=0.01,
1105
+ interactive=True,
1106
+ )
1107
+ with gr.Column():
1108
+ dir_input = gr.Textbox(
1109
+ label=i18n("输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)"),
1110
+ value="E:\codes\py39\\test-20230416b\\todo-songs",
1111
+ )
1112
+ inputs = gr.File(
1113
+ file_count="multiple", label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹")
1114
+ )
1115
+ with gr.Row():
1116
+ format1 = gr.Radio(
1117
+ label=i18n("导出文件格式"),
1118
+ choices=["wav", "flac", "mp3", "m4a"],
1119
+ value="flac",
1120
+ interactive=True,
1121
+ )
1122
+ but1 = gr.Button(i18n("转换"), variant="primary")
1123
+ vc_output3 = gr.Textbox(label=i18n("输出信息"))
1124
+ but1.click(
1125
+ vc.vc_multi,
1126
+ [
1127
+ spk_item,
1128
+ dir_input,
1129
+ opt_input,
1130
+ inputs,
1131
+ vc_transform1,
1132
+ f0method1,
1133
+ file_index3,
1134
+ file_index4,
1135
+ # file_big_npy2,
1136
+ index_rate2,
1137
+ filter_radius1,
1138
+ resample_sr1,
1139
+ rms_mix_rate1,
1140
+ protect1,
1141
+ format1,
1142
+ ],
1143
+ [vc_output3],
1144
+ api_name="infer_convert_batch",
1145
+ )
1146
+ sid0.change(
1147
+ fn=vc.get_vc,
1148
+ inputs=[sid0, protect0, protect1],
1149
+ outputs=[spk_item, protect0, protect1, file_index2, file_index4],
1150
+ )
1151
+ with gr.TabItem("Download Model"):
1152
+ with gr.Row():
1153
+ url=gr.Textbox(label="Enter the URL to the Model:")
1154
+ with gr.Row():
1155
+ model = gr.Textbox(label="Name your model:")
1156
+ download_button=gr.Button("Download")
1157
+ with gr.Row():
1158
+ status_bar=gr.Textbox(label="")
1159
+ download_button.click(fn=download_from_url, inputs=[url, model], outputs=[status_bar])
1160
+ with gr.Row():
1161
+ gr.Markdown(
1162
+ """
1163
+ ❤️ If you like the EasyGUI, help me keep it.❤️
1164
+ https://paypal.me/lesantillan
1165
+ """
1166
+ )
1167
+ with gr.TabItem(i18n("训练")):
1168
+ with gr.Row():
1169
+ with gr.Column():
1170
+ exp_dir1 = gr.Textbox(label=i18n("输入实验名"), value="My-Voice")
1171
+ np7 = gr.Slider(
1172
+ minimum=0,
1173
+ maximum=config.n_cpu,
1174
+ step=1,
1175
+ label=i18n("提取音高和处理数据使用的CPU进程数"),
1176
+ value=int(np.ceil(config.n_cpu / 1.5)),
1177
+ interactive=True,
1178
+ )
1179
+ sr2 = gr.Radio(
1180
+ label=i18n("目标采样率"),
1181
+ choices=["40k", "48k"],
1182
+ value="40k",
1183
+ interactive=True,
1184
+ visible=False
1185
+ )
1186
+ if_f0_3 = gr.Radio(
1187
+ label=i18n("模型是否带音高指导(唱歌一定要, 语音可以不要)"),
1188
+ choices=[True, False],
1189
+ value=True,
1190
+ interactive=True,
1191
+ visible=False
1192
+ )
1193
+ version19 = gr.Radio(
1194
+ label=i18n("版本"),
1195
+ choices=["v1", "v2"],
1196
+ value="v2",
1197
+ interactive=True,
1198
+ visible=False,
1199
+ )
1200
+ trainset_dir4 = gr.Textbox(
1201
+ label=i18n("输入训练文件夹路径"), value='./dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
1202
+ )
1203
+ easy_uploader = gr.Files(label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹"),file_types=['audio'])
1204
+ but1 = gr.Button(label=i18n("处理数据"), variant="primary")
1205
+ info1 = gr.Textbox(label=i18n("输出信息"), value="")
1206
+ easy_uploader.upload(fn=upload_to_dataset, inputs=[easy_uploader, trainset_dir4], outputs=[info1, trainset_dir4])
1207
+ gpus6 = gr.Textbox(
1208
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1209
+ value=gpus,
1210
+ interactive=True,
1211
+ visible=F0GPUVisible,
1212
+ )
1213
+ gpu_info9 = gr.Textbox(
1214
+ label=i18n("显卡信息"), value=gpu_info, visible=F0GPUVisible
1215
+ )
1216
+ spk_id5 = gr.Slider(
1217
+ minimum=0,
1218
+ maximum=4,
1219
+ step=1,
1220
+ label=i18n("请指定说话人id"),
1221
+ value=0,
1222
+ interactive=True,
1223
+ visible=False
1224
+ )
1225
+ but1.click(
1226
+ preprocess_dataset,
1227
+ [trainset_dir4, exp_dir1, sr2, np7],
1228
+ [info1],
1229
+ api_name="train_preprocess",
1230
+ )
1231
+ with gr.Column():
1232
+ f0method8 = gr.Radio(
1233
+ label=i18n(
1234
+ "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢,rmvpe效果最好且微吃CPU/GPU"
1235
+ ),
1236
+ choices=["pm", "harvest", "dio", "rmvpe", "rmvpe_gpu"],
1237
+ value="rmvpe_gpu",
1238
+ interactive=True,
1239
+ )
1240
+ gpus_rmvpe = gr.Textbox(
1241
+ label=i18n(
1242
+ "rmvpe卡号配置:以-分隔输入使用的不同进程卡号,例如0-0-1使用在卡0上跑2个进程并在卡1上跑1个进程"
1243
+ ),
1244
+ value="%s-%s" % (gpus, gpus),
1245
+ interactive=True,
1246
+ visible=F0GPUVisible,
1247
+ )
1248
+ but2 = gr.Button(i18n("特征提取"), variant="primary")
1249
+ info2 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1250
+ f0method8.change(
1251
+ fn=change_f0_method,
1252
+ inputs=[f0method8],
1253
+ outputs=[gpus_rmvpe],
1254
+ )
1255
+ but2.click(
1256
+ extract_f0_feature,
1257
+ [
1258
+ gpus6,
1259
+ np7,
1260
+ f0method8,
1261
+ if_f0_3,
1262
+ exp_dir1,
1263
+ version19,
1264
+ gpus_rmvpe,
1265
+ ],
1266
+ [info2],
1267
+ api_name="train_extract_f0_feature",
1268
+ )
1269
+ with gr.Column():
1270
+ total_epoch11 = gr.Slider(
1271
+ minimum=2,
1272
+ maximum=1000,
1273
+ step=1,
1274
+ label=i18n("总训练轮数total_epoch"),
1275
+ value=150,
1276
+ interactive=True,
1277
+ )
1278
+ gpus16 = gr.Textbox(
1279
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1280
+ value="0",
1281
+ interactive=True,
1282
+ visible=True
1283
+ )
1284
+ but3 = gr.Button(i18n("训练模型"), variant="primary")
1285
+ but4 = gr.Button(i18n("训练特征索引"), variant="primary")
1286
+ info3 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=10)
1287
+ with gr.Accordion(label=i18n("常规设置"), open=False):
1288
+ save_epoch10 = gr.Slider(
1289
+ minimum=1,
1290
+ maximum=50,
1291
+ step=1,
1292
+ label=i18n("保存频率save_every_epoch"),
1293
+ value=25,
1294
+ interactive=True,
1295
+ )
1296
+ batch_size12 = gr.Slider(
1297
+ minimum=1,
1298
+ maximum=40,
1299
+ step=1,
1300
+ label=i18n("每张显卡的batch_size"),
1301
+ value=default_batch_size,
1302
+ interactive=True,
1303
+ )
1304
+ if_save_latest13 = gr.Radio(
1305
+ label=i18n("是否仅保存最新的ckpt文件以节省硬盘空间"),
1306
+ choices=[i18n("是"), i18n("否")],
1307
+ value=i18n("是"),
1308
+ interactive=True,
1309
+ )
1310
+ if_cache_gpu17 = gr.Radio(
1311
+ label=i18n(
1312
+ "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速"
1313
+ ),
1314
+ choices=[i18n("是"), i18n("否")],
1315
+ value=i18n("否"),
1316
+ interactive=True,
1317
+ )
1318
+ if_save_every_weights18 = gr.Radio(
1319
+ label=i18n("是否在每次保存时间点将最终小模型保存至weights文件夹"),
1320
+ choices=[i18n("是"), i18n("否")],
1321
+ value=i18n("是"),
1322
+ interactive=True,
1323
+ )
1324
+ with gr.Row():
1325
+ pretrained_G14 = gr.Textbox(
1326
+ label=i18n("加载预训练底模G路径"),
1327
+ value="assets/pretrained_v2/f0G40k.pth",
1328
+ interactive=True,
1329
+ visible=False
1330
+ )
1331
+ pretrained_D15 = gr.Textbox(
1332
+ label=i18n("加载预训练底模D路径"),
1333
+ value="assets/pretrained_v2/f0D40k.pth",
1334
+ interactive=True,
1335
+ visible=False
1336
+ )
1337
+ sr2.change(
1338
+ change_sr2,
1339
+ [sr2, if_f0_3, version19],
1340
+ [pretrained_G14, pretrained_D15],
1341
+ )
1342
+ version19.change(
1343
+ change_version19,
1344
+ [sr2, if_f0_3, version19],
1345
+ [pretrained_G14, pretrained_D15, sr2],
1346
+ )
1347
+ if_f0_3.change(
1348
+ change_f0,
1349
+ [if_f0_3, sr2, version19],
1350
+ [f0method8, pretrained_G14, pretrained_D15],
1351
+ )
1352
+ with gr.Row():
1353
+ but5 = gr.Button(i18n("一键训练"), variant="primary", visible=False)
1354
+ but3.click(
1355
+ click_train,
1356
+ [
1357
+ exp_dir1,
1358
+ sr2,
1359
+ if_f0_3,
1360
+ spk_id5,
1361
+ save_epoch10,
1362
+ total_epoch11,
1363
+ batch_size12,
1364
+ if_save_latest13,
1365
+ pretrained_G14,
1366
+ pretrained_D15,
1367
+ gpus16,
1368
+ if_cache_gpu17,
1369
+ if_save_every_weights18,
1370
+ version19,
1371
+ ],
1372
+ info3,
1373
+ api_name="train_start",
1374
+ )
1375
+ but4.click(train_index, [exp_dir1, version19], info3)
1376
+ but5.click(
1377
+ train1key,
1378
+ [
1379
+ exp_dir1,
1380
+ sr2,
1381
+ if_f0_3,
1382
+ trainset_dir4,
1383
+ spk_id5,
1384
+ np7,
1385
+ f0method8,
1386
+ save_epoch10,
1387
+ total_epoch11,
1388
+ batch_size12,
1389
+ if_save_latest13,
1390
+ pretrained_G14,
1391
+ pretrained_D15,
1392
+ gpus16,
1393
+ if_cache_gpu17,
1394
+ if_save_every_weights18,
1395
+ version19,
1396
+ gpus_rmvpe,
1397
+ ],
1398
+ info3,
1399
+ api_name="train_start_all",
1400
+ )
1401
+
1402
+ if config.iscolab:
1403
+ app.queue(concurrency_count=511, max_size=1022).launch(share=True)
1404
+ else:
1405
+ app.queue(concurrency_count=511, max_size=1022).launch(
1406
+ server_name="0.0.0.0",
1407
+ inbrowser=not config.noautoopen,
1408
+ server_port=config.listen_port,
1409
+ quiet=True,
1410
+ )
LICENSE ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 liujing04
4
+ Copyright (c) 2023 源文雨
5
+ Copyright (c) 2023 Ftps
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
MIT协议暨相关引用库协议 ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 本软件及其相关代码以MIT协议开源,作者不对软件具备任何控制力,使用软件者、传播软件导出的声音者自负全责。
2
+ 如不认可该条款,则不能使用或引用软件包内任何代码和文件。
3
+
4
+ 特此授予任何获得本软件和相关文档文件(以下简称“软件”)副本的人免费使用、复制、修改、合并、出版、分发、再授权和/或销售本软件的权利,以及授予本软件所提供的人使用本软件的权利,但须符合以下条件:
5
+ 上述版权声明和本许可声明应包含在软件的所有副本或实质部分中。
6
+ 软件是“按原样”提供的,没有任何明示或暗示的保证,包括但不限于适销性、适用于特定目的和不侵权的保证。在任何情况下,作者或版权持有人均不承担因软件或软件的使用或其他交易而产生、产生或与之相关的任何索赔、损害赔偿或其他责任,无论是在合同诉讼、侵权诉讼还是其他诉讼中。
7
+
8
+
9
+ The LICENCEs for related libraries are as follows.
10
+ 相关引用库协议如下:
11
+
12
+ ContentVec
13
+ https://github.com/auspicious3000/contentvec/blob/main/LICENSE
14
+ MIT License
15
+
16
+ VITS
17
+ https://github.com/jaywalnut310/vits/blob/main/LICENSE
18
+ MIT License
19
+
20
+ HIFIGAN
21
+ https://github.com/jik876/hifi-gan/blob/master/LICENSE
22
+ MIT License
23
+
24
+ gradio
25
+ https://github.com/gradio-app/gradio/blob/main/LICENSE
26
+ Apache License 2.0
27
+
28
+ ffmpeg
29
+ https://github.com/FFmpeg/FFmpeg/blob/master/COPYING.LGPLv3
30
+ https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2021-02-28-12-32/ffmpeg-n4.3.2-160-gfbb9368226-win64-lgpl-4.3.zip
31
+ LPGLv3 License
32
+ MIT License
33
+
34
+ ultimatevocalremovergui
35
+ https://github.com/Anjok07/ultimatevocalremovergui/blob/master/LICENSE
36
+ https://github.com/yang123qwe/vocal_separation_by_uvr5
37
+ MIT License
38
+
39
+ audio-slicer
40
+ https://github.com/openvpi/audio-slicer/blob/main/LICENSE
41
+ MIT License
42
+
43
+ PySimpleGUI
44
+ https://github.com/PySimpleGUI/PySimpleGUI/blob/master/license.txt
45
+ LPGLv3 License
README.md CHANGED
@@ -1,13 +1,32 @@
1
- ---
2
- title: NioRCV
3
- emoji:
4
- colorFrom: purple
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 3.44.4
8
- app_file: app.py
9
- pinned: false
10
- license: apache-2.0
11
- ---
12
-
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw)
2
+
3
+ # Local Installation
4
+ If you already have RVC installed, then just download GUI.py and drop it in the root folder!
5
+ If you need to install RVC, I recommend you check the [original repo](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
6
+ Or read this at least.
7
+
8
+ I recommend you use a virtual environment
9
+
10
+ ```bash
11
+ python -m venv RVC
12
+ cd RVC
13
+ git clone https://github.com/777gt/-EVC-
14
+ Scripts/activate.bat
15
+ pip install torch torchvision torchaudio
16
+ pip install -r "-EVC-/requirements.txt"
17
+ ```
18
+ If you're on Windows, like me, and don't have an NVIDA graphics card, install the requirements from a different .txt:
19
+ ```bash
20
+ pip install -r "-EVC-/requirements-dml.txt"
21
+ ```
22
+ Also, do not forget to download the necessary models. EasyGUI uses RVC 2 40k models.
23
+
24
+ ```bash
25
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -O ./assets/rmvpe/rmvpe.pt
26
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.onnx -O ./assets/rmvpe/rmvpe.onnx
27
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -O ./assets/hubert/hubert_base.pt
28
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -O ./assets/pretrained_v2/D40k.pth
29
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -O ./assets/pretrained_v2/G40k.pth
30
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -O ./assets/pretrained_v2/f0D40k.pth
31
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -O ./assets/pretrained_v2/f0G40k.pth
32
+ ```
Retrieval_based_Voice_Conversion_WebUI.ipynb ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "attachments": {},
5
+ "cell_type": "markdown",
6
+ "metadata": {},
7
+ "source": [
8
+ "# [Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) Training notebook"
9
+ ]
10
+ },
11
+ {
12
+ "attachments": {},
13
+ "cell_type": "markdown",
14
+ "metadata": {
15
+ "id": "ZFFCx5J80SGa"
16
+ },
17
+ "source": [
18
+ "[![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.ipynb)"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "metadata": {
25
+ "id": "GmFP6bN9dvOq"
26
+ },
27
+ "outputs": [],
28
+ "source": [
29
+ "# @title 查看显卡\n",
30
+ "!nvidia-smi"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": null,
36
+ "metadata": {
37
+ "id": "jwu07JgqoFON"
38
+ },
39
+ "outputs": [],
40
+ "source": [
41
+ "# @title 挂载谷歌云盘\n",
42
+ "\n",
43
+ "from google.colab import drive\n",
44
+ "\n",
45
+ "drive.mount(\"/content/drive\")"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": null,
51
+ "metadata": {
52
+ "id": "wjddIFr1oS3W"
53
+ },
54
+ "outputs": [],
55
+ "source": [
56
+ "# @title 安装依赖\n",
57
+ "!apt-get -y install build-essential python3-dev ffmpeg\n",
58
+ "!pip3 install --upgrade setuptools wheel\n",
59
+ "!pip3 install --upgrade pip\n",
60
+ "!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"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": null,
66
+ "metadata": {
67
+ "id": "ge_97mfpgqTm"
68
+ },
69
+ "outputs": [],
70
+ "source": [
71
+ "# @title 克隆仓库\n",
72
+ "\n",
73
+ "!git clone --depth=1 -b stable https://github.com/fumiama/Retrieval-based-Voice-Conversion-WebUI\n",
74
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
75
+ "!mkdir -p pretrained uvr5_weights"
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "execution_count": null,
81
+ "metadata": {
82
+ "id": "BLDEZADkvlw1"
83
+ },
84
+ "outputs": [],
85
+ "source": [
86
+ "# @title 更新仓库(一般无需执行)\n",
87
+ "!git pull"
88
+ ]
89
+ },
90
+ {
91
+ "cell_type": "code",
92
+ "execution_count": null,
93
+ "metadata": {
94
+ "id": "pqE0PrnuRqI2"
95
+ },
96
+ "outputs": [],
97
+ "source": [
98
+ "# @title 安装aria2\n",
99
+ "!apt -y install -qq aria2"
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "code",
104
+ "execution_count": null,
105
+ "metadata": {
106
+ "id": "UG3XpUwEomUz"
107
+ },
108
+ "outputs": [],
109
+ "source": [
110
+ "# @title 下载底模\n",
111
+ "!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",
112
+ "!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",
113
+ "!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",
114
+ "!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",
115
+ "!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",
116
+ "!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",
117
+ "!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",
118
+ "!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",
119
+ "!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",
120
+ "!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",
121
+ "!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",
122
+ "!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"
123
+ ]
124
+ },
125
+ {
126
+ "cell_type": "code",
127
+ "execution_count": null,
128
+ "metadata": {
129
+ "id": "HugjmZqZRuiF"
130
+ },
131
+ "outputs": [],
132
+ "source": [
133
+ "# @title 下载人声分离模型\n",
134
+ "!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",
135
+ "!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"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "code",
140
+ "execution_count": null,
141
+ "metadata": {
142
+ "id": "2RCaT9FTR0ej"
143
+ },
144
+ "outputs": [],
145
+ "source": [
146
+ "# @title 下载hubert_base\n",
147
+ "!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"
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "execution_count": null,
153
+ "metadata": {},
154
+ "outputs": [],
155
+ "source": [
156
+ "# @title #下载rmvpe模型\n",
157
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o rmvpe.pt"
158
+ ]
159
+ },
160
+ {
161
+ "cell_type": "code",
162
+ "execution_count": null,
163
+ "metadata": {
164
+ "id": "Mwk7Q0Loqzjx"
165
+ },
166
+ "outputs": [],
167
+ "source": [
168
+ "# @title 从谷歌云盘加载打包好的数据集到/content/dataset\n",
169
+ "\n",
170
+ "# @markdown 数据集位置\n",
171
+ "DATASET = (\n",
172
+ " \"/content/drive/MyDrive/dataset/lulu20230327_32k.zip\" # @param {type:\"string\"}\n",
173
+ ")\n",
174
+ "\n",
175
+ "!mkdir -p /content/dataset\n",
176
+ "!unzip -d /content/dataset -B {DATASET}"
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": null,
182
+ "metadata": {
183
+ "id": "PDlFxWHWEynD"
184
+ },
185
+ "outputs": [],
186
+ "source": [
187
+ "# @title 重命名数据集中的重名文件\n",
188
+ "!ls -a /content/dataset/\n",
189
+ "!rename 's/(\\w+)\\.(\\w+)~(\\d*)/$1_$3.$2/' /content/dataset/*.*~*"
190
+ ]
191
+ },
192
+ {
193
+ "cell_type": "code",
194
+ "execution_count": null,
195
+ "metadata": {
196
+ "id": "7vh6vphDwO0b"
197
+ },
198
+ "outputs": [],
199
+ "source": [
200
+ "# @title 启动web\n",
201
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
202
+ "# %load_ext tensorboard\n",
203
+ "# %tensorboard --logdir /content/Retrieval-based-Voice-Conversion-WebUI/logs\n",
204
+ "!python3 infer-web.py --colab --pycmd python3"
205
+ ]
206
+ },
207
+ {
208
+ "cell_type": "code",
209
+ "execution_count": null,
210
+ "metadata": {
211
+ "id": "FgJuNeAwx5Y_"
212
+ },
213
+ "outputs": [],
214
+ "source": [
215
+ "# @title 手动将训练后的模型文件备份到谷歌云盘\n",
216
+ "# @markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
217
+ "\n",
218
+ "# @markdown 模型名\n",
219
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
220
+ "# @markdown 模型epoch\n",
221
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
222
+ "\n",
223
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth\n",
224
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth\n",
225
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/added_*.index /content/drive/MyDrive/\n",
226
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/total_*.npy /content/drive/MyDrive/\n",
227
+ "\n",
228
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth"
229
+ ]
230
+ },
231
+ {
232
+ "cell_type": "code",
233
+ "execution_count": null,
234
+ "metadata": {
235
+ "id": "OVQoLQJXS7WX"
236
+ },
237
+ "outputs": [],
238
+ "source": [
239
+ "# @title 从谷歌云盘恢复pth\n",
240
+ "# @markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
241
+ "\n",
242
+ "# @markdown 模型名\n",
243
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
244
+ "# @markdown 模型epoch\n",
245
+ "MODELEPOCH = 7500 # @param {type:\"integer\"}\n",
246
+ "\n",
247
+ "!mkdir -p /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
248
+ "\n",
249
+ "!cp /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
250
+ "!cp /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
251
+ "!cp /content/drive/MyDrive/*.index /content/\n",
252
+ "!cp /content/drive/MyDrive/*.npy /content/\n",
253
+ "!cp /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth"
254
+ ]
255
+ },
256
+ {
257
+ "cell_type": "code",
258
+ "execution_count": null,
259
+ "metadata": {
260
+ "id": "ZKAyuKb9J6dz"
261
+ },
262
+ "outputs": [],
263
+ "source": [
264
+ "# @title 手动预处理(不推荐)\n",
265
+ "# @markdown 模型名\n",
266
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
267
+ "# @markdown 采样率\n",
268
+ "BITRATE = 48000 # @param {type:\"integer\"}\n",
269
+ "# @markdown 使用的进程数\n",
270
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
271
+ "\n",
272
+ "!python3 trainset_preprocess_pipeline_print.py /content/dataset {BITRATE} {THREADCOUNT} logs/{MODELNAME} True"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "metadata": {
279
+ "id": "CrxJqzAUKmPJ"
280
+ },
281
+ "outputs": [],
282
+ "source": [
283
+ "# @title 手动提取特征(不推荐)\n",
284
+ "# @markdown 模型名\n",
285
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
286
+ "# @markdown 使用的进程数\n",
287
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
288
+ "# @markdown 音高提取算法\n",
289
+ "ALGO = \"harvest\" # @param {type:\"string\"}\n",
290
+ "\n",
291
+ "!python3 extract_f0_print.py logs/{MODELNAME} {THREADCOUNT} {ALGO}\n",
292
+ "\n",
293
+ "!python3 extract_feature_print.py cpu 1 0 0 logs/{MODELNAME}"
294
+ ]
295
+ },
296
+ {
297
+ "cell_type": "code",
298
+ "execution_count": null,
299
+ "metadata": {
300
+ "id": "IMLPLKOaKj58"
301
+ },
302
+ "outputs": [],
303
+ "source": [
304
+ "# @title 手动训练(不推荐)\n",
305
+ "# @markdown 模型名\n",
306
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
307
+ "# @markdown 使用的GPU\n",
308
+ "USEGPU = \"0\" # @param {type:\"string\"}\n",
309
+ "# @markdown 批大小\n",
310
+ "BATCHSIZE = 32 # @param {type:\"integer\"}\n",
311
+ "# @markdown 停止的epoch\n",
312
+ "MODELEPOCH = 3200 # @param {type:\"integer\"}\n",
313
+ "# @markdown 保存epoch间隔\n",
314
+ "EPOCHSAVE = 100 # @param {type:\"integer\"}\n",
315
+ "# @markdown 采样率\n",
316
+ "MODELSAMPLE = \"48k\" # @param {type:\"string\"}\n",
317
+ "# @markdown 是否缓存训练集\n",
318
+ "CACHEDATA = 1 # @param {type:\"integer\"}\n",
319
+ "# @markdown 是否仅保存最新的ckpt文件\n",
320
+ "ONLYLATEST = 0 # @param {type:\"integer\"}\n",
321
+ "\n",
322
+ "!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}"
323
+ ]
324
+ },
325
+ {
326
+ "cell_type": "code",
327
+ "execution_count": null,
328
+ "metadata": {
329
+ "id": "haYA81hySuDl"
330
+ },
331
+ "outputs": [],
332
+ "source": [
333
+ "# @title 删除其它pth,只留选中的(慎点,仔细看代码)\n",
334
+ "# @markdown 模型名\n",
335
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
336
+ "# @markdown 选中模型epoch\n",
337
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
338
+ "\n",
339
+ "!echo \"备份选中的模型。。。\"\n",
340
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
341
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
342
+ "\n",
343
+ "!echo \"正在删除。。。\"\n",
344
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
345
+ "!rm /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*.pth\n",
346
+ "\n",
347
+ "!echo \"恢复选中的模型。。。\"\n",
348
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
349
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
350
+ "\n",
351
+ "!echo \"删除完成\"\n",
352
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
353
+ ]
354
+ },
355
+ {
356
+ "cell_type": "code",
357
+ "execution_count": null,
358
+ "metadata": {
359
+ "id": "QhSiPTVPoIRh"
360
+ },
361
+ "outputs": [],
362
+ "source": [
363
+ "# @title 清除项目下所有文件,只留选中的模型(慎点,仔细看代码)\n",
364
+ "# @markdown 模型名\n",
365
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
366
+ "# @markdown 选中模型epoch\n",
367
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
368
+ "\n",
369
+ "!echo \"备份选中的模型。。。\"\n",
370
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
371
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
372
+ "\n",
373
+ "!echo \"正��删除。。。\"\n",
374
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
375
+ "!rm -rf /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*\n",
376
+ "\n",
377
+ "!echo \"恢复选中的模型。。。\"\n",
378
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
379
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
380
+ "\n",
381
+ "!echo \"删除完成\"\n",
382
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
383
+ ]
384
+ }
385
+ ],
386
+ "metadata": {
387
+ "accelerator": "GPU",
388
+ "colab": {
389
+ "private_outputs": true,
390
+ "provenance": []
391
+ },
392
+ "gpuClass": "standard",
393
+ "kernelspec": {
394
+ "display_name": "Python 3",
395
+ "name": "python3"
396
+ },
397
+ "language_info": {
398
+ "name": "python"
399
+ }
400
+ },
401
+ "nbformat": 4,
402
+ "nbformat_minor": 0
403
+ }
Retrieval_based_Voice_Conversion_WebUI_v2.ipynb ADDED
@@ -0,0 +1,422 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "attachments": {},
5
+ "cell_type": "markdown",
6
+ "metadata": {},
7
+ "source": [
8
+ "# [Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) Training notebook"
9
+ ]
10
+ },
11
+ {
12
+ "attachments": {},
13
+ "cell_type": "markdown",
14
+ "metadata": {
15
+ "id": "ZFFCx5J80SGa"
16
+ },
17
+ "source": [
18
+ "[![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)"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "metadata": {
25
+ "id": "GmFP6bN9dvOq"
26
+ },
27
+ "outputs": [],
28
+ "source": [
29
+ "# @title #查看显卡\n",
30
+ "!nvidia-smi"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": null,
36
+ "metadata": {
37
+ "id": "jwu07JgqoFON"
38
+ },
39
+ "outputs": [],
40
+ "source": [
41
+ "# @title 挂载谷歌云盘\n",
42
+ "\n",
43
+ "from google.colab import drive\n",
44
+ "\n",
45
+ "drive.mount(\"/content/drive\")"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": null,
51
+ "metadata": {
52
+ "id": "wjddIFr1oS3W"
53
+ },
54
+ "outputs": [],
55
+ "source": [
56
+ "# @title #安装依赖\n",
57
+ "!apt-get -y install build-essential python3-dev ffmpeg\n",
58
+ "!pip3 install --upgrade setuptools wheel\n",
59
+ "!pip3 install --upgrade pip\n",
60
+ "!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"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": null,
66
+ "metadata": {
67
+ "id": "ge_97mfpgqTm"
68
+ },
69
+ "outputs": [],
70
+ "source": [
71
+ "# @title #克隆仓库\n",
72
+ "\n",
73
+ "!mkdir Retrieval-based-Voice-Conversion-WebUI\n",
74
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
75
+ "!git init\n",
76
+ "!git remote add origin https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git\n",
77
+ "!git fetch origin cfd984812804ddc9247d65b14c82cd32e56c1133 --depth=1\n",
78
+ "!git reset --hard FETCH_HEAD"
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": null,
84
+ "metadata": {
85
+ "id": "BLDEZADkvlw1"
86
+ },
87
+ "outputs": [],
88
+ "source": [
89
+ "# @title #更新仓库(一般无需执行)\n",
90
+ "!git pull"
91
+ ]
92
+ },
93
+ {
94
+ "cell_type": "code",
95
+ "execution_count": null,
96
+ "metadata": {
97
+ "id": "pqE0PrnuRqI2"
98
+ },
99
+ "outputs": [],
100
+ "source": [
101
+ "# @title #安装aria2\n",
102
+ "!apt -y install -qq aria2"
103
+ ]
104
+ },
105
+ {
106
+ "cell_type": "code",
107
+ "execution_count": null,
108
+ "metadata": {
109
+ "id": "UG3XpUwEomUz"
110
+ },
111
+ "outputs": [],
112
+ "source": [
113
+ "# @title 下载底模\n",
114
+ "\n",
115
+ "# v1\n",
116
+ "!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",
117
+ "!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",
118
+ "!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",
119
+ "!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",
120
+ "!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",
121
+ "!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",
122
+ "!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",
123
+ "!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",
124
+ "!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",
125
+ "!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",
126
+ "!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",
127
+ "!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",
128
+ "\n",
129
+ "# v2\n",
130
+ "# !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",
131
+ "!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",
132
+ "# !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",
133
+ "# !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",
134
+ "!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",
135
+ "# !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",
136
+ "# !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",
137
+ "!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",
138
+ "# !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",
139
+ "# !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",
140
+ "!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",
141
+ "# !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"
142
+ ]
143
+ },
144
+ {
145
+ "cell_type": "code",
146
+ "execution_count": null,
147
+ "metadata": {
148
+ "id": "HugjmZqZRuiF"
149
+ },
150
+ "outputs": [],
151
+ "source": [
152
+ "# @title #下载人声分离模型\n",
153
+ "!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",
154
+ "!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"
155
+ ]
156
+ },
157
+ {
158
+ "cell_type": "code",
159
+ "execution_count": null,
160
+ "metadata": {
161
+ "id": "2RCaT9FTR0ej"
162
+ },
163
+ "outputs": [],
164
+ "source": [
165
+ "# @title #下载hubert_base\n",
166
+ "!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"
167
+ ]
168
+ },
169
+ {
170
+ "cell_type": "code",
171
+ "execution_count": null,
172
+ "metadata": {},
173
+ "outputs": [],
174
+ "source": [
175
+ "# @title #下载rmvpe模型\n",
176
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o rmvpe.pt"
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": null,
182
+ "metadata": {
183
+ "id": "Mwk7Q0Loqzjx"
184
+ },
185
+ "outputs": [],
186
+ "source": [
187
+ "# @title #从谷歌云盘加载打包好的数据集到/content/dataset\n",
188
+ "\n",
189
+ "# @markdown 数据集位置\n",
190
+ "DATASET = (\n",
191
+ " \"/content/drive/MyDrive/dataset/lulu20230327_32k.zip\" # @param {type:\"string\"}\n",
192
+ ")\n",
193
+ "\n",
194
+ "!mkdir -p /content/dataset\n",
195
+ "!unzip -d /content/dataset -B {DATASET}"
196
+ ]
197
+ },
198
+ {
199
+ "cell_type": "code",
200
+ "execution_count": null,
201
+ "metadata": {
202
+ "id": "PDlFxWHWEynD"
203
+ },
204
+ "outputs": [],
205
+ "source": [
206
+ "# @title #重命名数据集中的重名文件\n",
207
+ "!ls -a /content/dataset/\n",
208
+ "!rename 's/(\\w+)\\.(\\w+)~(\\d*)/$1_$3.$2/' /content/dataset/*.*~*"
209
+ ]
210
+ },
211
+ {
212
+ "cell_type": "code",
213
+ "execution_count": null,
214
+ "metadata": {
215
+ "id": "7vh6vphDwO0b"
216
+ },
217
+ "outputs": [],
218
+ "source": [
219
+ "# @title #启动webui\n",
220
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
221
+ "# %load_ext tensorboard\n",
222
+ "# %tensorboard --logdir /content/Retrieval-based-Voice-Conversion-WebUI/logs\n",
223
+ "!python3 infer-web.py --colab --pycmd python3"
224
+ ]
225
+ },
226
+ {
227
+ "cell_type": "code",
228
+ "execution_count": null,
229
+ "metadata": {
230
+ "id": "FgJuNeAwx5Y_"
231
+ },
232
+ "outputs": [],
233
+ "source": [
234
+ "# @title #手动将训练后的模型文件备份到谷歌云盘\n",
235
+ "# @markdown #需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
236
+ "\n",
237
+ "# @markdown #模型名\n",
238
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
239
+ "# @markdown #模型epoch\n",
240
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
241
+ "\n",
242
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth\n",
243
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth\n",
244
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/added_*.index /content/drive/MyDrive/\n",
245
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/total_*.npy /content/drive/MyDrive/\n",
246
+ "\n",
247
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth"
248
+ ]
249
+ },
250
+ {
251
+ "cell_type": "code",
252
+ "execution_count": null,
253
+ "metadata": {
254
+ "id": "OVQoLQJXS7WX"
255
+ },
256
+ "outputs": [],
257
+ "source": [
258
+ "# @title 从谷歌云盘恢复pth\n",
259
+ "# @markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
260
+ "\n",
261
+ "# @markdown 模型名\n",
262
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
263
+ "# @markdown 模型epoch\n",
264
+ "MODELEPOCH = 7500 # @param {type:\"integer\"}\n",
265
+ "\n",
266
+ "!mkdir -p /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
267
+ "\n",
268
+ "!cp /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
269
+ "!cp /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
270
+ "!cp /content/drive/MyDrive/*.index /content/\n",
271
+ "!cp /content/drive/MyDrive/*.npy /content/\n",
272
+ "!cp /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "metadata": {
279
+ "id": "ZKAyuKb9J6dz"
280
+ },
281
+ "outputs": [],
282
+ "source": [
283
+ "# @title 手动预处理(不推荐)\n",
284
+ "# @markdown 模型名\n",
285
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
286
+ "# @markdown 采样率\n",
287
+ "BITRATE = 48000 # @param {type:\"integer\"}\n",
288
+ "# @markdown 使用的进程数\n",
289
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
290
+ "\n",
291
+ "!python3 trainset_preprocess_pipeline_print.py /content/dataset {BITRATE} {THREADCOUNT} logs/{MODELNAME} True"
292
+ ]
293
+ },
294
+ {
295
+ "cell_type": "code",
296
+ "execution_count": null,
297
+ "metadata": {
298
+ "id": "CrxJqzAUKmPJ"
299
+ },
300
+ "outputs": [],
301
+ "source": [
302
+ "# @title 手动提取特征(不推荐)\n",
303
+ "# @markdown 模型名\n",
304
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
305
+ "# @markdown 使用的进程数\n",
306
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
307
+ "# @markdown 音高提取算法\n",
308
+ "ALGO = \"harvest\" # @param {type:\"string\"}\n",
309
+ "\n",
310
+ "!python3 extract_f0_print.py logs/{MODELNAME} {THREADCOUNT} {ALGO}\n",
311
+ "\n",
312
+ "!python3 extract_feature_print.py cpu 1 0 0 logs/{MODELNAME}"
313
+ ]
314
+ },
315
+ {
316
+ "cell_type": "code",
317
+ "execution_count": null,
318
+ "metadata": {
319
+ "id": "IMLPLKOaKj58"
320
+ },
321
+ "outputs": [],
322
+ "source": [
323
+ "# @title 手动训练(不推荐)\n",
324
+ "# @markdown 模型名\n",
325
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
326
+ "# @markdown 使用的GPU\n",
327
+ "USEGPU = \"0\" # @param {type:\"string\"}\n",
328
+ "# @markdown 批大小\n",
329
+ "BATCHSIZE = 32 # @param {type:\"integer\"}\n",
330
+ "# @markdown 停止的epoch\n",
331
+ "MODELEPOCH = 3200 # @param {type:\"integer\"}\n",
332
+ "# @markdown 保存epoch间隔\n",
333
+ "EPOCHSAVE = 100 # @param {type:\"integer\"}\n",
334
+ "# @markdown 采样率\n",
335
+ "MODELSAMPLE = \"48k\" # @param {type:\"string\"}\n",
336
+ "# @markdown 是否缓存训练集\n",
337
+ "CACHEDATA = 1 # @param {type:\"integer\"}\n",
338
+ "# @markdown 是否仅保存最新的ckpt文件\n",
339
+ "ONLYLATEST = 0 # @param {type:\"integer\"}\n",
340
+ "\n",
341
+ "!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}"
342
+ ]
343
+ },
344
+ {
345
+ "cell_type": "code",
346
+ "execution_count": null,
347
+ "metadata": {
348
+ "id": "haYA81hySuDl"
349
+ },
350
+ "outputs": [],
351
+ "source": [
352
+ "# @title 删除其它pth,只留选中的(慎点,仔细看代码)\n",
353
+ "# @markdown 模型名\n",
354
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
355
+ "# @markdown 选中模型epoch\n",
356
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
357
+ "\n",
358
+ "!echo \"备份选中的模型。。。\"\n",
359
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
360
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
361
+ "\n",
362
+ "!echo \"正在删除。。。\"\n",
363
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
364
+ "!rm /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*.pth\n",
365
+ "\n",
366
+ "!echo \"恢复选中的模型。。。\"\n",
367
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
368
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
369
+ "\n",
370
+ "!echo \"删除完成\"\n",
371
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
372
+ ]
373
+ },
374
+ {
375
+ "cell_type": "code",
376
+ "execution_count": null,
377
+ "metadata": {
378
+ "id": "QhSiPTVPoIRh"
379
+ },
380
+ "outputs": [],
381
+ "source": [
382
+ "# @title 清除项目下所有文件,只留选中的模型(慎点,仔细看代码)\n",
383
+ "# @markdown 模型名\n",
384
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
385
+ "# @markdown 选中模型epoch\n",
386
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
387
+ "\n",
388
+ "!echo \"备份选中的模型。。。\"\n",
389
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
390
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
391
+ "\n",
392
+ "!echo \"正在删除。。。\"\n",
393
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
394
+ "!rm -rf /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*\n",
395
+ "\n",
396
+ "!echo \"恢复选中的模型。。。\"\n",
397
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
398
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
399
+ "\n",
400
+ "!echo \"删除完成\"\n",
401
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
402
+ ]
403
+ }
404
+ ],
405
+ "metadata": {
406
+ "accelerator": "GPU",
407
+ "colab": {
408
+ "private_outputs": true,
409
+ "provenance": []
410
+ },
411
+ "gpuClass": "standard",
412
+ "kernelspec": {
413
+ "display_name": "Python 3",
414
+ "name": "python3"
415
+ },
416
+ "language_info": {
417
+ "name": "python"
418
+ }
419
+ },
420
+ "nbformat": 4,
421
+ "nbformat_minor": 0
422
+ }
a.png ADDED
app.py ADDED
@@ -0,0 +1,1463 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ import datetime, subprocess
3
+ from mega import Mega
4
+ now_dir = os.getcwd()
5
+ sys.path.append(now_dir)
6
+ import logging
7
+ import shutil
8
+ import threading
9
+ import traceback
10
+ import warnings
11
+ from random import shuffle
12
+ from subprocess import Popen
13
+ from time import sleep
14
+ import json
15
+ import pathlib
16
+
17
+ import fairseq
18
+ import faiss
19
+ import gradio as gr
20
+ import numpy as np
21
+ import torch
22
+ from dotenv import load_dotenv
23
+ from sklearn.cluster import MiniBatchKMeans
24
+
25
+ from configs.config import Config
26
+ from i18n.i18n import I18nAuto
27
+ from infer.lib.train.process_ckpt import (
28
+ change_info,
29
+ extract_small_model,
30
+ merge,
31
+ show_info,
32
+ )
33
+ from infer.modules.uvr5.modules import uvr
34
+ from infer.modules.vc.modules import VC
35
+ import subprocess, os
36
+
37
+ logging.getLogger("numba").setLevel(logging.WARNING)
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+ tmp = os.path.join(now_dir, "TEMP")
42
+ shutil.rmtree(tmp, ignore_errors=True)
43
+ shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)
44
+ shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)
45
+ os.makedirs(tmp, exist_ok=True)
46
+ os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)
47
+ os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)
48
+ os.environ["TEMP"] = tmp
49
+ warnings.filterwarnings("ignore")
50
+ torch.manual_seed(114514)
51
+
52
+ assets_folder = "./assets/"
53
+ if not os.path.exists(assets_folder):
54
+ os.makedirs(assets_folder)
55
+ files = {
56
+ "rmvpe/rmvpe.pt":"https://huggingface.co/Rejekts/project/resolve/main/rmvpe.pt",
57
+ "hubert/hubert_base.pt":"https://huggingface.co/Rejekts/project/resolve/main/hubert_base.pt",
58
+ "pretrained_v2/D40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/D40k.pth",
59
+ "pretrained_v2/G40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/G40k.pth",
60
+ "pretrained_v2/f0D40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/f0D40k.pth",
61
+ "pretrained_v2/f0G40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/f0G40k.pth"
62
+ }
63
+ for file, link in files.items():
64
+ file_path = os.path.join(assets_folder, file)
65
+ if not os.path.exists(file_path):
66
+ try:
67
+ subprocess.run(['wget', link, '-O', file_path], check=True)
68
+ except subprocess.CalledProcessError as e:
69
+ print(f"Error downloading {file}: {e}")
70
+
71
+
72
+
73
+ load_dotenv()
74
+ config = Config()
75
+ vc = VC(config)
76
+
77
+ if config.dml == True:
78
+
79
+ def forward_dml(ctx, x, scale):
80
+ ctx.scale = scale
81
+ res = x.clone().detach()
82
+ return res
83
+
84
+ fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml
85
+ i18n = I18nAuto()
86
+ logger.info(i18n)
87
+ # 判断是否有能用来训练和加速推理的N卡
88
+ ngpu = torch.cuda.device_count()
89
+ gpu_infos = []
90
+ mem = []
91
+ if_gpu_ok = False
92
+
93
+ if torch.cuda.is_available() or ngpu != 0:
94
+ for i in range(ngpu):
95
+ gpu_name = torch.cuda.get_device_name(i)
96
+ if any(
97
+ value in gpu_name.upper()
98
+ for value in [
99
+ "10",
100
+ "16",
101
+ "20",
102
+ "30",
103
+ "40",
104
+ "A2",
105
+ "A3",
106
+ "A4",
107
+ "P4",
108
+ "A50",
109
+ "500",
110
+ "A60",
111
+ "70",
112
+ "80",
113
+ "90",
114
+ "M4",
115
+ "T4",
116
+ "TITAN",
117
+ ]
118
+ ):
119
+ # A10#A100#V100#A40#P40#M40#K80#A4500
120
+ if_gpu_ok = True # 至少有一张能用的N卡
121
+ gpu_infos.append("%s\t%s" % (i, gpu_name))
122
+ mem.append(
123
+ int(
124
+ torch.cuda.get_device_properties(i).total_memory
125
+ / 1024
126
+ / 1024
127
+ / 1024
128
+ + 0.4
129
+ )
130
+ )
131
+ if if_gpu_ok and len(gpu_infos) > 0:
132
+ gpu_info = "\n".join(gpu_infos)
133
+ default_batch_size = min(mem) // 2
134
+ else:
135
+ gpu_info = i18n("很遗憾您这没有能用的显卡来支持您训练")
136
+ default_batch_size = 1
137
+ gpus = "-".join([i[0] for i in gpu_infos])
138
+
139
+
140
+ class ToolButton(gr.Button, gr.components.FormComponent):
141
+ """Small button with single emoji as text, fits inside gradio forms"""
142
+
143
+ def __init__(self, **kwargs):
144
+ super().__init__(variant="tool", **kwargs)
145
+
146
+ def get_block_name(self):
147
+ return "button"
148
+
149
+
150
+ weight_root = os.getenv("weight_root")
151
+ weight_uvr5_root = os.getenv("weight_uvr5_root")
152
+ index_root = os.getenv("index_root")
153
+
154
+ names = []
155
+ for name in os.listdir(weight_root):
156
+ if name.endswith(".pth"):
157
+ names.append(name)
158
+ index_paths = []
159
+ for root, dirs, files in os.walk(index_root, topdown=False):
160
+ for name in files:
161
+ if name.endswith(".index") and "trained" not in name:
162
+ index_paths.append("%s/%s" % (root, name))
163
+ uvr5_names = []
164
+ for name in os.listdir(weight_uvr5_root):
165
+ if name.endswith(".pth") or "onnx" in name:
166
+ uvr5_names.append(name.replace(".pth", ""))
167
+
168
+
169
+ def change_choices():
170
+ names = []
171
+ for name in os.listdir(weight_root):
172
+ if name.endswith(".pth"):
173
+ names.append(name)
174
+ index_paths = []
175
+ for root, dirs, files in os.walk(index_root, topdown=False):
176
+ for name in files:
177
+ if name.endswith(".index") and "trained" not in name:
178
+ index_paths.append("%s/%s" % (root, name))
179
+ audio_files=[]
180
+ for filename in os.listdir("./audios"):
181
+ if filename.endswith(('.wav','.mp3','.ogg')):
182
+ audio_files.append('./audios/'+filename)
183
+ return {"choices": sorted(names), "__type__": "update"}, {
184
+ "choices": sorted(index_paths),
185
+ "__type__": "update",
186
+ }, {"choices": sorted(audio_files), "__type__": "update"}
187
+
188
+ def clean():
189
+ return {"value": "", "__type__": "update"}
190
+
191
+
192
+ def export_onnx():
193
+ from infer.modules.onnx.export import export_onnx as eo
194
+
195
+ eo()
196
+
197
+
198
+ sr_dict = {
199
+ "32k": 32000,
200
+ "40k": 40000,
201
+ "48k": 48000,
202
+ }
203
+
204
+
205
+ def if_done(done, p):
206
+ while 1:
207
+ if p.poll() is None:
208
+ sleep(0.5)
209
+ else:
210
+ break
211
+ done[0] = True
212
+
213
+
214
+ def if_done_multi(done, ps):
215
+ while 1:
216
+ # poll==None代表进程未结束
217
+ # 只要有一个进程未结束都不停
218
+ flag = 1
219
+ for p in ps:
220
+ if p.poll() is None:
221
+ flag = 0
222
+ sleep(0.5)
223
+ break
224
+ if flag == 1:
225
+ break
226
+ done[0] = True
227
+
228
+
229
+ def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):
230
+ sr = sr_dict[sr]
231
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
232
+ f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")
233
+ f.close()
234
+ per = 3.0 if config.is_half else 3.7
235
+ cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (
236
+ config.python_cmd,
237
+ trainset_dir,
238
+ sr,
239
+ n_p,
240
+ now_dir,
241
+ exp_dir,
242
+ config.noparallel,
243
+ per,
244
+ )
245
+ logger.info(cmd)
246
+ p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir
247
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
248
+ done = [False]
249
+ threading.Thread(
250
+ target=if_done,
251
+ args=(
252
+ done,
253
+ p,
254
+ ),
255
+ ).start()
256
+ while 1:
257
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
258
+ yield (f.read())
259
+ sleep(1)
260
+ if done[0]:
261
+ break
262
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
263
+ log = f.read()
264
+ logger.info(log)
265
+ yield log
266
+
267
+
268
+ # but2.click(extract_f0,[gpus6,np7,f0method8,if_f0_3,trainset_dir4],[info2])
269
+ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, gpus_rmvpe):
270
+ gpus = gpus.split("-")
271
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
272
+ f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")
273
+ f.close()
274
+ if if_f0:
275
+ if f0method != "rmvpe_gpu":
276
+ cmd = (
277
+ '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'
278
+ % (
279
+ config.python_cmd,
280
+ now_dir,
281
+ exp_dir,
282
+ n_p,
283
+ f0method,
284
+ )
285
+ )
286
+ logger.info(cmd)
287
+ p = Popen(
288
+ cmd, shell=True, cwd=now_dir
289
+ ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE
290
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
291
+ done = [False]
292
+ threading.Thread(
293
+ target=if_done,
294
+ args=(
295
+ done,
296
+ p,
297
+ ),
298
+ ).start()
299
+ else:
300
+ if gpus_rmvpe != "-":
301
+ gpus_rmvpe = gpus_rmvpe.split("-")
302
+ leng = len(gpus_rmvpe)
303
+ ps = []
304
+ for idx, n_g in enumerate(gpus_rmvpe):
305
+ cmd = (
306
+ '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '
307
+ % (
308
+ config.python_cmd,
309
+ leng,
310
+ idx,
311
+ n_g,
312
+ now_dir,
313
+ exp_dir,
314
+ config.is_half,
315
+ )
316
+ )
317
+ logger.info(cmd)
318
+ p = Popen(
319
+ cmd, shell=True, cwd=now_dir
320
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
321
+ ps.append(p)
322
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就��常读一句输出一句;只能额外弄出一个文本流定时读
323
+ done = [False]
324
+ threading.Thread(
325
+ target=if_done_multi, #
326
+ args=(
327
+ done,
328
+ ps,
329
+ ),
330
+ ).start()
331
+ else:
332
+ cmd = (
333
+ config.python_cmd
334
+ + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '
335
+ % (
336
+ now_dir,
337
+ exp_dir,
338
+ )
339
+ )
340
+ logger.info(cmd)
341
+ p = Popen(
342
+ cmd, shell=True, cwd=now_dir
343
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
344
+ p.wait()
345
+ done = [True]
346
+ while 1:
347
+ with open(
348
+ "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"
349
+ ) as f:
350
+ yield (f.read())
351
+ sleep(1)
352
+ if done[0]:
353
+ break
354
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
355
+ log = f.read()
356
+ logger.info(log)
357
+ yield log
358
+ ####对不同part分别开多进程
359
+ """
360
+ n_part=int(sys.argv[1])
361
+ i_part=int(sys.argv[2])
362
+ i_gpu=sys.argv[3]
363
+ exp_dir=sys.argv[4]
364
+ os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)
365
+ """
366
+ leng = len(gpus)
367
+ ps = []
368
+ for idx, n_g in enumerate(gpus):
369
+ cmd = (
370
+ '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'
371
+ % (
372
+ config.python_cmd,
373
+ config.device,
374
+ leng,
375
+ idx,
376
+ n_g,
377
+ now_dir,
378
+ exp_dir,
379
+ version19,
380
+ )
381
+ )
382
+ logger.info(cmd)
383
+ p = Popen(
384
+ cmd, shell=True, cwd=now_dir
385
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
386
+ ps.append(p)
387
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
388
+ done = [False]
389
+ threading.Thread(
390
+ target=if_done_multi,
391
+ args=(
392
+ done,
393
+ ps,
394
+ ),
395
+ ).start()
396
+ while 1:
397
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
398
+ yield (f.read())
399
+ sleep(1)
400
+ if done[0]:
401
+ break
402
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
403
+ log = f.read()
404
+ logger.info(log)
405
+ yield log
406
+
407
+
408
+ def get_pretrained_models(path_str, f0_str, sr2):
409
+ if_pretrained_generator_exist = os.access(
410
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
411
+ )
412
+ if_pretrained_discriminator_exist = os.access(
413
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
414
+ )
415
+ if not if_pretrained_generator_exist:
416
+ logger.warn(
417
+ "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",
418
+ path_str,
419
+ f0_str,
420
+ sr2,
421
+ )
422
+ if not if_pretrained_discriminator_exist:
423
+ logger.warn(
424
+ "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",
425
+ path_str,
426
+ f0_str,
427
+ sr2,
428
+ )
429
+ return (
430
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
431
+ if if_pretrained_generator_exist
432
+ else "",
433
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
434
+ if if_pretrained_discriminator_exist
435
+ else "",
436
+ )
437
+
438
+
439
+ def change_sr2(sr2, if_f0_3, version19):
440
+ path_str = "" if version19 == "v1" else "_v2"
441
+ f0_str = "f0" if if_f0_3 else ""
442
+ return get_pretrained_models(path_str, f0_str, sr2)
443
+
444
+
445
+ def change_version19(sr2, if_f0_3, version19):
446
+ path_str = "" if version19 == "v1" else "_v2"
447
+ if sr2 == "32k" and version19 == "v1":
448
+ sr2 = "40k"
449
+ to_return_sr2 = (
450
+ {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}
451
+ if version19 == "v1"
452
+ else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}
453
+ )
454
+ f0_str = "f0" if if_f0_3 else ""
455
+ return (
456
+ *get_pretrained_models(path_str, f0_str, sr2),
457
+ to_return_sr2,
458
+ )
459
+
460
+
461
+ def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15
462
+ path_str = "" if version19 == "v1" else "_v2"
463
+ return (
464
+ {"visible": if_f0_3, "__type__": "update"},
465
+ *get_pretrained_models(path_str, "f0", sr2),
466
+ )
467
+
468
+
469
+ # but3.click(click_train,[exp_dir1,sr2,if_f0_3,save_epoch10,total_epoch11,batch_size12,if_save_latest13,pretrained_G14,pretrained_D15,gpus16])
470
+ def click_train(
471
+ exp_dir1,
472
+ sr2,
473
+ if_f0_3,
474
+ spk_id5,
475
+ save_epoch10,
476
+ total_epoch11,
477
+ batch_size12,
478
+ if_save_latest13,
479
+ pretrained_G14,
480
+ pretrained_D15,
481
+ gpus16,
482
+ if_cache_gpu17,
483
+ if_save_every_weights18,
484
+ version19,
485
+ ):
486
+ # 生成filelist
487
+ exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
488
+ os.makedirs(exp_dir, exist_ok=True)
489
+ gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)
490
+ feature_dir = (
491
+ "%s/3_feature256" % (exp_dir)
492
+ if version19 == "v1"
493
+ else "%s/3_feature768" % (exp_dir)
494
+ )
495
+ if if_f0_3:
496
+ f0_dir = "%s/2a_f0" % (exp_dir)
497
+ f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)
498
+ names = (
499
+ set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])
500
+ & set([name.split(".")[0] for name in os.listdir(feature_dir)])
501
+ & set([name.split(".")[0] for name in os.listdir(f0_dir)])
502
+ & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])
503
+ )
504
+ else:
505
+ names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(
506
+ [name.split(".")[0] for name in os.listdir(feature_dir)]
507
+ )
508
+ opt = []
509
+ for name in names:
510
+ if if_f0_3:
511
+ opt.append(
512
+ "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"
513
+ % (
514
+ gt_wavs_dir.replace("\\", "\\\\"),
515
+ name,
516
+ feature_dir.replace("\\", "\\\\"),
517
+ name,
518
+ f0_dir.replace("\\", "\\\\"),
519
+ name,
520
+ f0nsf_dir.replace("\\", "\\\\"),
521
+ name,
522
+ spk_id5,
523
+ )
524
+ )
525
+ else:
526
+ opt.append(
527
+ "%s/%s.wav|%s/%s.npy|%s"
528
+ % (
529
+ gt_wavs_dir.replace("\\", "\\\\"),
530
+ name,
531
+ feature_dir.replace("\\", "\\\\"),
532
+ name,
533
+ spk_id5,
534
+ )
535
+ )
536
+ fea_dim = 256 if version19 == "v1" else 768
537
+ if if_f0_3:
538
+ for _ in range(2):
539
+ opt.append(
540
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s/logs/mute/2a_f0/mute.wav.npy|%s/logs/mute/2b-f0nsf/mute.wav.npy|%s"
541
+ % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)
542
+ )
543
+ else:
544
+ for _ in range(2):
545
+ opt.append(
546
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"
547
+ % (now_dir, sr2, now_dir, fea_dim, spk_id5)
548
+ )
549
+ shuffle(opt)
550
+ with open("%s/filelist.txt" % exp_dir, "w") as f:
551
+ f.write("\n".join(opt))
552
+ logger.debug("Write filelist done")
553
+ # 生成config#无需生成config
554
+ # cmd = python_cmd + " train_nsf_sim_cache_sid_load_pretrain.py -e mi-test -sr 40k -f0 1 -bs 4 -g 0 -te 10 -se 5 -pg pretrained/f0G40k.pth -pd pretrained/f0D40k.pth -l 1 -c 0"
555
+ logger.info("Use gpus: %s", str(gpus16))
556
+ if pretrained_G14 == "":
557
+ logger.info("No pretrained Generator")
558
+ if pretrained_D15 == "":
559
+ logger.info("No pretrained Discriminator")
560
+ if version19 == "v1" or sr2 == "40k":
561
+ config_path = "v1/%s.json" % sr2
562
+ else:
563
+ config_path = "v2/%s.json" % sr2
564
+ config_save_path = os.path.join(exp_dir, "config.json")
565
+ if not pathlib.Path(config_save_path).exists():
566
+ with open(config_save_path, "w", encoding="utf-8") as f:
567
+ json.dump(
568
+ config.json_config[config_path],
569
+ f,
570
+ ensure_ascii=False,
571
+ indent=4,
572
+ sort_keys=True,
573
+ )
574
+ f.write("\n")
575
+ if gpus16:
576
+ cmd = (
577
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
578
+ % (
579
+ config.python_cmd,
580
+ exp_dir1,
581
+ sr2,
582
+ 1 if if_f0_3 else 0,
583
+ batch_size12,
584
+ gpus16,
585
+ total_epoch11,
586
+ save_epoch10,
587
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
588
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
589
+ 1 if if_save_latest13 == i18n("是") else 0,
590
+ 1 if if_cache_gpu17 == i18n("是") else 0,
591
+ 1 if if_save_every_weights18 == i18n("是") else 0,
592
+ version19,
593
+ )
594
+ )
595
+ else:
596
+ cmd = (
597
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
598
+ % (
599
+ config.python_cmd,
600
+ exp_dir1,
601
+ sr2,
602
+ 1 if if_f0_3 else 0,
603
+ batch_size12,
604
+ total_epoch11,
605
+ save_epoch10,
606
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
607
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
608
+ 1 if if_save_latest13 == i18n("是") else 0,
609
+ 1 if if_cache_gpu17 == i18n("是") else 0,
610
+ 1 if if_save_every_weights18 == i18n("是") else 0,
611
+ version19,
612
+ )
613
+ )
614
+ logger.info(cmd)
615
+ p = Popen(cmd, shell=True, cwd=now_dir)
616
+ p.wait()
617
+ return "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"
618
+
619
+
620
+ # but4.click(train_index, [exp_dir1], info3)
621
+ def train_index(exp_dir1, version19):
622
+ # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
623
+ exp_dir = "logs/%s" % (exp_dir1)
624
+ os.makedirs(exp_dir, exist_ok=True)
625
+ feature_dir = (
626
+ "%s/3_feature256" % (exp_dir)
627
+ if version19 == "v1"
628
+ else "%s/3_feature768" % (exp_dir)
629
+ )
630
+ if not os.path.exists(feature_dir):
631
+ return "请先进行特征提取!"
632
+ listdir_res = list(os.listdir(feature_dir))
633
+ if len(listdir_res) == 0:
634
+ return "请先进行特征提取!"
635
+ infos = []
636
+ npys = []
637
+ for name in sorted(listdir_res):
638
+ phone = np.load("%s/%s" % (feature_dir, name))
639
+ npys.append(phone)
640
+ big_npy = np.concatenate(npys, 0)
641
+ big_npy_idx = np.arange(big_npy.shape[0])
642
+ np.random.shuffle(big_npy_idx)
643
+ big_npy = big_npy[big_npy_idx]
644
+ if big_npy.shape[0] > 2e5:
645
+ infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
646
+ yield "\n".join(infos)
647
+ try:
648
+ big_npy = (
649
+ MiniBatchKMeans(
650
+ n_clusters=10000,
651
+ verbose=True,
652
+ batch_size=256 * config.n_cpu,
653
+ compute_labels=False,
654
+ init="random",
655
+ )
656
+ .fit(big_npy)
657
+ .cluster_centers_
658
+ )
659
+ except:
660
+ info = traceback.format_exc()
661
+ logger.info(info)
662
+ infos.append(info)
663
+ yield "\n".join(infos)
664
+
665
+ np.save("%s/total_fea.npy" % exp_dir, big_npy)
666
+ n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
667
+ infos.append("%s,%s" % (big_npy.shape, n_ivf))
668
+ yield "\n".join(infos)
669
+ index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
670
+ # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)
671
+ infos.append("training")
672
+ yield "\n".join(infos)
673
+ index_ivf = faiss.extract_index_ivf(index) #
674
+ index_ivf.nprobe = 1
675
+ index.train(big_npy)
676
+ faiss.write_index(
677
+ index,
678
+ "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"
679
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
680
+ )
681
+
682
+ infos.append("adding")
683
+ yield "\n".join(infos)
684
+ batch_size_add = 8192
685
+ for i in range(0, big_npy.shape[0], batch_size_add):
686
+ index.add(big_npy[i : i + batch_size_add])
687
+ faiss.write_index(
688
+ index,
689
+ "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"
690
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
691
+ )
692
+ infos.append(
693
+ "成功构建索引,added_IVF%s_Flat_nprobe_%s_%s_%s.index"
694
+ % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
695
+ )
696
+ # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))
697
+ # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))
698
+ yield "\n".join(infos)
699
+
700
+
701
+ # but5.click(train1key, [exp_dir1, sr2, if_f0_3, trainset_dir4, spk_id5, gpus6, np7, f0method8, save_epoch10, total_epoch11, batch_size12, if_save_latest13, pretrained_G14, pretrained_D15, gpus16, if_cache_gpu17], info3)
702
+ def train1key(
703
+ exp_dir1,
704
+ sr2,
705
+ if_f0_3,
706
+ trainset_dir4,
707
+ spk_id5,
708
+ np7,
709
+ f0method8,
710
+ save_epoch10,
711
+ total_epoch11,
712
+ batch_size12,
713
+ if_save_latest13,
714
+ pretrained_G14,
715
+ pretrained_D15,
716
+ gpus16,
717
+ if_cache_gpu17,
718
+ if_save_every_weights18,
719
+ version19,
720
+ gpus_rmvpe,
721
+ ):
722
+ infos = []
723
+
724
+ def get_info_str(strr):
725
+ infos.append(strr)
726
+ return "\n".join(infos)
727
+
728
+ ####### step1:处理数据
729
+ yield get_info_str(i18n("step1:正在处理数据"))
730
+ [get_info_str(_) for _ in preprocess_dataset(trainset_dir4, exp_dir1, sr2, np7)]
731
+
732
+ ####### step2a:提取音高
733
+ yield get_info_str(i18n("step2:正在提取音高&正在提取特征"))
734
+ [
735
+ get_info_str(_)
736
+ for _ in extract_f0_feature(
737
+ gpus16, np7, f0method8, if_f0_3, exp_dir1, version19, gpus_rmvpe
738
+ )
739
+ ]
740
+
741
+ ####### step3a:训练模型
742
+ yield get_info_str(i18n("step3a:正在训练模型"))
743
+ click_train(
744
+ exp_dir1,
745
+ sr2,
746
+ if_f0_3,
747
+ spk_id5,
748
+ save_epoch10,
749
+ total_epoch11,
750
+ batch_size12,
751
+ if_save_latest13,
752
+ pretrained_G14,
753
+ pretrained_D15,
754
+ gpus16,
755
+ if_cache_gpu17,
756
+ if_save_every_weights18,
757
+ version19,
758
+ )
759
+ yield get_info_str(i18n("训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"))
760
+
761
+ ####### step3b:训练索引
762
+ [get_info_str(_) for _ in train_index(exp_dir1, version19)]
763
+ yield get_info_str(i18n("全流程结束!"))
764
+
765
+
766
+ # ckpt_path2.change(change_info_,[ckpt_path2],[sr__,if_f0__])
767
+ def change_info_(ckpt_path):
768
+ if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):
769
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
770
+ try:
771
+ with open(
772
+ ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"
773
+ ) as f:
774
+ info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])
775
+ sr, f0 = info["sample_rate"], info["if_f0"]
776
+ version = "v2" if ("version" in info and info["version"] == "v2") else "v1"
777
+ return sr, str(f0), version
778
+ except:
779
+ traceback.print_exc()
780
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
781
+
782
+
783
+ F0GPUVisible = config.dml == False
784
+
785
+
786
+ def change_f0_method(f0method8):
787
+ if f0method8 == "rmvpe_gpu":
788
+ visible = F0GPUVisible
789
+ else:
790
+ visible = False
791
+ return {"visible": visible, "__type__": "update"}
792
+
793
+ def find_model():
794
+ if len(names) > 0:
795
+ vc.get_vc(sorted(names)[0],None,None)
796
+ return sorted(names)[0]
797
+ else:
798
+ try:
799
+ gr.Info("Do not forget to choose a model.")
800
+ except:
801
+ pass
802
+ return ''
803
+
804
+ def find_audios(index=False):
805
+ audio_files=[]
806
+ if not os.path.exists('./audios'): os.mkdir("./audios")
807
+ for filename in os.listdir("./audios"):
808
+ if filename.endswith(('.wav','.mp3','.ogg')):
809
+ audio_files.append("./audios/"+filename)
810
+ if index:
811
+ if len(audio_files) > 0: return sorted(audio_files)[0]
812
+ else: return ""
813
+ elif len(audio_files) > 0: return sorted(audio_files)
814
+ else: return []
815
+
816
+ def get_index():
817
+ if find_model() != '':
818
+ chosen_model=sorted(names)[0].split(".")[0]
819
+ logs_path="./logs/"+chosen_model
820
+ if os.path.exists(logs_path):
821
+ for file in os.listdir(logs_path):
822
+ if file.endswith(".index"):
823
+ return os.path.join(logs_path, file)
824
+ return ''
825
+ else:
826
+ return ''
827
+
828
+ def get_indexes():
829
+ indexes_list=[]
830
+ for dirpath, dirnames, filenames in os.walk("./logs/"):
831
+ for filename in filenames:
832
+ if filename.endswith(".index"):
833
+ indexes_list.append(os.path.join(dirpath,filename))
834
+ if len(indexes_list) > 0:
835
+ return indexes_list
836
+ else:
837
+ return ''
838
+
839
+ def save_wav(file):
840
+ try:
841
+ file_path=file.name
842
+ shutil.move(file_path,'./audios')
843
+ return './audios/'+os.path.basename(file_path)
844
+ except AttributeError:
845
+ try:
846
+ new_name = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")+'.wav'
847
+ new_path='./audios/'+new_name
848
+ shutil.move(file,new_path)
849
+ return new_path
850
+ except TypeError:
851
+ return None
852
+
853
+ def download_from_url(url, model):
854
+ if url == '':
855
+ return "URL cannot be left empty."
856
+ if model =='':
857
+ return "You need to name your model. For example: My-Model"
858
+ url = url.strip()
859
+ zip_dirs = ["zips", "unzips"]
860
+ for directory in zip_dirs:
861
+ if os.path.exists(directory):
862
+ shutil.rmtree(directory)
863
+ os.makedirs("zips", exist_ok=True)
864
+ os.makedirs("unzips", exist_ok=True)
865
+ zipfile = model + '.zip'
866
+ zipfile_path = './zips/' + zipfile
867
+ try:
868
+ if "drive.google.com" in url:
869
+ subprocess.run(["gdown", url, "--fuzzy", "-O", zipfile_path])
870
+ elif "mega.nz" in url:
871
+ m = Mega()
872
+ m.download_url(url, './zips')
873
+ else:
874
+ subprocess.run(["wget", url, "-O", zipfile_path])
875
+ for filename in os.listdir("./zips"):
876
+ if filename.endswith(".zip"):
877
+ zipfile_path = os.path.join("./zips/",filename)
878
+ shutil.unpack_archive(zipfile_path, "./unzips", 'zip')
879
+ else:
880
+ return "No zipfile found."
881
+ for root, dirs, files in os.walk('./unzips'):
882
+ for file in files:
883
+ file_path = os.path.join(root, file)
884
+ if file.endswith(".index"):
885
+ os.mkdir(f'./logs/{model}')
886
+ shutil.copy2(file_path,f'./logs/{model}')
887
+ elif "G_" not in file and "D_" not in file and file.endswith(".pth"):
888
+ shutil.copy(file_path,f'./assets/weights/{model}.pth')
889
+ shutil.rmtree("zips")
890
+ shutil.rmtree("unzips")
891
+ return "Success."
892
+ except:
893
+ return "There's been an error."
894
+
895
+ def upload_to_dataset(files, dir):
896
+ if dir == '':
897
+ dir = './dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
898
+ if not os.path.exists(dir):
899
+ os.makedirs(dir)
900
+ for file in files:
901
+ path=file.name
902
+ shutil.copy2(path,dir)
903
+ try:
904
+ gr.Info(i18n("处理数据"))
905
+ except:
906
+ pass
907
+ return i18n("处理数据"), {"value":dir,"__type__":"update"}
908
+
909
+ def download_model_files(model):
910
+ model_found = False
911
+ index_found = False
912
+ if os.path.exists(f'./assets/weights/{model}.pth'): model_found = True
913
+ if os.path.exists(f'./logs/{model}'):
914
+ for file in os.listdir(f'./logs/{model}'):
915
+ if file.endswith('.index') and 'added' in file:
916
+ log_file = file
917
+ index_found = True
918
+ if model_found and index_found:
919
+ return [f'./assets/weights/{model}.pth', f'./logs/{model}/{log_file}'], "Done"
920
+ elif model_found and not index_found:
921
+ return f'./assets/weights/{model}.pth', "Could not find Index file."
922
+ elif index_found and not model_found:
923
+ return f'./logs/{model}/{log_file}', f'Make sure the Voice Name is correct. I could not find {model}.pth'
924
+ else:
925
+ return None, f'Could not find {model}.pth or corresponding Index file.'
926
+
927
+ with gr.Blocks(title="🔊",theme=gr.themes.Base(primary_hue="rose",neutral_hue="zinc")) as app:
928
+ with gr.Row():
929
+ gr.HTML("<img src='file/a.png' alt='image'>")
930
+ with gr.Tabs():
931
+ with gr.TabItem(i18n("模型推理")):
932
+ with gr.Row():
933
+ sid0 = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names), value=find_model())
934
+ refresh_button = gr.Button(i18n("刷新音色列表和索引路径"), variant="primary")
935
+ #clean_button = gr.Button(i18n("卸载音色省显存"), variant="primary")
936
+ spk_item = gr.Slider(
937
+ minimum=0,
938
+ maximum=2333,
939
+ step=1,
940
+ label=i18n("请选择说话人id"),
941
+ value=0,
942
+ visible=False,
943
+ interactive=True,
944
+ )
945
+ #clean_button.click(
946
+ # fn=clean, inputs=[], outputs=[sid0], api_name="infer_clean"
947
+ #)
948
+ vc_transform0 = gr.Number(
949
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
950
+ )
951
+ but0 = gr.Button(i18n("转换"), variant="primary")
952
+ with gr.Row():
953
+ with gr.Column():
954
+ with gr.Row():
955
+ dropbox = gr.File(label="Drop your audio here & hit the Reload button.")
956
+ with gr.Row():
957
+ record_button=gr.Audio(source="microphone", label="OR Record audio.", type="filepath")
958
+ with gr.Row():
959
+ input_audio0 = gr.Dropdown(
960
+ label=i18n("输入待处理音频文件路径(默认是正确格式示例)"),
961
+ value=find_audios(True),
962
+ choices=find_audios()
963
+ )
964
+ record_button.change(fn=save_wav, inputs=[record_button], outputs=[input_audio0])
965
+ dropbox.upload(fn=save_wav, inputs=[dropbox], outputs=[input_audio0])
966
+ with gr.Column():
967
+ with gr.Accordion(label=i18n("自动检测index路径,下拉式选择(dropdown)"), open=False):
968
+ file_index2 = gr.Dropdown(
969
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
970
+ choices=get_indexes(),
971
+ interactive=True,
972
+ value=get_index()
973
+ )
974
+ index_rate1 = gr.Slider(
975
+ minimum=0,
976
+ maximum=1,
977
+ label=i18n("检索特征占比"),
978
+ value=0.66,
979
+ interactive=True,
980
+ )
981
+ vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
982
+ with gr.Accordion(label=i18n("常规设置"), open=False):
983
+ f0method0 = gr.Radio(
984
+ label=i18n(
985
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
986
+ ),
987
+ choices=["pm", "harvest", "crepe", "rmvpe"]
988
+ if config.dml == False
989
+ else ["pm", "harvest", "rmvpe"],
990
+ value="rmvpe",
991
+ interactive=True,
992
+ )
993
+ filter_radius0 = gr.Slider(
994
+ minimum=0,
995
+ maximum=7,
996
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
997
+ value=3,
998
+ step=1,
999
+ interactive=True,
1000
+ )
1001
+ resample_sr0 = gr.Slider(
1002
+ minimum=0,
1003
+ maximum=48000,
1004
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
1005
+ value=0,
1006
+ step=1,
1007
+ interactive=True,
1008
+ visible=False
1009
+ )
1010
+ rms_mix_rate0 = gr.Slider(
1011
+ minimum=0,
1012
+ maximum=1,
1013
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
1014
+ value=0.21,
1015
+ interactive=True,
1016
+ )
1017
+ protect0 = gr.Slider(
1018
+ minimum=0,
1019
+ maximum=0.5,
1020
+ label=i18n(
1021
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
1022
+ ),
1023
+ value=0.33,
1024
+ step=0.01,
1025
+ interactive=True,
1026
+ )
1027
+ file_index1 = gr.Textbox(
1028
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
1029
+ value="",
1030
+ interactive=True,
1031
+ visible=False
1032
+ )
1033
+ refresh_button.click(
1034
+ fn=change_choices,
1035
+ inputs=[],
1036
+ outputs=[sid0, file_index2, input_audio0],
1037
+ api_name="infer_refresh",
1038
+ )
1039
+ # file_big_npy1 = gr.Textbox(
1040
+ # label=i18n("特征文件路径"),
1041
+ # value="E:\\codes\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1042
+ # interactive=True,
1043
+ # )
1044
+ with gr.Row():
1045
+ f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"), visible=False)
1046
+ with gr.Row():
1047
+ vc_output1 = gr.Textbox(label=i18n("输出信息"))
1048
+ but0.click(
1049
+ vc.vc_single,
1050
+ [
1051
+ spk_item,
1052
+ input_audio0,
1053
+ vc_transform0,
1054
+ f0_file,
1055
+ f0method0,
1056
+ file_index1,
1057
+ file_index2,
1058
+ # file_big_npy1,
1059
+ index_rate1,
1060
+ filter_radius0,
1061
+ resample_sr0,
1062
+ rms_mix_rate0,
1063
+ protect0,
1064
+ ],
1065
+ [vc_output1, vc_output2],
1066
+ api_name="infer_convert",
1067
+ )
1068
+ with gr.Row():
1069
+ with gr.Accordion(open=False, label=i18n("批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ")):
1070
+ with gr.Row():
1071
+ opt_input = gr.Textbox(label=i18n("指定输出文件夹"), value="opt")
1072
+ vc_transform1 = gr.Number(
1073
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
1074
+ )
1075
+ f0method1 = gr.Radio(
1076
+ label=i18n(
1077
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
1078
+ ),
1079
+ choices=["pm", "harvest", "crepe", "rmvpe"]
1080
+ if config.dml == False
1081
+ else ["pm", "harvest", "rmvpe"],
1082
+ value="pm",
1083
+ interactive=True,
1084
+ )
1085
+ with gr.Row():
1086
+ filter_radius1 = gr.Slider(
1087
+ minimum=0,
1088
+ maximum=7,
1089
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
1090
+ value=3,
1091
+ step=1,
1092
+ interactive=True,
1093
+ visible=False
1094
+ )
1095
+ with gr.Row():
1096
+ file_index3 = gr.Textbox(
1097
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
1098
+ value="",
1099
+ interactive=True,
1100
+ visible=False
1101
+ )
1102
+ file_index4 = gr.Dropdown(
1103
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
1104
+ choices=sorted(index_paths),
1105
+ interactive=True,
1106
+ visible=False
1107
+ )
1108
+ refresh_button.click(
1109
+ fn=lambda: change_choices()[1],
1110
+ inputs=[],
1111
+ outputs=file_index4,
1112
+ api_name="infer_refresh_batch",
1113
+ )
1114
+ # file_big_npy2 = gr.Textbox(
1115
+ # label=i18n("特征文件路径"),
1116
+ # value="E:\\codes\\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1117
+ # interactive=True,
1118
+ # )
1119
+ index_rate2 = gr.Slider(
1120
+ minimum=0,
1121
+ maximum=1,
1122
+ label=i18n("检索特征占比"),
1123
+ value=1,
1124
+ interactive=True,
1125
+ visible=False
1126
+ )
1127
+ with gr.Row():
1128
+ resample_sr1 = gr.Slider(
1129
+ minimum=0,
1130
+ maximum=48000,
1131
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
1132
+ value=0,
1133
+ step=1,
1134
+ interactive=True,
1135
+ visible=False
1136
+ )
1137
+ rms_mix_rate1 = gr.Slider(
1138
+ minimum=0,
1139
+ maximum=1,
1140
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
1141
+ value=0.21,
1142
+ interactive=True,
1143
+ )
1144
+ protect1 = gr.Slider(
1145
+ minimum=0,
1146
+ maximum=0.5,
1147
+ label=i18n(
1148
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
1149
+ ),
1150
+ value=0.33,
1151
+ step=0.01,
1152
+ interactive=True,
1153
+ )
1154
+ with gr.Row():
1155
+ dir_input = gr.Textbox(
1156
+ label=i18n("输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)"),
1157
+ value="./audios",
1158
+ )
1159
+ inputs = gr.File(
1160
+ file_count="multiple", label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹")
1161
+ )
1162
+ with gr.Row():
1163
+ format1 = gr.Radio(
1164
+ label=i18n("导出文件格式"),
1165
+ choices=["wav", "flac", "mp3", "m4a"],
1166
+ value="wav",
1167
+ interactive=True,
1168
+ )
1169
+ but1 = gr.Button(i18n("转换"), variant="primary")
1170
+ vc_output3 = gr.Textbox(label=i18n("输出信息"))
1171
+ but1.click(
1172
+ vc.vc_multi,
1173
+ [
1174
+ spk_item,
1175
+ dir_input,
1176
+ opt_input,
1177
+ inputs,
1178
+ vc_transform1,
1179
+ f0method1,
1180
+ file_index1,
1181
+ file_index2,
1182
+ # file_big_npy2,
1183
+ index_rate1,
1184
+ filter_radius1,
1185
+ resample_sr1,
1186
+ rms_mix_rate1,
1187
+ protect1,
1188
+ format1,
1189
+ ],
1190
+ [vc_output3],
1191
+ api_name="infer_convert_batch",
1192
+ )
1193
+ sid0.change(
1194
+ fn=vc.get_vc,
1195
+ inputs=[sid0, protect0, protect1],
1196
+ outputs=[spk_item, protect0, protect1, file_index2, file_index4],
1197
+ )
1198
+ with gr.TabItem("Download Model"):
1199
+ with gr.Row():
1200
+ url=gr.Textbox(label="Enter the URL to the Model:")
1201
+ with gr.Row():
1202
+ model = gr.Textbox(label="Name your model:")
1203
+ download_button=gr.Button("Download")
1204
+ with gr.Row():
1205
+ status_bar=gr.Textbox(label="")
1206
+ download_button.click(fn=download_from_url, inputs=[url, model], outputs=[status_bar])
1207
+ with gr.Row():
1208
+ gr.Markdown(
1209
+ """
1210
+ ❤️ If you use this and like it, help me keep it.❤️
1211
+ https://paypal.me/lesantillan
1212
+ """
1213
+ )
1214
+ with gr.TabItem(i18n("训练")):
1215
+ with gr.Row():
1216
+ with gr.Column():
1217
+ exp_dir1 = gr.Textbox(label=i18n("输入实验名"), value="My-Voice")
1218
+ np7 = gr.Slider(
1219
+ minimum=0,
1220
+ maximum=config.n_cpu,
1221
+ step=1,
1222
+ label=i18n("提取音高和处理数据使用的CPU进程数"),
1223
+ value=int(np.ceil(config.n_cpu / 1.5)),
1224
+ interactive=True,
1225
+ )
1226
+ sr2 = gr.Radio(
1227
+ label=i18n("目标采样率"),
1228
+ choices=["40k", "48k"],
1229
+ value="40k",
1230
+ interactive=True,
1231
+ visible=False
1232
+ )
1233
+ if_f0_3 = gr.Radio(
1234
+ label=i18n("模型是否带音高指导(唱歌一定要, 语音可以不要)"),
1235
+ choices=[True, False],
1236
+ value=True,
1237
+ interactive=True,
1238
+ visible=False
1239
+ )
1240
+ version19 = gr.Radio(
1241
+ label=i18n("版本"),
1242
+ choices=["v1", "v2"],
1243
+ value="v2",
1244
+ interactive=True,
1245
+ visible=False,
1246
+ )
1247
+ trainset_dir4 = gr.Textbox(
1248
+ label=i18n("输入训练文件夹路径"), value='./dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
1249
+ )
1250
+ easy_uploader = gr.Files(label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹"),file_types=['audio'])
1251
+ but1 = gr.Button(i18n("处理数据"), variant="primary")
1252
+ info1 = gr.Textbox(label=i18n("输出信息"), value="")
1253
+ easy_uploader.upload(fn=upload_to_dataset, inputs=[easy_uploader, trainset_dir4], outputs=[info1, trainset_dir4])
1254
+ gpus6 = gr.Textbox(
1255
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1256
+ value=gpus,
1257
+ interactive=True,
1258
+ visible=F0GPUVisible,
1259
+ )
1260
+ gpu_info9 = gr.Textbox(
1261
+ label=i18n("显卡信息"), value=gpu_info, visible=F0GPUVisible
1262
+ )
1263
+ spk_id5 = gr.Slider(
1264
+ minimum=0,
1265
+ maximum=4,
1266
+ step=1,
1267
+ label=i18n("请指定说话人id"),
1268
+ value=0,
1269
+ interactive=True,
1270
+ visible=False
1271
+ )
1272
+ but1.click(
1273
+ preprocess_dataset,
1274
+ [trainset_dir4, exp_dir1, sr2, np7],
1275
+ [info1],
1276
+ api_name="train_preprocess",
1277
+ )
1278
+ with gr.Column():
1279
+ f0method8 = gr.Radio(
1280
+ label=i18n(
1281
+ "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢,rmvpe效果最好且微吃CPU/GPU"
1282
+ ),
1283
+ choices=["pm", "harvest", "dio", "rmvpe", "rmvpe_gpu"],
1284
+ value="rmvpe_gpu",
1285
+ interactive=True,
1286
+ )
1287
+ gpus_rmvpe = gr.Textbox(
1288
+ label=i18n(
1289
+ "rmvpe卡号配置:以-分隔输入使用的不同进程卡号,例如0-0-1使用在卡0上跑2个进程并在卡1上跑1个进程"
1290
+ ),
1291
+ value="%s-%s" % (gpus, gpus),
1292
+ interactive=True,
1293
+ visible=F0GPUVisible,
1294
+ )
1295
+ but2 = gr.Button(i18n("特征提取"), variant="primary")
1296
+ info2 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1297
+ f0method8.change(
1298
+ fn=change_f0_method,
1299
+ inputs=[f0method8],
1300
+ outputs=[gpus_rmvpe],
1301
+ )
1302
+ but2.click(
1303
+ extract_f0_feature,
1304
+ [
1305
+ gpus6,
1306
+ np7,
1307
+ f0method8,
1308
+ if_f0_3,
1309
+ exp_dir1,
1310
+ version19,
1311
+ gpus_rmvpe,
1312
+ ],
1313
+ [info2],
1314
+ api_name="train_extract_f0_feature",
1315
+ )
1316
+ with gr.Column():
1317
+ total_epoch11 = gr.Slider(
1318
+ minimum=2,
1319
+ maximum=1000,
1320
+ step=1,
1321
+ label=i18n("总训练轮数total_epoch"),
1322
+ value=150,
1323
+ interactive=True,
1324
+ )
1325
+ gpus16 = gr.Textbox(
1326
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1327
+ value="0",
1328
+ interactive=True,
1329
+ visible=True
1330
+ )
1331
+ but3 = gr.Button(i18n("训练模型"), variant="primary")
1332
+ but4 = gr.Button(i18n("训练特征索引"), variant="primary")
1333
+ info3 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=10)
1334
+ with gr.Accordion(label=i18n("常规设置"), open=False):
1335
+ save_epoch10 = gr.Slider(
1336
+ minimum=1,
1337
+ maximum=50,
1338
+ step=1,
1339
+ label=i18n("保存频率save_every_epoch"),
1340
+ value=25,
1341
+ interactive=True,
1342
+ )
1343
+ batch_size12 = gr.Slider(
1344
+ minimum=1,
1345
+ maximum=40,
1346
+ step=1,
1347
+ label=i18n("每张显卡的batch_size"),
1348
+ value=default_batch_size,
1349
+ interactive=True,
1350
+ )
1351
+ if_save_latest13 = gr.Radio(
1352
+ label=i18n("是否仅保存最新的ckpt文件以节省硬盘空间"),
1353
+ choices=[i18n("是"), i18n("否")],
1354
+ value=i18n("是"),
1355
+ interactive=True,
1356
+ visible=False
1357
+ )
1358
+ if_cache_gpu17 = gr.Radio(
1359
+ label=i18n(
1360
+ "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速"
1361
+ ),
1362
+ choices=[i18n("是"), i18n("否")],
1363
+ value=i18n("否"),
1364
+ interactive=True,
1365
+ )
1366
+ if_save_every_weights18 = gr.Radio(
1367
+ label=i18n("是否在每次保存时间点将最终小模型保存至weights文件夹"),
1368
+ choices=[i18n("是"), i18n("否")],
1369
+ value=i18n("是"),
1370
+ interactive=True,
1371
+ )
1372
+ with gr.Row():
1373
+ download_model = gr.Button('5.Download Model')
1374
+ with gr.Row():
1375
+ model_files = gr.Files(label='Your Model and Index file can be downloaded here:')
1376
+ download_model.click(fn=download_model_files, inputs=[exp_dir1], outputs=[model_files, info3])
1377
+ with gr.Row():
1378
+ pretrained_G14 = gr.Textbox(
1379
+ label=i18n("加载预训练底模G路径"),
1380
+ value="assets/pretrained_v2/f0G40k.pth",
1381
+ interactive=True,
1382
+ visible=False
1383
+ )
1384
+ pretrained_D15 = gr.Textbox(
1385
+ label=i18n("加载预训练底模D路径"),
1386
+ value="assets/pretrained_v2/f0D40k.pth",
1387
+ interactive=True,
1388
+ visible=False
1389
+ )
1390
+ sr2.change(
1391
+ change_sr2,
1392
+ [sr2, if_f0_3, version19],
1393
+ [pretrained_G14, pretrained_D15],
1394
+ )
1395
+ version19.change(
1396
+ change_version19,
1397
+ [sr2, if_f0_3, version19],
1398
+ [pretrained_G14, pretrained_D15, sr2],
1399
+ )
1400
+ if_f0_3.change(
1401
+ change_f0,
1402
+ [if_f0_3, sr2, version19],
1403
+ [f0method8, pretrained_G14, pretrained_D15],
1404
+ )
1405
+ with gr.Row():
1406
+ but5 = gr.Button(i18n("一键训练"), variant="primary", visible=False)
1407
+ but3.click(
1408
+ click_train,
1409
+ [
1410
+ exp_dir1,
1411
+ sr2,
1412
+ if_f0_3,
1413
+ spk_id5,
1414
+ save_epoch10,
1415
+ total_epoch11,
1416
+ batch_size12,
1417
+ if_save_latest13,
1418
+ pretrained_G14,
1419
+ pretrained_D15,
1420
+ gpus16,
1421
+ if_cache_gpu17,
1422
+ if_save_every_weights18,
1423
+ version19,
1424
+ ],
1425
+ info3,
1426
+ api_name="train_start",
1427
+ )
1428
+ but4.click(train_index, [exp_dir1, version19], info3)
1429
+ but5.click(
1430
+ train1key,
1431
+ [
1432
+ exp_dir1,
1433
+ sr2,
1434
+ if_f0_3,
1435
+ trainset_dir4,
1436
+ spk_id5,
1437
+ np7,
1438
+ f0method8,
1439
+ save_epoch10,
1440
+ total_epoch11,
1441
+ batch_size12,
1442
+ if_save_latest13,
1443
+ pretrained_G14,
1444
+ pretrained_D15,
1445
+ gpus16,
1446
+ if_cache_gpu17,
1447
+ if_save_every_weights18,
1448
+ version19,
1449
+ gpus_rmvpe,
1450
+ ],
1451
+ info3,
1452
+ api_name="train_start_all",
1453
+ )
1454
+
1455
+ if config.iscolab:
1456
+ app.queue(concurrency_count=511, max_size=1022).launch(share=True)
1457
+ else:
1458
+ app.queue(concurrency_count=511, max_size=1022).launch(
1459
+ server_name="0.0.0.0",
1460
+ inbrowser=not config.noautoopen,
1461
+ server_port=config.listen_port,
1462
+ quiet=True,
1463
+ )
assets/hubert/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *
2
+ !.gitignore
assets/pretrained/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *
2
+ !.gitignore
assets/pretrained_v2/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *
2
+ !.gitignore
assets/rmvpe/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *
2
+ !.gitignore
assets/uvr5_weights/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *
2
+ !.gitignore
assets/weights/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *
2
+ !.gitignore
audios/somegirl.mp3 ADDED
Binary file (32.2 kB). View file
 
audios/someguy.mp3 ADDED
Binary file (24.9 kB). View file
 
audios/unachica.mp3 ADDED
Binary file (36.4 kB). View file
 
audios/unchico.mp3 ADDED
Binary file (35.9 kB). View file
 
configs/config.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "pth_path": "assets/weights/kikiV1.pth",
3
+ "index_path": "logs/kikiV1.index",
4
+ "sg_input_device": "VoiceMeeter Output (VB-Audio Vo (MME)",
5
+ "sg_output_device": "VoiceMeeter Aux Input (VB-Audio (MME)",
6
+ "threhold": -45.0,
7
+ "pitch": 12.0,
8
+ "index_rate": 0.0,
9
+ "rms_mix_rate": 0.0,
10
+ "block_time": 0.25,
11
+ "crossfade_length": 0.04,
12
+ "extra_time": 2.0,
13
+ "n_cpu": 6.0,
14
+ "f0method": "rmvpe"
15
+ }
configs/config.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import os
3
+ import sys
4
+ import json
5
+ from multiprocessing import cpu_count
6
+
7
+ import torch
8
+ try:
9
+ import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import
10
+ if torch.xpu.is_available():
11
+ from infer.modules.ipex import ipex_init
12
+ ipex_init()
13
+ except Exception:
14
+ pass
15
+ import logging
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ version_config_list = [
21
+ "v1/32k.json",
22
+ "v1/40k.json",
23
+ "v1/48k.json",
24
+ "v2/48k.json",
25
+ "v2/32k.json",
26
+ ]
27
+
28
+
29
+ def singleton_variable(func):
30
+ def wrapper(*args, **kwargs):
31
+ if not wrapper.instance:
32
+ wrapper.instance = func(*args, **kwargs)
33
+ return wrapper.instance
34
+
35
+ wrapper.instance = None
36
+ return wrapper
37
+
38
+
39
+ @singleton_variable
40
+ class Config:
41
+ def __init__(self):
42
+ self.device = "cuda:0"
43
+ self.is_half = True
44
+ self.n_cpu = 0
45
+ self.gpu_name = None
46
+ self.json_config = self.load_config_json()
47
+ self.gpu_mem = None
48
+ (
49
+ self.python_cmd,
50
+ self.listen_port,
51
+ self.iscolab,
52
+ self.noparallel,
53
+ self.noautoopen,
54
+ self.dml,
55
+ ) = self.arg_parse()
56
+ self.instead = ""
57
+ self.x_pad, self.x_query, self.x_center, self.x_max = self.device_config()
58
+
59
+ @staticmethod
60
+ def load_config_json() -> dict:
61
+ d = {}
62
+ for config_file in version_config_list:
63
+ with open(f"configs/{config_file}", "r") as f:
64
+ d[config_file] = json.load(f)
65
+ return d
66
+
67
+ @staticmethod
68
+ def arg_parse() -> tuple:
69
+ exe = sys.executable or "python"
70
+ parser = argparse.ArgumentParser()
71
+ parser.add_argument("--port", type=int, default=7865, help="Listen port")
72
+ parser.add_argument("--pycmd", type=str, default=exe, help="Python command")
73
+ parser.add_argument("--colab", action="store_true", help="Launch in colab")
74
+ parser.add_argument(
75
+ "--noparallel", action="store_true", help="Disable parallel processing"
76
+ )
77
+ parser.add_argument(
78
+ "--noautoopen",
79
+ action="store_true",
80
+ help="Do not open in browser automatically",
81
+ )
82
+ parser.add_argument(
83
+ "--dml",
84
+ action="store_true",
85
+ help="torch_dml",
86
+ )
87
+ cmd_opts = parser.parse_args()
88
+
89
+ cmd_opts.port = cmd_opts.port if 0 <= cmd_opts.port <= 65535 else 7865
90
+
91
+ return (
92
+ cmd_opts.pycmd,
93
+ cmd_opts.port,
94
+ cmd_opts.colab,
95
+ cmd_opts.noparallel,
96
+ cmd_opts.noautoopen,
97
+ cmd_opts.dml,
98
+ )
99
+
100
+ # has_mps is only available in nightly pytorch (for now) and MasOS 12.3+.
101
+ # check `getattr` and try it for compatibility
102
+ @staticmethod
103
+ def has_mps() -> bool:
104
+ if not torch.backends.mps.is_available():
105
+ return False
106
+ try:
107
+ torch.zeros(1).to(torch.device("mps"))
108
+ return True
109
+ except Exception:
110
+ return False
111
+
112
+ @staticmethod
113
+ def has_xpu() -> bool:
114
+ if hasattr(torch, "xpu") and torch.xpu.is_available():
115
+ return True
116
+ else:
117
+ return False
118
+
119
+ def use_fp32_config(self):
120
+ for config_file in version_config_list:
121
+ self.json_config[config_file]["train"]["fp16_run"] = False
122
+
123
+ def device_config(self) -> tuple:
124
+ if torch.cuda.is_available():
125
+ if self.has_xpu():
126
+ self.device = self.instead = "xpu:0"
127
+ self.is_half = True
128
+ i_device = int(self.device.split(":")[-1])
129
+ self.gpu_name = torch.cuda.get_device_name(i_device)
130
+ if (
131
+ ("16" in self.gpu_name and "V100" not in self.gpu_name.upper())
132
+ or "P40" in self.gpu_name.upper()
133
+ or "P10" in self.gpu_name.upper()
134
+ or "1060" in self.gpu_name
135
+ or "1070" in self.gpu_name
136
+ or "1080" in self.gpu_name
137
+ ):
138
+ logger.info("Found GPU %s, force to fp32", self.gpu_name)
139
+ self.is_half = False
140
+ self.use_fp32_config()
141
+ else:
142
+ logger.info("Found GPU %s", self.gpu_name)
143
+ self.gpu_mem = int(
144
+ torch.cuda.get_device_properties(i_device).total_memory
145
+ / 1024
146
+ / 1024
147
+ / 1024
148
+ + 0.4
149
+ )
150
+ if self.gpu_mem <= 4:
151
+ with open("infer/modules/train/preprocess.py", "r") as f:
152
+ strr = f.read().replace("3.7", "3.0")
153
+ with open("infer/modules/train/preprocess.py", "w") as f:
154
+ f.write(strr)
155
+ elif self.has_mps():
156
+ logger.info("No supported Nvidia GPU found")
157
+ self.device = self.instead = "mps"
158
+ self.is_half = False
159
+ self.use_fp32_config()
160
+ else:
161
+ logger.info("No supported Nvidia GPU found")
162
+ self.device = self.instead = "cpu"
163
+ self.is_half = False
164
+ self.use_fp32_config()
165
+
166
+ if self.n_cpu == 0:
167
+ self.n_cpu = cpu_count()
168
+
169
+ if self.is_half:
170
+ # 6G显存配置
171
+ x_pad = 3
172
+ x_query = 10
173
+ x_center = 60
174
+ x_max = 65
175
+ else:
176
+ # 5G显存配置
177
+ x_pad = 1
178
+ x_query = 6
179
+ x_center = 38
180
+ x_max = 41
181
+
182
+ if self.gpu_mem is not None and self.gpu_mem <= 4:
183
+ x_pad = 1
184
+ x_query = 5
185
+ x_center = 30
186
+ x_max = 32
187
+ if self.dml:
188
+ logger.info("Use DirectML instead")
189
+ if (
190
+ os.path.exists(
191
+ "runtime\Lib\site-packages\onnxruntime\capi\DirectML.dll"
192
+ )
193
+ == False
194
+ ):
195
+ try:
196
+ os.rename(
197
+ "runtime\Lib\site-packages\onnxruntime",
198
+ "runtime\Lib\site-packages\onnxruntime-cuda",
199
+ )
200
+ except:
201
+ pass
202
+ try:
203
+ os.rename(
204
+ "runtime\Lib\site-packages\onnxruntime-dml",
205
+ "runtime\Lib\site-packages\onnxruntime",
206
+ )
207
+ except:
208
+ pass
209
+ # if self.device != "cpu":
210
+ import torch_directml
211
+
212
+ self.device = torch_directml.device(torch_directml.default_device())
213
+ self.is_half = False
214
+ else:
215
+ if self.instead:
216
+ logger.info(f"Use {self.instead} instead")
217
+ if (
218
+ os.path.exists(
219
+ "runtime\Lib\site-packages\onnxruntime\capi\onnxruntime_providers_cuda.dll"
220
+ )
221
+ == False
222
+ ):
223
+ try:
224
+ os.rename(
225
+ "runtime\Lib\site-packages\onnxruntime",
226
+ "runtime\Lib\site-packages\onnxruntime-dml",
227
+ )
228
+ except:
229
+ pass
230
+ try:
231
+ os.rename(
232
+ "runtime\Lib\site-packages\onnxruntime-cuda",
233
+ "runtime\Lib\site-packages\onnxruntime",
234
+ )
235
+ except:
236
+ pass
237
+ return x_pad, x_query, x_center, x_max
configs/v1/32k.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "train": {
3
+ "log_interval": 200,
4
+ "seed": 1234,
5
+ "epochs": 20000,
6
+ "learning_rate": 1e-4,
7
+ "betas": [0.8, 0.99],
8
+ "eps": 1e-9,
9
+ "batch_size": 4,
10
+ "fp16_run": true,
11
+ "lr_decay": 0.999875,
12
+ "segment_size": 12800,
13
+ "init_lr_ratio": 1,
14
+ "warmup_epochs": 0,
15
+ "c_mel": 45,
16
+ "c_kl": 1.0
17
+ },
18
+ "data": {
19
+ "max_wav_value": 32768.0,
20
+ "sampling_rate": 32000,
21
+ "filter_length": 1024,
22
+ "hop_length": 320,
23
+ "win_length": 1024,
24
+ "n_mel_channels": 80,
25
+ "mel_fmin": 0.0,
26
+ "mel_fmax": null
27
+ },
28
+ "model": {
29
+ "inter_channels": 192,
30
+ "hidden_channels": 192,
31
+ "filter_channels": 768,
32
+ "n_heads": 2,
33
+ "n_layers": 6,
34
+ "kernel_size": 3,
35
+ "p_dropout": 0,
36
+ "resblock": "1",
37
+ "resblock_kernel_sizes": [3,7,11],
38
+ "resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
39
+ "upsample_rates": [10,4,2,2,2],
40
+ "upsample_initial_channel": 512,
41
+ "upsample_kernel_sizes": [16,16,4,4,4],
42
+ "use_spectral_norm": false,
43
+ "gin_channels": 256,
44
+ "spk_embed_dim": 109
45
+ }
46
+ }
configs/v1/40k.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "train": {
3
+ "log_interval": 200,
4
+ "seed": 1234,
5
+ "epochs": 20000,
6
+ "learning_rate": 1e-4,
7
+ "betas": [0.8, 0.99],
8
+ "eps": 1e-9,
9
+ "batch_size": 4,
10
+ "fp16_run": true,
11
+ "lr_decay": 0.999875,
12
+ "segment_size": 12800,
13
+ "init_lr_ratio": 1,
14
+ "warmup_epochs": 0,
15
+ "c_mel": 45,
16
+ "c_kl": 1.0
17
+ },
18
+ "data": {
19
+ "max_wav_value": 32768.0,
20
+ "sampling_rate": 40000,
21
+ "filter_length": 2048,
22
+ "hop_length": 400,
23
+ "win_length": 2048,
24
+ "n_mel_channels": 125,
25
+ "mel_fmin": 0.0,
26
+ "mel_fmax": null
27
+ },
28
+ "model": {
29
+ "inter_channels": 192,
30
+ "hidden_channels": 192,
31
+ "filter_channels": 768,
32
+ "n_heads": 2,
33
+ "n_layers": 6,
34
+ "kernel_size": 3,
35
+ "p_dropout": 0,
36
+ "resblock": "1",
37
+ "resblock_kernel_sizes": [3,7,11],
38
+ "resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
39
+ "upsample_rates": [10,10,2,2],
40
+ "upsample_initial_channel": 512,
41
+ "upsample_kernel_sizes": [16,16,4,4],
42
+ "use_spectral_norm": false,
43
+ "gin_channels": 256,
44
+ "spk_embed_dim": 109
45
+ }
46
+ }
configs/v1/48k.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "train": {
3
+ "log_interval": 200,
4
+ "seed": 1234,
5
+ "epochs": 20000,
6
+ "learning_rate": 1e-4,
7
+ "betas": [0.8, 0.99],
8
+ "eps": 1e-9,
9
+ "batch_size": 4,
10
+ "fp16_run": true,
11
+ "lr_decay": 0.999875,
12
+ "segment_size": 11520,
13
+ "init_lr_ratio": 1,
14
+ "warmup_epochs": 0,
15
+ "c_mel": 45,
16
+ "c_kl": 1.0
17
+ },
18
+ "data": {
19
+ "max_wav_value": 32768.0,
20
+ "sampling_rate": 48000,
21
+ "filter_length": 2048,
22
+ "hop_length": 480,
23
+ "win_length": 2048,
24
+ "n_mel_channels": 128,
25
+ "mel_fmin": 0.0,
26
+ "mel_fmax": null
27
+ },
28
+ "model": {
29
+ "inter_channels": 192,
30
+ "hidden_channels": 192,
31
+ "filter_channels": 768,
32
+ "n_heads": 2,
33
+ "n_layers": 6,
34
+ "kernel_size": 3,
35
+ "p_dropout": 0,
36
+ "resblock": "1",
37
+ "resblock_kernel_sizes": [3,7,11],
38
+ "resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
39
+ "upsample_rates": [10,6,2,2,2],
40
+ "upsample_initial_channel": 512,
41
+ "upsample_kernel_sizes": [16,16,4,4,4],
42
+ "use_spectral_norm": false,
43
+ "gin_channels": 256,
44
+ "spk_embed_dim": 109
45
+ }
46
+ }
configs/v2/32k.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "train": {
3
+ "log_interval": 200,
4
+ "seed": 1234,
5
+ "epochs": 20000,
6
+ "learning_rate": 1e-4,
7
+ "betas": [0.8, 0.99],
8
+ "eps": 1e-9,
9
+ "batch_size": 4,
10
+ "fp16_run": true,
11
+ "lr_decay": 0.999875,
12
+ "segment_size": 12800,
13
+ "init_lr_ratio": 1,
14
+ "warmup_epochs": 0,
15
+ "c_mel": 45,
16
+ "c_kl": 1.0
17
+ },
18
+ "data": {
19
+ "max_wav_value": 32768.0,
20
+ "sampling_rate": 32000,
21
+ "filter_length": 1024,
22
+ "hop_length": 320,
23
+ "win_length": 1024,
24
+ "n_mel_channels": 80,
25
+ "mel_fmin": 0.0,
26
+ "mel_fmax": null
27
+ },
28
+ "model": {
29
+ "inter_channels": 192,
30
+ "hidden_channels": 192,
31
+ "filter_channels": 768,
32
+ "n_heads": 2,
33
+ "n_layers": 6,
34
+ "kernel_size": 3,
35
+ "p_dropout": 0,
36
+ "resblock": "1",
37
+ "resblock_kernel_sizes": [3,7,11],
38
+ "resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
39
+ "upsample_rates": [10,8,2,2],
40
+ "upsample_initial_channel": 512,
41
+ "upsample_kernel_sizes": [20,16,4,4],
42
+ "use_spectral_norm": false,
43
+ "gin_channels": 256,
44
+ "spk_embed_dim": 109
45
+ }
46
+ }
configs/v2/48k.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "train": {
3
+ "log_interval": 200,
4
+ "seed": 1234,
5
+ "epochs": 20000,
6
+ "learning_rate": 1e-4,
7
+ "betas": [0.8, 0.99],
8
+ "eps": 1e-9,
9
+ "batch_size": 4,
10
+ "fp16_run": true,
11
+ "lr_decay": 0.999875,
12
+ "segment_size": 17280,
13
+ "init_lr_ratio": 1,
14
+ "warmup_epochs": 0,
15
+ "c_mel": 45,
16
+ "c_kl": 1.0
17
+ },
18
+ "data": {
19
+ "max_wav_value": 32768.0,
20
+ "sampling_rate": 48000,
21
+ "filter_length": 2048,
22
+ "hop_length": 480,
23
+ "win_length": 2048,
24
+ "n_mel_channels": 128,
25
+ "mel_fmin": 0.0,
26
+ "mel_fmax": null
27
+ },
28
+ "model": {
29
+ "inter_channels": 192,
30
+ "hidden_channels": 192,
31
+ "filter_channels": 768,
32
+ "n_heads": 2,
33
+ "n_layers": 6,
34
+ "kernel_size": 3,
35
+ "p_dropout": 0,
36
+ "resblock": "1",
37
+ "resblock_kernel_sizes": [3,7,11],
38
+ "resblock_dilation_sizes": [[1,3,5], [1,3,5], [1,3,5]],
39
+ "upsample_rates": [12,10,2,2],
40
+ "upsample_initial_channel": 512,
41
+ "upsample_kernel_sizes": [24,20,4,4],
42
+ "use_spectral_norm": false,
43
+ "gin_channels": 256,
44
+ "spk_embed_dim": 109
45
+ }
46
+ }
docker-compose.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.8"
2
+ services:
3
+ rvc:
4
+ build:
5
+ context: .
6
+ dockerfile: Dockerfile
7
+ container_name: rvc
8
+ volumes:
9
+ - ./weights:/app/assets/weights
10
+ - ./opt:/app/opt
11
+ # - ./dataset:/app/dataset # you can use this folder in order to provide your dataset for model training
12
+ ports:
13
+ - 7865:7865
docs/cn/Changelog_CN.md ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### 20230813更新
2
+ 1-常规bug修复
3
+ - 保存频率总轮数最低改为1 总轮数最低改为2
4
+ - 修复无pretrain模型训练报错
5
+ - 增加伴奏人声分离完毕清理显存
6
+ - faiss保存路径绝对路径改为相对路径
7
+ - 支持路径包含空格(训练集路径+实验名称均支持,不再会报错)
8
+ - filelist取消强制utf8编码
9
+ - 解决实时变声中开启索引导致的CPU极大占用问题
10
+
11
+ 2-重点更新
12
+ - 训练出当前最强开源人声音高提取模型RMVPE,并用于RVC的训练、离线/实时推理,支持pytorch/onnx/DirectML
13
+ - 通过pytorch-dml支持A卡和I卡的
14
+ (1)实时变声(2)推理(3)人声伴奏分离(4)训练暂未支持,会切换至CPU训练;通过onnx_dml支持rmvpe_gpu的推理
15
+
16
+ ### 20230618更新
17
+ - v2增加32k和48k两个新预训练模型
18
+ - 修复非f0模型推理报错
19
+ - 对于超过一小时的训练集的索引建立环节,自动kmeans缩小特征处理以加速索引训练、加入和查询
20
+ - 附送一个人声转吉他玩具仓库
21
+ - 数据处理剔除异常值切片
22
+ - onnx导出选项卡
23
+
24
+ 失败的实验:
25
+ - ~~特征检索增加时序维度:寄,没啥效果~~
26
+ - ~~特征检索增加PCAR降维可选项:寄,数据大用kmeans缩小数据量,数据小降维操作耗时比省下的匹配耗时还多~~
27
+ - ~~支持onnx推理(附带仅推理的小压缩包):寄,生成nsf还是需要pytorch~~
28
+ - ~~训练时在音高、gender、eq、噪声等方面对输入进行随机增强:寄,没啥效果~~
29
+ - ~~接入小型声码器调研:寄,效果变差~~
30
+
31
+ todolist:
32
+ - ~~训练集音高识别支持crepe:已经被RMVPE取代,不需要~~
33
+ - ~~多进程harvest推理:已经被RMVPE取代,不需要~~
34
+ - ~~crepe的精度支持和RVC-config同步:已经被RMVPE取代,不需要。支持这个还要同步torchcrepe的库,麻烦~~
35
+ - 对接F0编辑器
36
+
37
+
38
+ ### 20230528更新
39
+ - 增加v2的jupyter notebook,韩文changelog,增加一些环境依赖
40
+ - 增加呼吸、清辅音、齿音保护模式
41
+ - 支持crepe-full推理
42
+ - UVR5人声伴奏分离加上3个去延迟模型和MDX-Net去混响模型,增加HP3人声提取模型
43
+ - 索引名称增加版本和实验名称
44
+ - 人声伴奏分离、推理批量导出增加音频导出格式选项
45
+ - 废弃32k模型的训练
46
+
47
+ ### 20230513更新
48
+ - 清除一键包内部老版本runtime内残留的lib.infer_pack和uvr5_pack
49
+ - 修复训练集预处理伪多进程的bug
50
+ - 增加harvest识别音高可选通过中值滤波削弱哑音现象,可调整中值滤波半径
51
+ - 导出音频增加后处理重采样
52
+ - 训练n_cpu进程数从"仅调整f0提取"改为"调整数据预处理和f0提取"
53
+ - 自动检测logs文件夹下的index路径,提供下拉列表功能
54
+ - tab页增加"常见问题解答"(也可参考github-rvc-wiki)
55
+ - 相同路径的输入音频推理增加了音高缓存(用途:使用harvest音高提取,整个pipeline会经历漫长且重复的音高提取过程,如果不使用缓存,实验不同音色、索引、音高中值滤波半径参数的用户在第一次测试后的等待结果会非常痛苦)
56
+
57
+ ### 20230514更新
58
+ - 音量包络对齐输入混合(可以缓解“输入静音输出小幅度噪声”的问题。如果输入音频背景底噪大则不建议开启,默认不开启(值为1可视为不开启))
59
+ - 支持按照指定频率保存提取的小模型(假如你想尝试不同epoch下的推理效果,但是不想保存所有大checkpoint并且每次都要ckpt手工处理提取小模型,这项功能会非常实用)
60
+ - 通过设置环境变量解决服务端开了系统全局代理导致浏览器连接错误的问题
61
+ - 支持v2预训练模型(目前只公开了40k版本进行测试,另外2个采样率还没有训练完全)
62
+ - 推理前限制超过1的过大音量
63
+ - 微调数据预处理参数
64
+
65
+
66
+ ### 20230409更新
67
+ - 修正训练参数,提升显卡平均利用率,A100最高从25%提升至90%左右,V100:50%->90%左右,2060S:60%->85%左右,P40:25%->95%左右,训练速度显著提升
68
+ - 修正参数:总batch_size改为每张卡的batch_size
69
+ - 修正total_epoch:最大限制100解锁至1000;默认10提升至默认20
70
+ - 修复ckpt提取识别是否带音高错误导致推理异常的问题
71
+ - 修复分布式训练每个rank都保存一次ckpt的问题
72
+ - 特征提取进行nan特征过滤
73
+ - 修复静音输入输出随机辅音or噪声的问题(老版模型需要重做训练集重训)
74
+
75
+ ### 20230416更新
76
+ - 新增本地实时变声迷你GUI,双击go-realtime-gui.bat启动
77
+ - 训练推理均对<50Hz的频段进行滤波过滤
78
+ - 训练推理音高提取pyworld最低音高从默认80下降至50,50-80hz间的男声低音不会哑
79
+ - WebUI支持根据系统区域变更语言(现支持en_US,ja_JP,zh_CN,zh_HK,zh_SG,zh_TW,不支持的默认en_US)
80
+ - 修正部分显卡识别(例如V100-16G识别失败,P4识别失败)
81
+
82
+ ### 20230428更新
83
+ - 升级faiss索引设置,速度更快,质量更高
84
+ - 取消total_npy依赖,后续分享模型不再需要填写total_npy
85
+ - 解锁16系限制。4G显存GPU给到4G的推理设置。
86
+ - 修复部分音频格式下UVR5人声伴奏分离的bug
87
+ - 实时变声迷你gui增加对非40k与不懈怠音高模型的支持
88
+
89
+ ### 后续计划:
90
+ 功能:
91
+ - 支持多人训练选项卡(至多4人)
92
+
93
+ 底模:
94
+ - 收集呼吸wav加入训练集修正呼吸变声电音的问题
95
+ - 我们正在训练增加了歌声训练集的底模,未来会公开
96
+
docs/cn/faq.md ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Q1:ffmpeg error/utf8 error.
2
+
3
+ 大概率不是ffmpeg问题,而是音频路径问题;<br>
4
+ ffmpeg读取路径带空格、()等特殊符号,可能出现ffmpeg error;训练集音频带中文路径,在写入filelist.txt的时候可能出现utf8 error;<br>
5
+
6
+ ## Q2:一键训练结束没有索引
7
+
8
+ 显示"Training is done. The program is closed."则模型训练成功,后续紧邻的报错是假的;<br>
9
+
10
+ 一键训练结束完成没有added开头的索引文件,可能是因为训练集太大卡住了添加索引的步骤;已通过批处理add索引解决内存add索引对内存需求过大的问题。临时可尝试再次点击"训练索引"按钮。<br>
11
+
12
+ ## Q3:训练结束推理没看到训练集的音色
13
+ 点刷新音色再看看,如果还没有看看训练有没有报错,控制台和webui的截图,logs/实验名下的log,都可以发给开发者看看。<br>
14
+
15
+ ## Q4:如何分享模型
16
+   rvc_root/logs/实验名 下面存储的pth不是用来分享模型用来推理的,而是为了存储实验状态供复现,以及继续训练用的。用来分享的模型应该是weights文件夹下大小为60+MB的pth文件;<br>
17
+   后续将把weights/exp_name.pth和logs/exp_name/added_xxx.index合并打包成weights/exp_name.zip省去填写index的步骤,那么zip文件用来分享,不要分享pth文件,除非是想换机器继续训练;<br>
18
+   如果你把logs文件夹下的几百MB的pth文件复制/分享到weights文件夹下强行用于推理,可能会出现f0,tgt_sr等各种key不存在的报错。你需要用ckpt选项卡最下面,手工或自动(本地logs下如果能找到相关信息则会自动)选择是否携带音高、目标音频采样率的选项后进行ckpt小模型提取(输入路径填G开头的那个),提取完在weights文件夹下会出现60+MB的pth文件,刷新音色后可以选择使用。<br>
19
+
20
+ ## Q5:Connection Error.
21
+ 也许你关闭了控制台(黑色窗口)。<br>
22
+
23
+ ## Q6:WebUI弹出Expecting value: line 1 column 1 (char 0).
24
+ 请关闭系统局域网代理/全局代理。<br>
25
+
26
+ 这个不仅是客户端的代理,也包括服务端的代理(例如你使用autodl设置了http_proxy和https_proxy学术加速,使用时也需要unset关掉)<br>
27
+
28
+ ## Q7:不用WebUI如何通过命令训练推理
29
+ 训练脚本:<br>
30
+ 可先跑通WebUI,消息窗内会显示数据集处理和训练用命令行;<br>
31
+
32
+ 推理脚本:<br>
33
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/myinfer.py<br>
34
+
35
+ 例子:<br>
36
+
37
+ 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>
38
+
39
+ f0up_key=sys.argv[1]<br>
40
+ input_path=sys.argv[2]<br>
41
+ index_path=sys.argv[3]<br>
42
+ f0method=sys.argv[4]#harvest or pm<br>
43
+ opt_path=sys.argv[5]<br>
44
+ model_path=sys.argv[6]<br>
45
+ index_rate=float(sys.argv[7])<br>
46
+ device=sys.argv[8]<br>
47
+ is_half=bool(sys.argv[9])<br>
48
+
49
+ ## Q8:Cuda error/Cuda out of memory.
50
+ 小概率是cuda配置问题、设备不支持;大概率是显存不够(out of memory);<br>
51
+
52
+ 训练的话缩小batch size(如果缩小到1还不够只能更换显卡训练),推理的话酌情缩小config.py结尾的x_pad,x_query,x_center,x_max。4G以下显存(例如1060(3G)和各种2G显卡)可以直接放弃,4G显存显卡还有救。<br>
53
+
54
+ ## Q9:total_epoch调多少比较好
55
+
56
+ 如果训练集音质差底噪大,20~30足够了,调太高,底模音质无法带高你的低音质训练集<br>
57
+ 如果训练集音质高底噪低时长多,可以调高,200是ok的(训练速度很快,既然你有条件准备高音质训练集,显卡想必条件也不错,肯定不在乎多一些训练时间)<br>
58
+
59
+ ## Q10:需要多少训练集时长
60
+   推荐10min至50min<br>
61
+   保证音质高底噪低的情况下,如果有个人特色的音色统一,则多多益善<br>
62
+   高水平的训练集(精简+音色有特色),5min至10min也是ok的,仓库作者本人就经常这么玩<br>
63
+   也有人拿1min至2min的数据来训练并且训练成功的,但是成功经验是其他人不可复现的,不太具备参考价值。这要求训练集音色特色非常明显(比如说高频气声较明显的萝莉少女音),且音质高;<br>
64
+   1min以下时长数据目前没见有人尝试(成功)过。不建议进行这种鬼畜行为。<br>
65
+
66
+ ## Q11:index rate干嘛用的,怎么调(科普)
67
+   如果底模和推理源的音质高于训练集的音质,他们可以带高推理结果的音质,但代价可能是音色往底模/推理源的音色靠,这种现象叫做"音色泄露";<br>
68
+   index rate用来削减/解决音色泄露问题。调到1,则理论上不存在推理源的音色泄露问题,但音质更倾向于训练集。如果训练集音质比推理源低,则index rate调高可能降低音质。调到0,则不具备利用检索混合来保护训练集音色的效果;<br>
69
+   如果训练集优质时长多,可调高total_epoch,此时模型本身不太会引用推理源和底模的音色,很少存在"音色泄露"问题,此时index_rate不重要,你甚至可以不建立/分享index索引文件。<br>
70
+
71
+ ## Q11:推理怎么选gpu
72
+ config.py文件里device cuda:后面选择卡号;<br>
73
+ 卡号和显卡的映射关系,在训练选项卡的显卡信息栏里能看到。<br>
74
+
75
+ ## Q12:如何推理训练中间保存的pth
76
+ 通过ckpt选项卡最下面提取小模型。<br>
77
+
78
+
79
+ ## Q13:如何中断和继续训练
80
+ 现阶段只能关闭WebUI控制台双击go-web.bat重启程序。网页参数也要刷新重新填写;<br>
81
+ 继续训练:相同网页参数点训练模型,就会接着上次的checkpoint继续训练。<br>
82
+
83
+ ## Q14:训练时出现文件页面/内存error
84
+ 进程开太多了,内存炸了。你可能可以通过如下方式解决<br>
85
+ 1、"提取音高和处理数据使用的CPU进程数" 酌情拉低;<br>
86
+ 2、训练集音频手工切一下,不要太长。<br>
87
+
88
+
89
+ ## Q15:如何中途加数据训练
90
+ 1、所有数据新建一个实验名;<br>
91
+ 2、拷贝上一次的最新的那个G和D文件(或者你想基于哪个中间ckpt训练,也可以拷贝中间的)到新实验名;下<br>
92
+ 3、一键训练新实验名,他会继续上一次的最新进度训练。<br>
93
+
94
+ ## Q16: error about llvmlite.dll
95
+
96
+ OSError: Could not load shared object file: llvmlite.dll
97
+
98
+ FileNotFoundError: Could not find module lib\site-packages\llvmlite\binding\llvmlite.dll (or one of its dependencies). Try using the full path with constructor syntax.
99
+
100
+ win平台会报这个错,装上https://aka.ms/vs/17/release/vc_redist.x64.exe这个再重启WebUI就好了。
101
+
102
+ ## Q17: RuntimeError: The expanded size of the tensor (17280) must match the existing size (0) at non-singleton dimension 1. Target sizes: [1, 17280]. Tensor sizes: [0]
103
+
104
+ wavs16k文件夹下,找到文件大小显著比其他都小的一些音频文件,删掉,点击训练模型,就不会报错了,不过由于一键流程中断了你训练完模型还要点训练索引。
105
+
106
+ ## Q18: RuntimeError: The size of tensor a (24) must match the size of tensor b (16) at non-singleton dimension 2
107
+
108
+ 不要中途变更采样率继续训练。如果一定要变更,应更换实验名从头训练。当然你也可以把上次提取的音高和特征(0/1/2/2b folders)拷贝过去加速训练流程。
docs/en/Changelog_EN.md ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### 2023-08-13
2
+ 1-Regular bug fix
3
+ - Change the minimum total epoch number to 1, and change the minimum total epoch number to 2
4
+ - Fix training errors of not using pre-train models
5
+ - After accompaniment vocals separation, clear graphics memory
6
+ - Change faiss save path absolute path to relative path
7
+ - Support path containing spaces (both training set path and experiment name are supported, and errors will no longer be reported)
8
+ - Filelist cancels mandatory utf8 encoding
9
+ - Solve the CPU consumption problem caused by faiss searching during real-time voice changes
10
+
11
+ 2-Key updates
12
+ - Train the current strongest open-source vocal pitch extraction model RMVPE, and use it for RVC training, offline/real-time inference, supporting PyTorch/Onnx/DirectML
13
+ - Support for AMD and Intel graphics cards through Pytorch_DML
14
+
15
+ (1) Real time voice change (2) Inference (3) Separation of vocal accompaniment (4) Training not currently supported, will switch to CPU training; supports RMVPE inference of gpu by Onnx_Dml
16
+
17
+
18
+ ### 2023-06-18
19
+ - New pretrained v2 models: 32k and 48k
20
+ - Fix non-f0 model inference errors
21
+ - 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.
22
+ - Provide a toy vocal2guitar huggingface space
23
+ - Auto delete outlier short cut training-set audios
24
+ - Onnx export tab
25
+
26
+ Failed experiments:
27
+ - ~~Feature retrieval: add temporal feature retrieval: not effective~~
28
+ - ~~Feature retrieval: add PCAR dimensionality reduction: searching is even slower~~
29
+ - ~~Random data augmentation when training: not effective~~
30
+
31
+ todolist:
32
+ - ~~Vocos-RVC (tiny vocoder): not effective~~
33
+ - ~~Crepe support for training:replaced by RMVPE~~
34
+ - ~~Half precision crepe inference:replaced by RMVPE. And hard to achive.~~
35
+ - F0 editor support
36
+
37
+ ### 2023-05-28
38
+ - Add v2 jupyter notebook, korean changelog, fix some environment requirments
39
+ - Add voiceless consonant and breath protection mode
40
+ - Support crepe-full pitch detect
41
+ - UVR5 vocal separation: support dereverb models and de-echo models
42
+ - Add experiment name and version on the name of index
43
+ - Support users to manually select export format of output audios when batch voice conversion processing and UVR5 vocal separation
44
+ - v1 32k model training is no more supported
45
+
46
+ ### 2023-05-13
47
+ - Clear the redundant codes in the old version of runtime in the one-click-package: lib.infer_pack and uvr5_pack
48
+ - Fix pseudo multiprocessing bug in training set preprocessing
49
+ - Adding median filtering radius adjustment for harvest pitch recognize algorithm
50
+ - Support post processing resampling for exporting audio
51
+ - Multi processing "n_cpu" setting for training is changed from "f0 extraction" to "data preprocessing and f0 extraction"
52
+ - Automatically detect the index paths under the logs folder and provide a drop-down list function
53
+ - Add "Frequently Asked Questions and Answers" on the tab page (you can also refer to github RVC wiki)
54
+ - 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)
55
+
56
+ ### 2023-05-14
57
+ - 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)
58
+ - 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)
59
+ - Resolve the issue of "connection errors" caused by the server's global proxy by setting environment variables
60
+ - 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)
61
+ - Limit excessive volume exceeding 1 before inference
62
+ - Slightly adjusted the settings of training-set preprocessing
63
+
64
+
65
+ #######################
66
+
67
+ History changelogs:
68
+
69
+ ### 2023-04-09
70
+ - 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
71
+ - Changed parameter: total batch_size is now per GPU batch_size
72
+ - Changed total_epoch: maximum limit increased from 100 to 1000; default increased from 10 to 20
73
+ - Fixed issue of ckpt extraction recognizing pitch incorrectly, causing abnormal inference
74
+ - Fixed issue of distributed training saving ckpt for each rank
75
+ - Applied nan feature filtering for feature extraction
76
+ - Fixed issue with silent input/output producing random consonants or noise (old models need to retrain with a new dataset)
77
+
78
+ ### 2023-04-16 Update
79
+ - Added local real-time voice changing mini-GUI, start by double-clicking go-realtime-gui.bat
80
+ - Applied filtering for frequency bands below 50Hz during training and inference
81
+ - 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
82
+ - 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)
83
+ - Fixed recognition of some GPUs (e.g., V100-16G recognition failure, P4 recognition failure)
84
+
85
+ ### 2023-04-28 Update
86
+ - Upgraded faiss index settings for faster speed and higher quality
87
+ - Removed dependency on total_npy; future model sharing will not require total_npy input
88
+ - Unlocked restrictions for the 16-series GPUs, providing 4GB inference settings for 4GB VRAM GPUs
89
+ - Fixed bug in UVR5 vocal accompaniment separation for certain audio formats
90
+ - Real-time voice changing mini-GUI now supports non-40k and non-lazy pitch models
91
+
92
+ ### Future Plans:
93
+ Features:
94
+ - Add option: extract small models for each epoch save
95
+ - Add option: export additional mp3 to the specified path during inference
96
+ - Support multi-person training tab (up to 4 people)
97
+
98
+ Base model:
99
+ - Collect breathing wav files to add to the training dataset to fix the issue of distorted breath sounds
100
+ - We are currently training a base model with an extended singing dataset, which will be released in the future
docs/en/README.en.md ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+
3
+ <h1>Retrieval-based-Voice-Conversion-WebUI</h1>
4
+ An easy-to-use Voice Conversion framework based on VITS.<br><br>
5
+
6
+ [![madewithlove](https://img.shields.io/badge/made_with-%E2%9D%A4-red?style=for-the-badge&labelColor=orange
7
+ )](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
8
+
9
+ <img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
10
+
11
+ [![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb)
12
+ [![Licence](https://img.shields.io/github/license/RVC-Project/Retrieval-based-Voice-Conversion-WebUI?style=for-the-badge)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/LICENSE)
13
+ [![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)
14
+
15
+ [![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk)
16
+
17
+ </div>
18
+
19
+ ------
20
+ [**Changelog**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/Changelog_EN.md) | [**FAQ (Frequently Asked Questions)**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/FAQ-(Frequently-Asked-Questions))
21
+
22
+ [**English**](../en/README.en.md) | [**中文简体**](../../README.md) | [**日本語**](../jp/README.ja.md) | [**한국어**](../kr/README.ko.md) ([**韓國語**](../kr/README.ko.han.md)) | [**Türkçe**](../tr/README.tr.md)
23
+
24
+
25
+ Check our [Demo Video](https://www.bilibili.com/video/BV1pm4y1z7Gm/) here!
26
+
27
+ Realtime Voice Conversion Software using RVC : [w-okada/voice-changer](https://github.com/w-okada/voice-changer)
28
+
29
+
30
+ > The dataset for the pre-training model uses nearly 50 hours of high quality VCTK open source dataset.
31
+
32
+ > High quality licensed song datasets will be added to training-set one after another for your use, without worrying about copyright infringement.
33
+
34
+ > Please look forward to the pretrained base model of RVCv3, which has larger parameters, more training data, better results, unchanged inference speed, and requires less training data for training.
35
+
36
+ ## Summary
37
+ This repository has the following features:
38
+ + Reduce tone leakage by replacing the source feature to training-set feature using top1 retrieval;
39
+ + Easy and fast training, even on relatively poor graphics cards;
40
+ + Training with a small amount of data also obtains relatively good results (>=10min low noise speech recommended);
41
+ + Supporting model fusion to change timbres (using ckpt processing tab->ckpt merge);
42
+ + Easy-to-use Webui interface;
43
+ + Use the UVR5 model to quickly separate vocals and instruments.
44
+ + Use the most powerful High-pitch Voice Extraction Algorithm [InterSpeech2023-RMVPE](#Credits) to prevent the muted sound problem. Provides the best results (significantly) and is faster, with even lower resource consumption than Crepe_full.
45
+ + AMD/Intel graphics cards acceleration supported.
46
+ + Intel ARC graphics cards acceleration with IPEX supported.
47
+
48
+ ## Preparing the environment
49
+ The following commands need to be executed in the environment of Python version 3.8 or higher.
50
+
51
+ (Windows/Linux)
52
+ First install the main dependencies through pip:
53
+ ```bash
54
+ # Install PyTorch-related core dependencies, skip if installed
55
+ # Reference: https://pytorch.org/get-started/locally/
56
+ pip install torch torchvision torchaudio
57
+
58
+ #For Windows + Nvidia Ampere Architecture(RTX30xx), you need to specify the cuda version corresponding to pytorch according to the experience of https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/issues/21
59
+ #pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
60
+ ```
61
+
62
+ Then can use poetry to install the other dependencies:
63
+ ```bash
64
+ # Install the Poetry dependency management tool, skip if installed
65
+ # Reference: https://python-poetry.org/docs/#installation
66
+ curl -sSL https://install.python-poetry.org | python3 -
67
+
68
+ # Install the project dependencies
69
+ poetry install
70
+ ```
71
+
72
+ You can also use pip to install them:
73
+ ```bash
74
+
75
+ for Nvidia graphics cards
76
+ pip install -r requirements.txt
77
+
78
+ for AMD/Intel graphics cards:
79
+ pip install -r requirements-dml.txt
80
+
81
+ for Intel ARC graphics cards on Linux / WSL using Python 3.10:
82
+ pip install -r requirements-ipex.txt
83
+
84
+ ```
85
+
86
+ ------
87
+ Mac users can install dependencies via `run.sh`:
88
+ ```bash
89
+ sh ./run.sh
90
+ ```
91
+
92
+ ## Preparation of other Pre-models
93
+ RVC requires other pre-models to infer and train.
94
+
95
+ You need to download them from our [Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/).
96
+
97
+ Here's a list of Pre-models and other files that RVC needs:
98
+ ```bash
99
+ ./assets/hubert/hubert_base.pt
100
+
101
+ ./assets/pretrained
102
+
103
+ ./assets/uvr5_weights
104
+
105
+ Additional downloads are required if you want to test the v2 version of the model.
106
+
107
+ ./assets/pretrained_v2
108
+
109
+ 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
110
+
111
+ ./assets/pretrained_v2
112
+
113
+ #If you are using Windows, you may also need these two files, skip if FFmpeg and FFprobe are installed
114
+ ffmpeg.exe
115
+
116
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe
117
+
118
+ ffprobe.exe
119
+
120
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe
121
+
122
+ If you want to use the latest SOTA RMVPE vocal pitch extraction algorithm, you need to download the RMVPE weights and place them in the RVC root directory
123
+
124
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/rmvpe.pt
125
+
126
+ For AMD/Intel graphics cards users you need download:
127
+
128
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/rmvpe.onnx
129
+
130
+ ```
131
+
132
+ Intel ARC graphics cards users needs to run `source /opt/intel/oneapi/setvars.sh` command before starting Webui.
133
+
134
+ Then use this command to start Webui:
135
+ ```bash
136
+ python infer-web.py
137
+ ```
138
+ If you are using Windows or macOS, you can download and extract `RVC-beta.7z` to use RVC directly by using `go-web.bat` on windows or `sh ./run.sh` on macOS to start Webui.
139
+
140
+ ## Credits
141
+ + [ContentVec](https://github.com/auspicious3000/contentvec/)
142
+ + [VITS](https://github.com/jaywalnut310/vits)
143
+ + [HIFIGAN](https://github.com/jik876/hifi-gan)
144
+ + [Gradio](https://github.com/gradio-app/gradio)
145
+ + [FFmpeg](https://github.com/FFmpeg/FFmpeg)
146
+ + [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
147
+ + [audio-slicer](https://github.com/openvpi/audio-slicer)
148
+ + [Vocal pitch extraction:RMVPE](https://github.com/Dream-High/RMVPE)
149
+ + The pretrained model is trained and tested by [yxlllc](https://github.com/yxlllc/RMVPE) and [RVC-Boss](https://github.com/RVC-Boss).
150
+
151
+ ## Thanks to all contributors for their efforts
152
+ <a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
153
+ <img src="https://contrib.rocks/image?repo=RVC-Project/Retrieval-based-Voice-Conversion-WebUI" />
154
+ </a>
155
+
docs/en/faiss_tips_en.md ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ faiss tuning TIPS
2
+ ==================
3
+ # about faiss
4
+ faiss is a library of neighborhood searches for dense vectors, developed by facebook research, which efficiently implements many approximate neighborhood search methods.
5
+ Approximate Neighbor Search finds similar vectors quickly while sacrificing some accuracy.
6
+
7
+ ## faiss in RVC
8
+ In RVC, for the embedding of features converted by HuBERT, we search for embeddings similar to the embedding generated from the training data and mix them to achieve a conversion that is closer to the original speech. However, since this search takes time if performed naively, high-speed conversion is realized by using approximate neighborhood search.
9
+
10
+ # implementation overview
11
+ In '/logs/your-experiment/3_feature256' where the model is located, features extracted by HuBERT from each voice data are located.
12
+ 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].)
13
+ After saving big_npy as /logs/your-experiment/total_fea.npy, train it with faiss.
14
+
15
+ In this article, I will explain the meaning of these parameters.
16
+
17
+ # Explanation of the method
18
+ ## index factory
19
+ An index factory is a unique faiss notation that expresses a pipeline that connects multiple approximate neighborhood search methods as a string.
20
+ This allows you to try various approximate neighborhood search methods simply by changing the index factory string.
21
+ In RVC it is used like this:
22
+
23
+ ```python
24
+ index = faiss.index_factory(256, "IVF%s,Flat" % n_ivf)
25
+ ```
26
+ Among the arguments of index_factory, the first is the number of dimensions of the vector, the second is the index factory string, and the third is the distance to use.
27
+
28
+ For more detailed notation
29
+ https://github.com/facebookresearch/faiss/wiki/The-index-factory
30
+
31
+ ## index for distance
32
+ There are two typical indexes used as similarity of embedding as follows.
33
+
34
+ - Euclidean distance (METRIC_L2)
35
+ - inner product (METRIC_INNER_PRODUCT)
36
+
37
+ Euclidean distance takes the squared difference in each dimension, sums the differences in all dimensions, and then takes the square root. This is the same as the distance in 2D and 3D that we use on a daily basis.
38
+ The inner product is not used as an index of similarity as it is, and the cosine similarity that takes the inner product after being normalized by the L2 norm is generally used.
39
+
40
+ Which is better depends on the case, but cosine similarity is often used in embedding obtained by word2vec and similar image retrieval models learned by ArcFace. If you want to do l2 normalization on vector X with numpy, you can do it with the following code with eps small enough to avoid 0 division.
41
+
42
+ ```python
43
+ X_normed = X / np.maximum(eps, np.linalg.norm(X, ord=2, axis=-1, keepdims=True))
44
+ ```
45
+
46
+ Also, for the index factory, you can change the distance index used for calculation by choosing the value to pass as the third argument.
47
+
48
+ ```python
49
+ index = faiss.index_factory(dimention, text, faiss.METRIC_INNER_PRODUCT)
50
+ ```
51
+
52
+ ## IVF
53
+ IVF (Inverted file indexes) is an algorithm similar to the inverted index in full-text search.
54
+ During learning, the search target is clustered with kmeans, and Voronoi partitioning is performed using the cluster center. Each data point is assigned a cluster, so we create a dictionary that looks up the data points from the clusters.
55
+
56
+ For example, if clusters are assigned as follows
57
+ |index|Cluster|
58
+ |-----|-------|
59
+ |1|A|
60
+ |2|B|
61
+ |3|A|
62
+ |4|C|
63
+ |5|B|
64
+
65
+ The resulting inverted index looks like this:
66
+
67
+ |cluster|index|
68
+ |-------|-----|
69
+ |A|1, 3|
70
+ |B|2, 5|
71
+ |C|4|
72
+
73
+ When searching, we first search n_probe clusters from the clusters, and then calculate the distances for the data points belonging to each cluster.
74
+
75
+ # recommend parameter
76
+ There are official guidelines on how to choose an index, so I will explain accordingly.
77
+ https://github.com/facebookresearch/faiss/wiki/Guidelines-to-choose-an-index
78
+
79
+ For datasets below 1M, 4bit-PQ is the most efficient method available in faiss as of April 2023.
80
+ Combining this with IVF, narrowing down the candidates with 4bit-PQ, and finally recalculating the distance with an accurate index can be described by using the following index factory.
81
+
82
+ ```python
83
+ index = faiss.index_factory(256, "IVF1024,PQ128x4fs,RFlat")
84
+ ```
85
+
86
+ ## Recommended parameters for IVF
87
+ Consider the case of too many IVFs. For example, if coarse quantization by IVF is performed for the number of data, this is the same as a naive exhaustive search and is inefficient.
88
+ For 1M or less, IVF values are recommended between 4*sqrt(N) ~ 16*sqrt(N) for N number of data points.
89
+
90
+ Since the calculation time increases in proportion to the number of n_probes, please consult with the accuracy and choose appropriately. Personally, I don't think RVC needs that much accuracy, so n_probe = 1 is fine.
91
+
92
+ ## FastScan
93
+ FastScan is a method that enables high-speed approximation of distances by Cartesian product quantization by performing them in registers.
94
+ Cartesian product quantization performs clustering independently for each d dimension (usually d = 2) during learning, calculates the distance between clusters in advance, and creates a lookup table. At the time of prediction, the distance of each dimension can be calculated in O(1) by looking at the lookup table.
95
+ So the number you specify after PQ usually specifies half the dimension of the vector.
96
+
97
+ For a more detailed description of FastScan, please refer to the official documentation.
98
+ https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan)
99
+
100
+ ## RFlat
101
+ RFlat is an instruction to recalculate the rough distance calculated by FastScan with the exact distance specified by the third argument of index factory.
102
+ When getting k neighbors, k*k_factor points are recalculated.
docs/en/faq_en.md ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Q1:ffmpeg error/utf8 error.
2
+ It is most likely not a FFmpeg issue, but rather an audio path issue;
3
+
4
+ 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>
5
+
6
+ ## Q2:Cannot find index file after "One-click Training".
7
+ If it displays "Training is done. The program is closed," then the model has been trained successfully, and the subsequent errors are fake;
8
+
9
+ 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>
10
+
11
+ ## Q3:Cannot find the model in “Inferencing timbre” after training
12
+ 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>
13
+
14
+ ## Q4:How to share a model/How to use others' models?
15
+ 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;
16
+
17
+ 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;
18
+
19
+ 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>
20
+
21
+ ## Q5:Connection Error.
22
+ You may have closed the console (black command line window).<br>
23
+
24
+ ## Q6:WebUI popup 'Expecting value: line 1 column 1 (char 0)'.
25
+ Please disable system LAN proxy/global proxy and then refresh.<br>
26
+
27
+ ## Q7:How to train and infer without the WebUI?
28
+ Training script:<br>
29
+ 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>
30
+
31
+ Inference script:<br>
32
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/myinfer.py<br>
33
+
34
+
35
+ e.g.<br>
36
+
37
+ 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>
38
+
39
+
40
+ f0up_key=sys.argv[1]<br>
41
+ input_path=sys.argv[2]<br>
42
+ index_path=sys.argv[3]<br>
43
+ f0method=sys.argv[4]#harvest or pm<br>
44
+ opt_path=sys.argv[5]<br>
45
+ model_path=sys.argv[6]<br>
46
+ index_rate=float(sys.argv[7])<br>
47
+ device=sys.argv[8]<br>
48
+ is_half=bool(sys.argv[9])<br>
49
+
50
+ ## Q8:Cuda error/Cuda out of memory.
51
+ 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>
52
+
53
+ 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>
54
+
55
+ ## Q9:How many total_epoch are optimal?
56
+ 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>
57
+
58
+ 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>
59
+
60
+ ## Q10:How much training set duration is needed?
61
+
62
+ A dataset of around 10min to 50min is recommended.<br>
63
+
64
+ With guaranteed high sound quality and low bottom noise, more can be added if the dataset's timbre is uniform.<br>
65
+
66
+ For a high-level training set (lean + distinctive tone), 5min to 10min is fine.<br>
67
+
68
+ 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;
69
+ Data of less than 1min duration has not been successfully attempted so far. This is not recommended.<br>
70
+
71
+
72
+ ## Q11:What is the index rate for and how to adjust it?
73
+ 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>
74
+
75
+ 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>
76
+
77
+ 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>
78
+
79
+ ## Q12:How to choose the gpu when inferring?
80
+ In the config.py file, select the card number after "device cuda:".<br>
81
+
82
+ The mapping between card number and graphics card can be seen in the graphics card information section of the training tab.<br>
83
+
84
+ ## Q13:How to use the model saved in the middle of training?
85
+ Save via model extraction at the bottom of the ckpt processing tab.
86
+
87
+ ## Q14:File/memory error(when training)?
88
+ Too many processes and your memory is not enough. You may fix it by:
89
+
90
+ 1、decrease the input in field "Threads of CPU".
91
+
92
+ 2、pre-cut trainset to shorter audio files.
93
+
94
+ ## Q15: How to continue training using more data
95
+
96
+ step1: put all wav data to path2.
97
+
98
+ step2: exp_name2+path2 -> process dataset and extract feature.
99
+
100
+ step3: copy the latest G and D file of exp_name1 (your previous experiment) into exp_name2 folder.
101
+
102
+ step4: click "train the model", and it will continue training from the beginning of your previous exp model epoch.
103
+
104
+ ## Q16: error about llvmlite.dll
105
+
106
+ OSError: Could not load shared object file: llvmlite.dll
107
+
108
+ FileNotFoundError: Could not find module lib\site-packages\llvmlite\binding\llvmlite.dll (or one of its dependencies). Try using the full path with constructor syntax.
109
+
110
+ The issue will happen in windows, install https://aka.ms/vs/17/release/vc_redist.x64.exe and it will be fixed.
111
+
112
+ ## Q17: RuntimeError: The expanded size of the tensor (17280) must match the existing size (0) at non-singleton dimension 1. Target sizes: [1, 17280]. Tensor sizes: [0]
113
+
114
+ Delete the wav files whose size is significantly smaller than others, and that won't happen again. Than click "train the model"and "train the index".
115
+
116
+ ## Q18: RuntimeError: The size of tensor a (24) must match the size of tensor b (16) at non-singleton dimension 2
117
+
118
+ Do not change the sampling rate and then continue training. If it is necessary to change, the exp name should be changed and the model will be trained from scratch. You can also copy the pitch and features (0/1/2/2b folders) extracted last time to accelerate the training process.
119
+
docs/en/training_tips_en.md ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Instructions and tips for RVC training
2
+ ======================================
3
+ This TIPS explains how data training is done.
4
+
5
+ # Training flow
6
+ I will explain along the steps in the training tab of the GUI.
7
+
8
+ ## step1
9
+ Set the experiment name here.
10
+
11
+ You can also set here whether the model should take pitch into account.
12
+ If the model doesn't consider pitch, the model will be lighter, but not suitable for singing.
13
+
14
+ Data for each experiment is placed in `/logs/your-experiment-name/`.
15
+
16
+ ## step2a
17
+ Loads and preprocesses audio.
18
+
19
+ ### load audio
20
+ If you specify a folder with audio, the audio files in that folder will be read automatically.
21
+ For example, if you specify `C:Users\hoge\voices`, `C:Users\hoge\voices\voice.mp3` will be loaded, but `C:Users\hoge\voices\dir\voice.mp3` will Not loaded.
22
+
23
+ Since ffmpeg is used internally for reading audio, if the extension is supported by ffmpeg, it will be read automatically.
24
+ After converting to int16 with ffmpeg, convert to float32 and normalize between -1 to 1.
25
+
26
+ ### denoising
27
+ The audio is smoothed by scipy's filtfilt.
28
+
29
+ ### Audio Split
30
+ 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.
31
+
32
+ ## step2b
33
+ ### Extract pitch
34
+ 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`.
35
+
36
+ ### Extract feature_print
37
+ 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`.
38
+
39
+ ## step3
40
+ train the model.
41
+ ### Glossary for Beginners
42
+ In deep learning, the data set is divided and the learning proceeds little by little. In one model update (step), batch_size data are retrieved and predictions and error corrections are performed. Doing this once for a dataset counts as one epoch.
43
+
44
+ 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.
45
+
46
+ ### Specify pretrained model
47
+ RVC starts training the model from pretrained weights instead of from 0, so it can be trained with a small dataset.
48
+
49
+ By default
50
+
51
+ - If you consider pitch, it loads `rvc-location/pretrained/f0G40k.pth` and `rvc-location/pretrained/f0D40k.pth`.
52
+ - If you don't consider pitch, it loads `rvc-location/pretrained/f0G40k.pth` and `rvc-location/pretrained/f0D40k.pth`.
53
+
54
+ 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.
55
+
56
+ ### learning index
57
+ 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.
58
+ 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`.
59
+
60
+ (From the 20230428update version, it is read from the index, and saving / specifying is no longer necessary.)
61
+
62
+ ### Button description
63
+ - Train model: After executing step2b, press this button to train the model.
64
+ - Train feature index: After training the model, perform index learning.
65
+ - One-click training: step2b, model training and feature index training all at once.
docs/fr/Changelog_FR.md ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### 2023-08-13
2
+ 1-Corrections régulières de bugs
3
+ - Modification du nombre total d'époques minimum à 1 et changement du nombre total d'époques minimum à 2
4
+ - Correction des erreurs d'entraînement sans utiliser de modèles pré-entraînés
5
+ - Après la séparation des voix d'accompagnement, libération de la mémoire graphique
6
+ - Changement du chemin absolu d'enregistrement de faiss en chemin relatif
7
+ - Prise en charge des chemins contenant des espaces (le chemin du jeu de données d'entraînement et le nom de l'expérience sont pris en charge, et aucune erreur ne sera signalée)
8
+ - La liste de fichiers annule l'encodage utf8 obligatoire
9
+ - Résolution du problème de consommation de CPU causé par la recherche faiss lors des changements de voix en temps réel
10
+
11
+ 2-Mises à jour clés
12
+ - Entraînement du modèle d'extraction de hauteur vocale open-source le plus puissant actuel, RMVPE, et utilisation pour l'entraînement, l'inférence hors ligne/en temps réel de RVC, supportant PyTorch/Onnx/DirectML
13
+ - Prise en charge des cartes graphiques AMD et Intel via Pytorch_DML
14
+
15
+ (1) Changement de voix en temps réel (2) Inférence (3) Séparation de l'accompagnement vocal (4) L'entraînement n'est pas actuellement pris en charge, passera à l'entraînement CPU; prend en charge l'inférence RMVPE de la GPU par Onnx_Dml
16
+
17
+ ### 2023-06-18
18
+ - Nouveaux modèles pré-entraînés v2 : 32k et 48k
19
+ - Correction des erreurs d'inférence du modèle non-f0
20
+ - Pour un jeu de données d'entraînement dépassant 1 heure, réalisation automatique de minibatch-kmeans pour réduire la forme des caractéristiques, afin que l'entraînement, l'ajout et la recherche d'index soient beaucoup plus rapides.
21
+ - Fourniture d'un espace huggingface vocal2guitar jouet
22
+ - Suppression automatique des audios de jeu de données d'entraînement court-circuitant les valeurs aberrantes
23
+ - Onglet d'exportation Onnx
24
+
25
+ Expériences échouées:
26
+ - ~~Récupération de caractéristiques : ajout de la récupération de caractéristiques temporelles : non efficace~~
27
+ - ~~Récupération de caractéristiques : ajout de la réduction de dimensionnalité PCAR : la recherche est encore plus lente~~
28
+ - ~~Augmentation aléatoire des données lors de l'entraînement : non efficace~~
29
+
30
+ Liste de tâches:
31
+ - ~~Vocos-RVC (vocodeur minuscule) : non efficace~~
32
+ - ~~Support de Crepe pour l'entraînement : remplacé par RMVPE~~
33
+ - ~~Inférence de précision à moitié crepe : remplacée par RMVPE. Et difficile à réaliser.~~
34
+ - Support de l'éditeur F0
35
+
36
+ ### 2023-05-28
37
+ - Ajout d'un cahier v2, changelog coréen, correction de certaines exigences environnementales
38
+ - Ajout d'un mode de protection des consonnes muettes et de la respiration
39
+ - Support de la détection de hauteur crepe-full
40
+ - Séparation vocale UVR5 : support des modèles de déréverbération et de désécho
41
+ - Ajout du nom de l'expérience et de la version sur le nom de l'index
42
+ - Support pour les utilisateurs de sélectionner manuellement le format d'exportation des audios de sortie lors du traitement de conversion vocale en lots et de la séparation vocale UVR5
43
+ - L'entraînement du modèle v1 32k n'est plus pris en charge
44
+
45
+ ### 2023-05-13
46
+ - Nettoyage des codes redondants de l'ancienne version du runtime dans le package en un clic : lib.infer_pack et uvr5_pack
47
+ - Correction du bug de multiprocessus pseudo dans la préparation du jeu de données d'entraînement
48
+ - Ajout de l'ajustement du rayon de filtrage médian pour l'algorithme de reconnaissance de hauteur de récolte
49
+ - Prise en charge du rééchantillonnage post-traitement pour l'exportation audio
50
+ - Réglage de multi-traitement "n_cpu" pour l'entraînement est passé de "extraction f0" à "prétraitement des données et extraction f0"
51
+ - Détection automatique des chemins d'index sous le dossier de logs et fourniture d'une fonction de liste déroulante
52
+ - Ajout de "Questions fréquemment posées et réponses" sur la page d'onglet (vous pouvez également consulter le wiki github RVC)
53
+ - Lors de l'inférence, la hauteur de la récolte est mise en cache lors de l'utilisation du même chemin d'accès audio d'entrée (objectif : en utilisant l'extraction de
54
+
55
+ la hauteur de la récolte, l'ensemble du pipeline passera par un long processus d'extraction de la hauteur répétitif. Si la mise en cache n'est pas utilisée, les utilisateurs qui expérimentent différents timbres, index, et réglages de rayon de filtrage médian de hauteur connaîtront un processus d'attente très douloureux après la première inférence)
56
+
57
+ ### 2023-05-14
58
+ - Utilisation de l'enveloppe de volume de l'entrée pour mixer ou remplacer l'enveloppe de volume de la sortie (peut atténuer le problème du "muet en entrée et bruit de faible amplitude en sortie". Si le bruit de fond de l'audio d'entrée est élevé, il n'est pas recommandé de l'activer, et il n'est pas activé par défaut (1 peut être considéré comme n'étant pas activé)
59
+ - Prise en charge de la sauvegarde des modèles extraits à une fréquence spécifiée (si vous voulez voir les performances sous différentes époques, mais que vous ne voulez pas sauvegarder tous les grands points de contrôle et extraire manuellement les petits modèles par ckpt-processing à chaque fois, cette fonctionnalité sera très pratique)
60
+ - Résolution du problème des "erreurs de connexion" causées par le proxy global du serveur en définissant des variables d'environnement
61
+ - Prise en charge des modèles pré-entraînés v2 (actuellement, seule la version 40k est disponible au public pour les tests, et les deux autres taux d'échantillonnage n'ont pas encore été entièrement entraînés)
62
+ - Limite le volume excessif dépassant 1 avant l'inférence
63
+ - Réglages légèrement ajustés de la préparation du jeu de données d'entraînement
64
+
65
+ #######################
66
+
67
+ Historique des changelogs:
68
+
69
+ ### 2023-04-09
70
+ - Correction des paramètres d'entraînement pour améliorer le taux d'utilisation du GPU : A100 est passé de 25% à environ 90%, V100 : de 50% à environ 90%, 2060S : de 60% à environ 85%, P40 : de 25% à environ 95% ; amélioration significative de la vitesse d'entraînement
71
+ - Changement de paramètre : la taille de batch_size totale est maintenant la taille de batch_size par GPU
72
+ - Changement de total_epoch : la limite maximale est passée de 100 à 1000 ; la valeur par défaut est passée de 10 à 20
73
+ - Correction du problème d'extraction de ckpt reconnaissant la hauteur de manière incorrecte, causant une inférence anormale
74
+ - Correction du problème d'entraînement distribué sauvegardant ckpt pour chaque rang
75
+ - Application du filtrage des caractéristiques nan pour l'extraction des caractéristiques
76
+ - Correction du problème d'entrée/sortie silencieuse produisant des consonnes aléatoires ou du bruit (les anciens modèles doivent être réentraînés avec un nouveau jeu de données)
77
+
78
+ ### 2023-04-16 Mise à jour
79
+ - Ajout d'une mini-interface graphique pour le changement de voix en temps réel, démarrage par double-clic sur go-realtime-gui.bat
80
+ - Application d'un filtrage pour les bandes de fréquences inférieures à 50Hz pendant l'entraînement et l'inférence
81
+ - Abaissement de l'extraction de hauteur minimale de pyworld du défaut 80 à 50 pour l'entraînement et l'inférence, permettant aux voix masculines graves entre 50-80Hz de ne pas être mises en sourdine
82
+ - WebUI prend en charge le changement de langue en fonction des paramètres régionaux du système (prise en charge actuelle de en_US, ja_JP, zh_CN, zh_HK, zh_SG, zh_TW ; défaut à en_US si non pris en charge)
83
+ - Correction de la reconnaissance de certains GPU (par exemple, échec de reconnaissance V100-16G, échec de reconnaissance P4)
84
+
85
+ ### 2023-04-28 Mise à jour
86
+ - Mise à niveau des paramètres d'index de faiss pour une vitesse plus rapide et une meilleure qualité
87
+ - Suppression de la dépendance à total_npy ; le partage futur de modèles ne nécessitera pas d'entrée total
88
+
89
+ _npy
90
+ - Levée des restrictions pour les GPU de la série 16, fournissant des paramètres d'inférence de 4 Go pour les GPU VRAM de 4 Go
91
+ - Correction d'un bug dans la séparation vocale d'accompagnement UVR5 pour certains formats audio
92
+ - La mini-interface de changement de voix en temps réel prend maintenant en charge les modèles de hauteur non-40k et non-lazy
93
+
94
+ ### Plans futurs :
95
+ Fonctionnalités :
96
+ - Ajouter une option : extraire de petits modèles pour chaque sauvegarde d'époque
97
+ - Ajouter une option : exporter un mp3 supplémentaire vers le chemin spécifié pendant l'inférence
98
+ - Prise en charge de l'onglet d'entraînement multi-personnes (jusqu'à 4 personnes)
99
+
100
+ Modèle de base :
101
+ - Collecter des fichiers wav de respiration pour les ajouter au jeu de données d'entraînement pour résoudre le problème des sons de respiration déformés
102
+ - Nous entraînons actuellement un modèle de base avec un jeu de données de chant étendu, qui sera publié à l'avenir
docs/fr/README.fr.md ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+
3
+ <h1>Retrieval-based-Voice-Conversion-WebUI</h1>
4
+ Un framework simple et facile à utiliser pour la conversion vocale (modificateur de voix) basé sur VITS<br><br>
5
+
6
+ [![madewithlove](https://img.shields.io/badge/made_with-%E2%9D%A4-red?style=for-the-badge&labelColor=orange
7
+ )](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
8
+
9
+ <img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
10
+
11
+ [![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb)
12
+ [![Licence](https://img.shields.io/badge/LICENSE-MIT-green.svg?style=for-the-badge)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/LICENSE)
13
+ [![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)
14
+
15
+ [![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk)
16
+
17
+ [**Journal de mise à jour**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/Changelog_CN.md) | [**FAQ**](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·Formation d'un chanteur AI pour 5 centimes**](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) | [**Enregistrement des expériences comparatives**](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)) | [**Démonstration en ligne**](https://huggingface.co/spaces/Ricecake123/RVC-demo)
18
+
19
+ </div>
20
+
21
+ ------
22
+
23
+ [**English**](./docs/en/README.en.md) |[ **中文简体**](./docs/cn/README.md) | [**日本語**](./docs/jp/README.ja.md) | [**한국어**](./docs/kr/README.ko.md) ([**韓國語**](./docs/kr/README.ko.han.md)) | [**Turc**](./docs/tr/README.tr.md)
24
+
25
+ Cliquez ici pour voir notre [vidéo de démonstration](https://www.bilibili.com/video/BV1pm4y1z7Gm/) !
26
+
27
+ > Conversion vocale en temps réel avec RVC : [w-okada/voice-changer](https://github.com/w-okada/voice-changer)
28
+
29
+ > Le modèle de base est formé avec près de 50 heures de données VCTK de haute qualité et open source. Aucun souci concernant les droits d'auteur, n'hésitez pas à l'utiliser.
30
+
31
+ > Attendez-vous au modèle de base RVCv3 : plus de paramètres, plus de données, de meilleurs résultats, une vitesse d'inférence presque identique, et nécessite moins de données pour la formation.
32
+
33
+ ## Introduction
34
+ Ce dépôt a les caractéristiques suivantes :
35
+ + Utilise le top1 pour remplacer les caractéristiques de la source d'entrée par les caractéristiques de l'ensemble d'entraînement pour éliminer les fuites de timbre vocal.
36
+ + Peut être formé rapidement même sur une carte graphique relativement moins performante.
37
+ + Obtient de bons résultats même avec peu de données pour la formation (il est recommandé de collecter au moins 10 minutes de données vocales avec un faible bruit de fond).
38
+ + Peut changer le timbre vocal en fusionnant des modèles (avec l'aide de l'onglet ckpt-merge).
39
+ + Interface web simple et facile à utiliser.
40
+ + Peut appeler le modèle UVR5 pour séparer rapidement la voix et l'accompagnement.
41
+ + Utilise l'algorithme de pitch vocal le plus avancé [InterSpeech2023-RMVPE](#projets-référencés) pour éliminer les problèmes de voix muette. Meilleurs résultats, plus rapide que crepe_full, et moins gourmand en ressources.
42
+ + Support d'accélération pour les cartes A et I.
43
+
44
+ ## Configuration de l'environnement
45
+ Exécutez les commandes suivantes dans un environnement Python de version supérieure à 3.8.
46
+
47
+ (Windows/Linux)
48
+ Installez d'abord les dépendances principales via pip :
49
+ ```bash
50
+ # Installez Pytorch et ses dépendances essentielles, sautez si déjà installé.
51
+ # Voir : https://pytorch.org/get-started/locally/
52
+ pip install torch torchvision torchaudio
53
+
54
+ # Pour les utilisateurs de Windows avec une architecture Nvidia Ampere (RTX30xx), en se basant sur l'expérience #21, spécifiez la version CUDA correspondante pour Pytorch.
55
+ # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
56
+ ```
57
+
58
+ Vous pouvez utiliser poetry pour installer les dépendances :
59
+ ```bash
60
+ # Installez l'outil de gestion des dépendances Poetry, sautez si déjà installé.
61
+ # Voir : https://python-poetry.org/docs/#installation
62
+ curl -sSL https://install.python-poetry.org | python3 -
63
+
64
+ # Installez les dépendances avec poetry.
65
+ poetry install
66
+ ```
67
+
68
+ Ou vous pouvez utiliser pip pour installer les dépendances :
69
+ ```bash
70
+ Cartes Nvidia :
71
+
72
+ pip install -r requirements.txt
73
+
74
+ Cartes AMD/Intel :
75
+ pip install -
76
+
77
+ r requirements-dml.txt
78
+
79
+ ```
80
+
81
+ ------
82
+ Les utilisateurs de Mac peuvent exécuter `run.sh` pour installer les dépendances :
83
+ ```bash
84
+ sh ./run.sh
85
+ ```
86
+
87
+ ## Préparation d'autres modèles pré-entraînés
88
+ RVC nécessite d'autres modèles pré-entraînés pour l'inférence et la formation.
89
+
90
+ Vous pouvez télécharger ces modèles depuis notre [espace Hugging Face](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/).
91
+
92
+ Voici une liste des modèles et autres fichiers requis par RVC :
93
+ ```bash
94
+ ./assets/hubert/hubert_base.pt
95
+
96
+ ./assets/pretrained
97
+
98
+ ./assets/uvr5_weights
99
+
100
+ Pour tester la version v2 du modèle, téléchargez également :
101
+
102
+ ./assets/pretrained_v2
103
+
104
+ Si vous utilisez Windows, vous pourriez avoir besoin de ces fichiers pour ffmpeg et ffprobe, sautez cette étape si vous avez déjà installé ffmpeg et ffprobe. Les utilisateurs d'ubuntu/debian peuvent installer ces deux bibliothèques avec apt install ffmpeg. Les utilisateurs de Mac peuvent les installer avec brew install ffmpeg (prérequis : avoir installé brew).
105
+
106
+ ./ffmpeg
107
+
108
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe
109
+
110
+ ./ffprobe
111
+
112
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe
113
+
114
+ Si vous souhaitez utiliser le dernier algorithme RMVPE de pitch vocal, téléchargez les paramètres du modèle de pitch et placez-les dans le répertoire racine de RVC.
115
+
116
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/rmvpe.pt
117
+
118
+ Les utilisateurs de cartes AMD/Intel nécessitant l'environnement DML doivent télécharger :
119
+
120
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/rmvpe.onnx
121
+
122
+ ```
123
+ Ensuite, exécutez la commande suivante pour démarrer WebUI :
124
+ ```bash
125
+ python infer-web.py
126
+ ```
127
+
128
+ Si vous utilisez Windows ou macOS, vous pouvez télécharger et extraire `RVC-beta.7z`. Les utilisateurs de Windows peuvent exécuter `go-web.bat` pour démarrer WebUI, tandis que les utilisateurs de macOS peuvent exécuter `sh ./run.sh`.
129
+
130
+ Il y a également un `Guide facile pour les débutants.doc` inclus pour référence.
131
+
132
+ ## Crédits
133
+ + [ContentVec](https://github.com/auspicious3000/contentvec/)
134
+ + [VITS](https://github.com/jaywalnut310/vits)
135
+ + [HIFIGAN](https://github.com/jik876/hifi-gan)
136
+ + [Gradio](https://github.com/gradio-app/gradio)
137
+ + [FFmpeg](https://github.com/FFmpeg/FFmpeg)
138
+ + [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
139
+ + [audio-slicer](https://github.com/openvpi/audio-slicer)
140
+ + [Extraction de la hauteur vocale : RMVPE](https://github.com/Dream-High/RMVPE)
141
+ + Le modèle pré-entraîné a été formé et testé par [yxlllc](https://github.com/yxlllc/RMVPE) et [RVC-Boss](https://github.com/RVC-Boss).
142
+
143
+ ## Remerciements à tous les contributeurs pour leurs efforts
144
+ <a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
145
+ <img src="https://contrib.rocks/image?repo=RVC-Project/Retrieval-based-Voice-Conversion-WebUI" />
146
+ </a>
docs/fr/faiss_tips_fr.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Conseils de réglage pour faiss
2
+ ==================
3
+ # À propos de faiss
4
+ faiss est une bibliothèque de recherches de voisins pour les vecteurs denses, développée par Facebook Research, qui implémente efficacement de nombreuses méthodes de recherche de voisins approximatifs.
5
+ La recherche de voisins approximatifs trouve rapidement des vecteurs similaires tout en sacrifiant une certaine précision.
6
+
7
+ ## faiss dans RVC
8
+ Dans RVC, pour l'incorporation des caractéristiques converties par HuBERT, nous recherchons des incorporations similaires à l'incorporation générée à partir des données d'entraînement et les mixons pour obtenir une conversion plus proche de la parole originale. Cependant, cette recherche serait longue si elle était effectuée de manière naïve, donc une conversion à haute vitesse est réalisée en utilisant une recherche de voisinage approximatif.
9
+
10
+ # Vue d'ensemble de la mise en œuvre
11
+ Dans '/logs/votre-expérience/3_feature256' où le modèle est situé, les caractéristiques extraites par HuBERT de chaque donnée vocale sont situées.
12
+ À partir de là, nous lisons les fichiers npy dans un ordre trié par nom de fichier et concaténons les vecteurs pour créer big_npy. (Ce vecteur a la forme [N, 256].)
13
+ Après avoir sauvegardé big_npy comme /logs/votre-expérience/total_fea.npy, nous l'entraînons avec faiss.
14
+
15
+ Dans cet article, j'expliquerai la signification de ces paramètres.
16
+
17
+ # Explication de la méthode
18
+ ## Usine d'index
19
+ Une usine d'index est une notation unique de faiss qui exprime un pipeline qui relie plusieurs méthodes de recherche de voisinage approximatif sous forme de chaîne.
20
+ Cela vous permet d'essayer diverses méthodes de recherche de voisinage approximatif simplement en changeant la chaîne de l'usine d'index.
21
+ Dans RVC, elle est utilisée comme ceci :
22
+
23
+ ```python
24
+ index = faiss.index_factory(256, "IVF%s,Flat" % n_ivf)
25
+ ```
26
+
27
+ Parmi les arguments de index_factory, le premier est le nombre de dimensions du vecteur, le second est la chaîne de l'usine d'index, et le troisième est la distance à utiliser.
28
+
29
+ Pour une notation plus détaillée :
30
+ https://github.com/facebookresearch/faiss/wiki/The-index-factory
31
+
32
+ ## Index pour la distance
33
+ Il existe deux index typiques utilisés comme similarité de l'incorporation comme suit :
34
+
35
+ - Distance euclidienne (METRIC_L2)
36
+ - Produit intérieur (METRIC_INNER_PRODUCT)
37
+
38
+ La distance euclidienne prend la différence au carré dans chaque dimension, somme les différences dans toutes les dimensions, puis prend la racine carrée. C'est la même chose que la distance en 2D et 3D que nous utilisons au quotidien.
39
+ Le produit intérieur n'est pas utilisé comme index de similarité tel quel, et la similarité cosinus qui prend le produit intérieur après avoir été normalisé par la norme L2 est généralement utilisée.
40
+
41
+ Lequel est le mieux dépend du cas, mais la similarité cosinus est souvent utilisée dans l'incorporation obtenue par word2vec et des modèles de récupération d'images similaires appris par ArcFace. Si vous voulez faire une normalisation l2 sur le vecteur X avec numpy, vous pouvez le faire avec le code suivant avec eps suffisamment petit pour éviter une division par 0.
42
+
43
+ ```python
44
+ X_normed = X / np.maximum(eps, np.linalg.norm(X, ord=2, axis=-1, keepdims=True))
45
+ ```
46
+
47
+ De plus, pour l'usine d'index, vous pouvez changer l'index de distance utilisé pour le calcul en choisissant la valeur à passer comme troisième argument.
48
+
49
+ ```python
50
+ index = faiss.index_factory(dimention, texte, faiss.METRIC_INNER_PRODUCT)
51
+ ```
52
+
53
+ ## IVF
54
+ IVF (Inverted file indexes) est un algorithme similaire à l'index inversé dans la recherche en texte intégral.
55
+ Lors de l'apprentissage, la cible de recherche est regroupée avec kmeans, et une partition de Voronoi est effectuée en utilisant le centre du cluster. Chaque point de données est attribué à un cluster, nous créons donc un dictionnaire qui permet de rechercher les points de données à partir des clusters.
56
+
57
+ Par exemple, si des clusters sont attribués comme suit :
58
+ |index|Cluster|
59
+ |-----|-------|
60
+ |1|A|
61
+ |2|B|
62
+ |3|A|
63
+ |4|C|
64
+ |5|B|
65
+
66
+ L'index inversé résultant ressemble à ceci :
67
+
68
+ |cluster|index|
69
+ |-------|-----|
70
+ |A|1, 3|
71
+ |B|2, 5|
72
+ |C|4|
73
+
74
+ Lors de la recherche, nous recherchons d'abord n_probe clusters parmi les clusters, puis nous calculons les distances pour les points de données appartenant à chaque cluster.
75
+
76
+ # Recommandation de paramètre
77
+ Il existe des directives officielles sur la façon de choisir un index, je vais donc expliquer en conséquence.
78
+ https://github.com/facebookresearch/faiss/wiki/Guidelines-to-choose-an-index
79
+
80
+ Pour les ensembles de données inférieurs à 1M, 4bit-PQ est la méthode la plus efficace disponible dans faiss en avril 2023.
81
+ En combinant cela avec IVF, en réduisant les candidats avec 4bit-PQ, et enfin en recalculant la distance avec un index précis, on peut le décrire en utilisant l'usine d'index suivante.
82
+
83
+ ```python
84
+ index = faiss.index_factory(256, "IVF1024,PQ128x4fs,RFlat")
85
+ ```
86
+
87
+ ## Paramètres recommandés pour IVF
88
+ Considérez le cas de trop d'IVF. Par exemple, si une quantification grossière par IVF est effectuée pour le nombre de données, cela revient à une recherche exhaustive naïve et est inefficace.
89
+ Pour 1M ou moins, les valeurs IVF sont recommandées entre 4*sqrt(N) ~ 16*sqrt(N) pour N nombre de points de données.
90
+
91
+ Comme le temps de calcul augmente proportionnellement au nombre de n_probes, veuillez consulter la précision et choisir de manière appropriée. Personnellement, je ne pense pas que RVC ait besoin de tant de précision, donc n_probe = 1 est bien.
92
+
93
+ ## FastScan
94
+ FastScan est une méthode qui permet d'approximer rapidement les distances par quantification de produit cartésien en les effectuant dans les registres.
95
+ La quantification du produit cartésien effectue un regroupement indépendamment
96
+
97
+ pour chaque dimension d (généralement d = 2) pendant l'apprentissage, calcule la distance entre les clusters à l'avance, et crée une table de recherche. Au moment de la prédiction, la distance de chaque dimension peut être calculée en O(1) en consultant la table de recherche.
98
+ Le nombre que vous spécifiez après PQ spécifie généralement la moitié de la dimension du vecteur.
99
+
100
+ Pour une description plus détaillée de FastScan, veuillez consulter la documentation officielle.
101
+ https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan)
102
+
103
+ ## RFlat
104
+ RFlat est une instruction pour recalculer la distance approximative calculée par FastScan avec la distance exacte spécifiée par le troisième argument de l'usine d'index.
105
+ Lors de l'obtention de k voisins, k*k_factor points sont recalculés.
docs/fr/faq_fr.md ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Q1: Erreur ffmpeg/erreur utf8.
2
+ Il s'agit très probablement non pas d'un problème lié à FFmpeg, mais d'un problème lié au chemin de l'audio ;
3
+
4
+ FFmpeg peut rencontrer une erreur lors de la lecture de chemins contenant des caractères spéciaux tels que des espaces et (), ce qui peut provoquer une erreur FFmpeg ; et lorsque l'audio du jeu d'entraînement contient des chemins en chinois, l'écrire dans filelist.txt peut provoquer une erreur utf8.<br>
5
+
6
+ ## Q2: Impossible de trouver le fichier index après "Entraînement en un clic".
7
+ Si l'affichage indique "L'entraînement est terminé. Le programme est fermé", alors le modèle a été formé avec succès, et les erreurs subséquentes sont fausses ;
8
+
9
+ L'absence d'un fichier index 'ajouté' après un entraînement en un clic peut être due au fait que le jeu d'entraînement est trop grand, ce qui bloque l'ajout de l'index ; cela a été résolu en utilisant un traitement par lots pour ajouter l'index, ce qui résout le problème de surcharge de mémoire lors de l'ajout de l'index. Comme solution temporaire, essayez de cliquer à nouveau sur le bouton "Entraîner l'index".<br>
10
+
11
+ ## Q3: Impossible de trouver le modèle dans “Inférence du timbre” après l'entraînement
12
+ Cliquez sur “Actualiser la liste des timbres” et vérifiez à nouveau ; si vous ne le voyez toujours pas, vérifiez s'il y a des erreurs pendant l'entraînement et envoyez des captures d'écran de la console, de l'interface utilisateur web, et des logs/nom_de_l'expérience/*.log aux développeurs pour une analyse plus approfondie.<br>
13
+
14
+ ## Q4: Comment partager un modèle/Comment utiliser les modèles d'autres personnes ?
15
+ Les fichiers pth stockés dans rvc_root/logs/nom_de_l'expérience ne sont pas destinés à être partagés ou inférés, mais à stocker les points de contrôle de l'expérience pour la reproductibilité et l'entraînement ultérieur. Le modèle à partager doit être le fichier pth de 60+MB dans le dossier des poids ;
16
+
17
+ À l'avenir, les poids/nom_de_l'expérience.pth et les logs/nom_de_l'expérience/ajouté_xxx.index seront fusionnés en un seul fichier poids/nom_de_l'expérience.zip pour éliminer le besoin d'une entrée d'index manuelle ; partagez donc le fichier zip, et non le fichier pth, sauf si vous souhaitez continuer l'entraînement sur une machine différente ;
18
+
19
+ Copier/partager les fichiers pth de plusieurs centaines de Mo du dossier des logs au dossier des poids pour une inférence forcée peut entraîner des erreurs telles que des f0, tgt_sr, ou d'autres clés manquantes. Vous devez utiliser l'onglet ckpt en bas pour sélectionner manuellement ou automatiquement (si l'information se trouve dans les logs/nom_de_l'expérience), si vous souhaitez inclure les informations sur la hauteur et les options de taux d'échantillonnage audio cible, puis extraire le modèle plus petit. Après extraction, il y aura un fichier pth de 60+ MB dans le dossier des poids, et vous pouvez actualiser les voix pour l'utiliser.<br>
20
+
21
+ ## Q5: Erreur de connexion.
22
+ Il se peut que vous ayez fermé la console (fenêtre de ligne de commande noire).<br>
23
+
24
+ ## Q6: WebUI affiche 'Expecting value: line 1 column 1 (char 0)'.
25
+ Veuillez désactiver le proxy système LAN/proxy global puis rafraîchir.<br>
26
+
27
+ ## Q7: Comment s'entraîner et déduire sans le WebUI ?
28
+ Script d'entraînement :<br>
29
+ Vous pouvez d'abord lancer l'entraînement dans WebUI, et les versions en ligne de commande de la préparation du jeu de données et de l'entraînement seront affichées dans la fenêtre de message.<br>
30
+
31
+ Script d'inférence :<br>
32
+ https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/myinfer.py<br>
33
+
34
+ Par exemple :<br>
35
+
36
+ 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" récolte "test.wav" "weights/mi-test.pth" 0.6 cuda:0 True<br>
37
+
38
+ f0up_key=sys.argv[1]<br>
39
+ input_path=sys.argv[2]<br>
40
+ index_path=sys.argv[3]<br>
41
+ f0method=sys.argv[4]#récolte ou pm<br>
42
+ opt_path=sys.argv[5]<br>
43
+ model_path=sys.argv[6]<br>
44
+ index_rate=float(sys.argv[7])<br>
45
+ device=sys.argv[8]<br>
46
+ is_half=bool(sys.argv[9])<br>
47
+
48
+ ### Explication des arguments :
49
+
50
+ 1. **Numéro de voix cible** : `0` (dans cet exemple)
51
+ 2. **Chemin du fichier audio d'entrée** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\INPUTS_VOCAL\vocal.wav"`
52
+ 3. **Chemin du fichier index** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\logs\Hagrid.index"`
53
+ 4. **Méthode pour l'extraction du pitch (F0)** : `harvest` (dans cet exemple)
54
+ 5. **Chemin de sortie pour le fichier audio traité** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\INPUTS_VOCAL\test.wav"`
55
+ 6. **Chemin du modèle** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\weights\HagridFR.pth"`
56
+ 7. **Taux d'index** : `0.6` (dans cet exemple)
57
+ 8. **Périphérique pour l'exécution (GPU/CPU)** : `cuda:0` pour une carte NVIDIA, par exemple.
58
+ 9. **Protection des droits d'auteur (True/False)**.
59
+
60
+ <!-- Pour myinfer nouveau models :
61
+
62
+ runtime\python.exe myinfer.py 0 "C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\INPUTS_VOCAL\vocal.wav" "C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\logs\Hagrid.index" harvest "C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\INPUTS_VOCAL\test.wav" "C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\weights\HagridFR.pth" 0.6 cuda:0 True 5 44100 44100 1.0 1.0 True
63
+
64
+
65
+ f0up_key=sys.argv[1]
66
+ input_path = sys.argv[2]
67
+ index_path = sys.argv[3]
68
+ f0method = sys.argv[4]
69
+ opt_path = sys.argv[5]
70
+ model_path = sys.argv[6]
71
+ index_rate = float(sys.argv[7])
72
+ device = sys.argv[8]
73
+ is_half = bool(sys.argv[9])
74
+ filter_radius = int(sys.argv[10])
75
+ tgt_sr = int(sys.argv[11])
76
+ resample_sr = int(sys.argv[12])
77
+ rms_mix_rate = float(sys.argv[13])
78
+ version = sys.argv[14]
79
+ protect = sys.argv[15].lower() == 'false' # change for true if needed
80
+
81
+ ### Explication des arguments :
82
+
83
+ 1. **Numéro de voix cible** : `0` (dans cet exemple)
84
+ 2. **Chemin du fichier audio d'entrée** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\INPUTS_VOCAL\vocal.wav"`
85
+ 3. **Chemin du fichier index** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\logs\Hagrid.index"`
86
+ 4. **Méthode pour l'extraction du pitch (F0)** : `harvest` (dans cet exemple)
87
+ 5. **Chemin de sortie pour le fichier audio traité** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\INPUTS_VOCAL\test.wav"`
88
+ 6. **Chemin du modèle** : `"C:\ YOUR PATH FOR THE ROOT (RVC0813Nvidia)\weights\HagridFR.pth"`
89
+ 7. **Taux d'index** : `0.6` (dans cet exemple)
90
+ 8. **Périphérique pour l'exécution (GPU/CPU)** : `cuda:0` pour une carte NVIDIA, par exemple.
91
+ 9. **Protection des droits d'auteur (True/False)**.
92
+ 10. **Rayon du filtre** : `5` (dans cet exemple)
93
+ 11. **Taux d'échantillonnage cible** : `44100` (dans cet exemple)
94
+ 12. **Taux d'échantillonnage pour le rééchantillonnage** : `44100` (dans cet exemple)
95
+ 13. **Taux de mixage RMS** : `1.0` (dans cet exemple)
96
+ 14. **Version** : `1.0` (dans cet exemple)
97
+ 15. **Protection** : `True` (dans cet exemple)
98
+
99
+ Assurez-vous de remplacer les chemins par ceux correspondant à votre configuration et d'ajuster les autres paramètres selon vos besoins.
100
+ -->
101
+
102
+ ## Q8: Erreur Cuda/Mémoire Cuda épuisée.
103
+ Il y a une faible chance qu'il y ait un problème avec la configuration CUDA ou que le dispositif ne soit pas pris en charge ; plus probablement, il n'y a pas assez de mémoire (manque de mémoire).<br>
104
+
105
+ Pour l'entraînement, réduisez la taille du lot (si la réduction à 1 n'est toujours pas suffisante, vous devrez peut-être changer la carte graphique) ; pour l'inférence, ajustez les paramètres x_pad, x_query, x_center, et x_max dans le fichier config.py selon les besoins. Les cartes mémoire de 4 Go ou moins (par exemple 1060(3G) et diverses cartes de 2 Go) peuvent être abandonnées, tandis que les cartes mémoire de 4 Go ont encore une chance.<br>
106
+
107
+ ## Q9: Combien de total_epoch sont optimaux ?
108
+ Si la qualité audio du jeu d'entraînement est médiocre et que le niveau de bruit est élevé, 20-30 époques sont suffisantes. Le fixer trop haut n'améliorera pas la qualité audio de votre jeu d'entraînement de faible qualité.<br>
109
+
110
+ Si la qualité audio du jeu d'entraînement est élevée, le niveau de bruit est faible, et la durée est suffisante, vous pouvez l'augmenter. 200 est acceptable (puisque l'entraînement est rapide, et si vous êtes capable de préparer un jeu d'entraînement de haute qualité, votre GPU peut probablement gérer une durée d'entraînement plus longue sans problème).<br>
111
+
112
+ ## Q10: Quelle durée de jeu d'entraînement est nécessaire ?
113
+ Un jeu d'environ 10 min à 50 min est recommandé.<br>
114
+
115
+ Avec une garantie de haute qualité sonore et de faible bruit de fond, plus peut être ajouté si le timbre du jeu est uniforme.<br>
116
+
117
+ Pour un jeu d'entraînement de haut niveau (ton maigre + ton distinctif), 5 min à 10 min sont suffisantes.<br>
118
+
119
+ Il y a des personnes qui ont réussi à s'entraîner avec des données de 1 min à 2 min, mais le succès n'est pas reproductible par d'autres et n'est pas très informatif. <br>Cela nécessite que le jeu d'entraînement ait un timbre très distinctif (par exemple, un son de fille d'anime aérien à haute fréquence) et que la qualité de l'audio soit élevée ;
120
+ Aucune tentative réussie n'a été faite jusqu'à présent avec des données de moins de 1 min. Cela n'est pas recommandé.<br>
121
+
122
+ ## Q11: À quoi sert le taux d'index et comment l'ajuster ?
123
+ Si la qualité tonale du modèle pré-entraîné et de la source d'inférence est supérieure à celle du jeu d'entraînement, ils peuvent améliorer la qualité tonale du résultat d'inférence, mais au prix d'un possible biais tonal vers le ton du modèle sous-jacent/source d'inférence plutôt que le ton du jeu d'entraînement, ce qui est généralement appelé "fuite de ton".<br>
124
+
125
+ Le taux d'index est utilisé pour réduire/résoudre le problème de la fuite de timbre. Si le taux d'index est fixé à 1, théoriquement il n'y a pas de fuite de timbre de la source d'inférence et la qualité du timbre est plus biaisée vers le jeu d'entraînement. Si le jeu d'entraînement a une qualité sonore inférieure à celle de la source d'inférence, alors un taux d'index plus élevé peut réduire la qualité sonore. Le réduire à 0 n'a pas l'effet d'utiliser le mélange de récupération pour protéger les tons du jeu d'entraînement.<br>
126
+
127
+ Si le jeu d'entraînement a une bonne qualité audio et une longue durée, augmentez le total_epoch, lorsque le modèle lui-même est moins susceptible de se référer à la source déduite et au modèle sous-jacent pré-entraîné, et qu'il y a peu de "fuite de ton", le taux d'index n'est pas important et vous pouvez même ne pas créer/partager le fichier index.<br>
128
+
129
+ ## Q12: Comment choisir le gpu lors de l'inférence ?
130
+ Dans le fichier config.py, sélectionnez le numéro de carte après "device cuda:".<br>
131
+
132
+ La correspondance entre le numéro de carte et la carte graphique peut être vue dans la section d'information de la carte graphique de l'onglet d'entraînement.<br>
133
+
134
+ ## Q13: Comment utiliser le modèle sauvegardé au milieu de l'entraînement ?
135
+ Sauvegardez via l'extraction de modèle en bas de l'onglet de traitement ckpt.
136
+
137
+ ## Q14: Erreur de fichier/erreur de mémoire (lors de l'entraînement) ?
138
+ Il y a trop de processus et votre mémoire n'est pas suffisante. Vous pouvez le corriger en :
139
+
140
+ 1. Diminuer l'entrée dans le champ "Threads of CPU".
141
+
142
+ 2. Pré-découper le jeu d'entraînement en fichiers audio plus courts.
143
+
144
+ ## Q15: Comment poursuivre l'entraînement avec plus de données
145
+
146
+ étape 1 : mettre toutes les données wav dans path2.
147
+
148
+ étape 2 : exp_name2+path2 -> traiter le jeu de données et extraire la caractéristique.
149
+
150
+ étape 3 : copier les derniers fichiers G et D de exp_name1 (votre expérience précédente) dans le dossier exp_name2.
151
+
152
+ étape 4 : cliquez sur "entraîner le modèle", et il continuera l'entraînement depuis le début de votre époque de modèle exp précédente.
153
+
154
+ ## Q16: erreur à propos de llvmlite.dll
155
+
156
+ OSError: Impossible de charger le fichier objet partagé : llvmlite.dll
157
+
158
+ FileNotFoundError: Impossible de trouver le module lib\site-packages\llvmlite\binding\llvmlite.dll (ou l'une de ses dépendances). Essayez d'utiliser la syntaxe complète du constructeur.
159
+
160
+ Le problème se produira sous Windows, installez https://aka.ms/vs/17/release/vc_redist.x64.exe et il sera corrigé.
161
+
162
+ ## Q17: RuntimeError: La taille étendue du tensor (17280) doit correspondre à la taille existante (0) à la dimension non-singleton 1. Tailles cibles : [1, 17280]. Tailles des tensors : [0]
163
+
164
+ Supprimez les fichiers wav dont la taille est nettement inférieure à celle des autres, et cela ne se reproduira plus. Ensuite, cliquez sur "entraîner le modèle" et "entraîner l'index".
165
+
166
+ ## Q18: RuntimeError: La taille du tensor a (24) doit correspondre à la taille du tensor b (16) à la dimension non-singleton 2
167
+
168
+ Ne changez pas le taux d'échantillonnage puis continuez l'entraînement. S'il est nécessaire de changer, le nom de l'expérience doit être modifié et le modèle sera formé à partir de zéro. Vous pouvez également copier les hauteurs et caractéristiques (dossiers 0/1/2/2b) extraites la dernière fois pour accélérer le processus d'entraînement.
169
+
docs/fr/training_tips_fr.md ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Instructions et conseils pour la formation RVC
2
+ ======================================
3
+ Ces conseils expliquent comment se déroule la formation des données.
4
+
5
+ # Flux de formation
6
+ Je vais expliquer selon les étapes de l'onglet de formation de l'interface graphique.
7
+
8
+ ## étape 1
9
+ Définissez ici le nom de l'expérience.
10
+
11
+ Vous pouvez également définir ici si le modèle doit prendre en compte le pitch.
12
+ Si le modèle ne considère pas le pitch, le modèle sera plus léger, mais pas adapté au chant.
13
+
14
+ Les données de chaque expérience sont placées dans `/logs/nom-de-votre-experience/`.
15
+
16
+ ## étape 2a
17
+ Charge et pré-traite l'audio.
18
+
19
+ ### charger l'audio
20
+ Si vous spécifiez un dossier avec de l'audio, les fichiers audio de ce dossier seront lus automatiquement.
21
+ Par exemple, si vous spécifiez `C:Users\hoge\voices`, `C:Users\hoge\voices\voice.mp3` sera chargé, mais `C:Users\hoge\voices\dir\voice.mp3` ne sera pas chargé.
22
+
23
+ Comme ffmpeg est utilisé en interne pour lire l'audio, si l'extension est prise en charge par ffmpeg, elle sera lue automatiquement.
24
+ Après la conversion en int16 avec ffmpeg, convertir en float32 et normaliser entre -1 et 1.
25
+
26
+ ### débruitage
27
+ L'audio est lissé par filtfilt de scipy.
28
+
29
+ ### Séparation audio
30
+ Tout d'abord, l'audio d'entrée est divisé en détectant des parties de silence qui durent plus d'une certaine période (max_sil_kept = 5 secondes ?). Après avoir séparé l'audio sur le silence, séparez l'audio toutes les 4 secondes avec un chevauchement de 0,3 seconde. Pour l'audio séparé en 4 secondes, après normalisation du volume, convertir le fichier wav en `/logs/nom-de-votre-experience/0_gt_wavs` puis le convertir à un taux d'échantillonnage de 16k dans `/logs/nom-de-votre-experience/1_16k_wavs` sous forme de fichier wav.
31
+
32
+ ## étape 2b
33
+ ### Extraire le pitch
34
+ Extrait les informations de pitch des fichiers wav. Extraire les informations de pitch (=f0) en utilisant la méthode intégrée dans parselmouth ou pyworld et les sauvegarder dans `/logs/nom-de-votre-experience/2a_f0`. Convertissez ensuite logarithmiquement les informations de pitch en un entier entre 1 et 255 et sauvegardez-le dans `/logs/nom-de-votre-experience/2b-f0nsf`.
35
+
36
+ ### Extraire l'empreinte de caractéristique
37
+ Convertissez le fichier wav en incorporation à l'avance en utilisant HuBERT. Lisez le fichier wav sauvegardé dans `/logs/nom-de-votre-experience/1_16k_wavs`, convertissez le fichier wav en caractéristiques de dimension 256 avec HuBERT, et sauvegardez au format npy dans `/logs/nom-de-votre-experience/3_feature256`.
38
+
39
+ ## étape 3
40
+ former le modèle.
41
+ ### Glossaire pour les débutants
42
+ Dans l'apprentissage profond, l'ensemble de données est divisé et l'apprentissage progresse petit à petit. Dans une mise à jour de modèle (étape), les données de batch_size sont récupérées et des prédictions et corrections d'erreur sont effectuées. Faire cela une fois pour un ensemble de données compte comme une époque.
43
+
44
+ Par conséquent, le temps d'apprentissage est le temps d'apprentissage par étape x (le nombre de données dans l'ensemble de données / taille du lot) x le nombre d'époques. En général, plus la taille du lot est grande, plus l'apprentissage devient stable (temps d'apprentissage par étape ÷ taille du lot) devient plus petit, mais il utilise plus de mémoire GPU. La RAM GPU peut être vérifiée avec la commande nvidia-smi. L'apprentissage peut être effectué en peu de temps en augmentant la taille du lot autant que possible selon la machine de l'environnement d'exécution.
45
+
46
+ ### Spécifier le modèle pré-entraîné
47
+ RVC commence à former le modèle à partir de poids pré-entraînés plutôt que de zéro, il peut donc être formé avec un petit ensemble de données.
48
+
49
+ Par défaut :
50
+
51
+ - Si vous considérez le pitch, il charge `rvc-location/pretrained/f0G40k.pth` et `rvc-location/pretrained/f0D40k.pth`.
52
+ - Si vous ne considérez pas le pitch, il charge `rvc-location/pretrained/f0G40k.pth` et `rvc-location/pretrained/f0D40k.pth`.
53
+
54
+ Lors de l'apprentissage, les paramètres du modèle sont sauvegardés dans `logs/nom-de-votre-experience/G_{}.pth` et `logs/nom-de-votre-experience/D_{}.pth` pour chaque save_every_epoch, mais en spécifiant ce chemin, vous pouvez démarrer l'apprentissage. Vous pouvez redémarrer ou commencer à former à partir de poids de modèle appris lors d'une expérience différente.
55
+
56
+ ### Index d'apprentissage
57
+ RVC sauvegarde les valeurs de caractéristique HuBERT utilisées lors de la formation, et pendant l'inférence, recherche les valeurs de caractéristique qui sont similaires aux valeurs de caractéristique utilisées lors de l'apprentissage pour effectuer l'inférence. Afin d'effectuer cette recherche à haute vitesse, l'index est appris à l'avance.
58
+ Pour l'apprentissage d'index, nous utilisons la bibliothèque de recherche de voisinage approximatif faiss. Lisez la valeur de caractéristique de `logs/nom-de-votre-experience/3_feature256` et utilisez-la pour apprendre l'index, et sauvegardez-la sous `logs/nom-de-votre-experience/add_XXX.index`.
59
+
60
+ (À partir de la version de mise à jour 20230428, elle est lue à partir de l'index, et la sauvegarde / spécification n'est plus nécessaire.)
61
+
62
+ ### Description du bouton
63
+ - Former le modèle : après avoir exécuté l'étape 2b, appuyez sur ce bouton pour former le modèle.
64
+ - Former l'index de caractéristique : après avoir formé le modèle, effectuez un apprentissage d'index.
65
+ - Formation en un clic : étape 2b, formation du modèle et formation de l'index de caractéristique tout d'un coup.```
docs/jp/README.ja.md ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+
3
+ <h1>Retrieval-based-Voice-Conversion-WebUI</h1>
4
+ VITSに基づく使いやすい音声変換(voice changer)framework<br><br>
5
+
6
+ [![madewithlove](https://img.shields.io/badge/made_with-%E2%9D%A4-red?style=for-the-badge&labelColor=orange
7
+ )](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
8
+
9
+ <img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
10
+
11
+ [![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb)
12
+ [![Licence](https://img.shields.io/github/license/RVC-Project/Retrieval-based-Voice-Conversion-WebUI?style=for-the-badge)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/LICENSE)
13
+ [![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)
14
+
15
+ [![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk)
16
+
17
+ </div>
18
+
19
+ ------
20
+
21
+ [**更新日誌**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/Changelog_CN.md)
22
+
23
+ [**English**](../en/README.en.md) | [**中文简体**](../../README.md) | [**日本語**](../jp/README.ja.md) | [**한국어**](../kr/README.ko.md) ([**韓國語**](../kr/README.ko.han.md)) | [**Türkçe**](../tr/README.tr.md)
24
+
25
+ > デモ動画は[こちら](https://www.bilibili.com/video/BV1pm4y1z7Gm/)でご覧ください。
26
+
27
+ > RVCによるリアルタイム音声変換: [w-okada/voice-changer](https://github.com/w-okada/voice-changer)
28
+
29
+ > 著作権侵害を心配することなく使用できるように、基底モデルは約50時間の高品質なオープンソースデータセットで訓練されています。
30
+
31
+ > 今後も、次々と使用許可のある高品質な歌声の資料集を追加し、基底モデルを訓練する予定です。
32
+
33
+ ## はじめに
34
+ 本リポジトリには下記の特徴があります。
35
+
36
+ + Top1検索を用いることで、生の特徴量を訓練用データセット特徴量に変換し、トーンリーケージを削減します。
37
+ + 比較的貧弱なGPUでも、高速かつ簡単に訓練できます。
38
+ + 少量のデータセットからでも、比較的良い結果を得ることができます。(10分以上のノイズの少ない音声を推奨します。)
39
+ + モデルを融合することで、音声を混ぜることができます。(ckpt processingタブの、ckpt mergeを使用します。)
40
+ + 使いやすいWebUI。
41
+ + UVR5 Modelも含んでいるため、人の声とBGMを素早く分離できます。
42
+
43
+ ## 環境構築
44
+ Poetryで依存関係をインストールすることをお勧めします。
45
+
46
+ 下記のコマンドは、Python3.8以上の環境で実行する必要があります:
47
+ ```bash
48
+ # PyTorch関連の依存関係をインストール。インストール済の場合は省略。
49
+ # 参照先: https://pytorch.org/get-started/locally/
50
+ pip install torch torchvision torchaudio
51
+
52
+ #Windows+ Nvidia Ampere Architecture(RTX30xx)の場合、 #21 に従い、pytorchに対応するcuda versionを指定する必要があります。
53
+ #pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
54
+
55
+ # PyTorch関連の依存関係をインストール。インストール済の場合は省略。
56
+ # 参照先: https://python-poetry.org/docs/#installation
57
+ curl -sSL https://install.python-poetry.org | python3 -
58
+
59
+ # Poetry経由で依存関係をインストール
60
+ poetry install
61
+ ```
62
+
63
+ pipでも依存関係のインストールが可能です:
64
+
65
+ ```bash
66
+ pip install -r requirements.txt
67
+ ```
68
+
69
+ ## 基底modelsを準備
70
+ RVCは推論/訓練のために、様々な事前訓練を行った基底モデルを必要とします。
71
+
72
+ modelsは[Hugging Face space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)からダウンロードできます。
73
+
74
+ 以下は、RVCに必要な基底モデルやその他のファイルの一覧です。
75
+ ```bash
76
+ ./assets/hubert/hubert_base.pt
77
+
78
+ ./assets/pretrained
79
+
80
+ ./assets/uvr5_weights
81
+
82
+ V2のモデルを使用するには、追加でファイルをダウンロードする必要があります
83
+
84
+ ./assets/pretrained_v2
85
+
86
+ # ffmpegがすでにinstallされている場合は省略
87
+ ./ffmpeg
88
+ ```
89
+ その後、下記のコマンドでWebUIを起動します。
90
+ ```bash
91
+ python infer-web.py
92
+ ```
93
+ Windowsをお使いの方は、直接`RVC-beta.7z`をダウンロード後に展開し、`go-web.bat`をクリックすることで、WebUIを起動することができます。(7zipが必要です。)
94
+
95
+ また、リポジトリに[小白简易教程.doc](./小白简易教程.doc)がありますので、参考にしてください(中国語版のみ)。
96
+
97
+ ## 参考プロジェクト
98
+ + [ContentVec](https://github.com/auspicious3000/contentvec/)
99
+ + [VITS](https://github.com/jaywalnut310/vits)
100
+ + [HIFIGAN](https://github.com/jik876/hifi-gan)
101
+ + [Gradio](https://github.com/gradio-app/gradio)
102
+ + [FFmpeg](https://github.com/FFmpeg/FFmpeg)
103
+ + [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
104
+ + [audio-slicer](https://github.com/openvpi/audio-slicer)
105
+
106
+ ## 貢献者(contributor)の皆様の尽力に感謝します
107
+ <a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
108
+ <img src="https://contrib.rocks/image?repo=RVC-Project/Retrieval-based-Voice-Conversion-WebUI" />
109
+ </a>
docs/jp/faiss_tips_ja.md ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ faiss tuning TIPS
2
+ ==================
3
+ # about faiss
4
+ faissはfacebook researchの開発する、密なベクトルに対する近傍探索をまとめたライブラリで、多くの近似近傍探索の手法を効率的に実装しています。
5
+ 近似近傍探索はある程度精度を犠牲にしながら高速に類似するベクトルを探します。
6
+
7
+ ## faiss in RVC
8
+ RVCではHuBERTで変換した特徴量のEmbeddingに対し、学習データから生成されたEmbeddingと類似するものを検索し、混ぜることでより元の音声に近い変換を実現しています。ただ、この検索は愚直に行うと時間がかかるため、近似近傍探索を用いることで高速な変換を実現しています。
9
+
10
+ # 実装のoverview
11
+ モデルが配置されている '/logs/your-experiment/3_feature256'には各音声データからHuBERTで抽出された特徴量が配置されています。
12
+ ここからnpyファイルをファイル名でソートした順番で読み込み、ベクトルを連結してbig_npyを作成しfaissを学習させます。(このベクトルのshapeは[N, 256]です。)
13
+
14
+ 本Tipsではまずこれらのパラメータの意味を解説します。
15
+
16
+ # 手法の解説
17
+ ## index factory
18
+ index factoryは複数の近似近傍探索の手法を繋げるパイプラインをstringで表記するfaiss独自の記法です。
19
+ これにより、index factoryの文字列を変更するだけで様々な近似近傍探索の手法を試せます。
20
+ RVCでは以下のように使われています。
21
+
22
+ ```python
23
+ index = faiss.index_factory(256, "IVF%s,Flat" % n_ivf)
24
+ ```
25
+ index_factoryの引数のうち、1つ目はベクトルの次元数、2つ目はindex factoryの文字列で、3つ目には用いる距離を指定することができます。
26
+
27
+ より詳細な記法については
28
+ https://github.com/facebookresearch/faiss/wiki/The-index-factory
29
+
30
+ ## 距離指標
31
+ embeddingの類似度として用いられる代表的な指標として以下の二つがあります。
32
+
33
+ - ユークリッド距離(METRIC_L2)
34
+ - 内積(METRIC_INNER_PRODUCT)
35
+
36
+ ユークリッド距離では各次元において二乗の差をとり、全次元の差を足してから平方根をとります。これは日常的に用いる2次元、3次元での距離と同じです。
37
+ 内積はこのままでは類似度の指標として用いず、一般的にはL2ノルムで正規化してから内積をとるコサイン類似度を用います。
38
+
39
+ どちらがよいかは場合によりますが、word2vec等で得られるembeddingやArcFace等で学習した類似画像検索のモデルではコサイン類似度が用いられることが多いです。ベクトルXに対してl2正規化をnumpyで行う場合は、0 divisionを避けるために十分に小さな値をepsとして以下のコードで可能です。
40
+
41
+ ```python
42
+ X_normed = X / np.maximum(eps, np.linalg.norm(X, ord=2, axis=-1, keepdims=True))
43
+ ```
44
+
45
+ また、index factoryには第3引数に渡す値を選ぶことで計算に用いる距離指標を変更できます。
46
+
47
+ ```python
48
+ index = faiss.index_factory(dimention, text, faiss.METRIC_INNER_PRODUCT)
49
+ ```
50
+
51
+ ## IVF
52
+ IVF(Inverted file indexes)は全文検索における転置インデックスと似たようなアルゴリズムです。
53
+ 学習時には検索対象に対してkmeansでクラスタリングを行い、クラスタ中心を用いてボロノイ分割を行います。各データ点には一つずつクラスタが割り当てられるので、クラスタからデータ点を逆引きする辞書を作成します。
54
+
55
+ 例えば以下のようにクラスタが割り当てられた場合
56
+ |index|クラスタ|
57
+ |-----|-------|
58
+ |1|A|
59
+ |2|B|
60
+ |3|A|
61
+ |4|C|
62
+ |5|B|
63
+
64
+ 作成される転置インデックスは以下のようになります。
65
+
66
+ |クラスタ|index|
67
+ |-------|-----|
68
+ |A|1, 3|
69
+ |B|2, 5|
70
+ |C|4|
71
+
72
+ 検索時にはまずクラスタからn_probe個のクラスタを検索し、次にそれぞれのクラスタに属するデータ点について距離を計算します。
73
+
74
+ # 推奨されるパラメータ
75
+ indexの選び方については公式にガイドラインがあるので、それに準じて説明します。
76
+ https://github.com/facebookresearch/faiss/wiki/Guidelines-to-choose-an-index
77
+
78
+ 1M以下のデータセットにおいては4bit-PQが2023年4月時点ではfaissで利用できる最も効率的な手法です。
79
+ これをIVFと組み合わせ、4bit-PQで候補を絞り、最後に正確な指標で距離を再計算するには以下のindex factoryを用いることで記載できます。
80
+
81
+ ```python
82
+ index = faiss.index_factory(256, "IVF1024,PQ128x4fs,RFlat")
83
+ ```
84
+
85
+ ## IVFの推奨パラメータ
86
+ IVFの数が多すぎる場合、たとえばデータ数の数だけIVFによる粗量子化を行うと、これは愚直な全探索と同じになり効率が悪いです。
87
+ 1M以下の場合ではIVFの値はデータ点の数Nに対して4*sqrt(N) ~ 16*sqrt(N)に推奨しています。
88
+
89
+ n_probeはn_probeの数に比例して計算時間が増えるので、精度と相談して適切に選んでください。個人的にはRVCにおいてそこまで精度は必要ないと思うのでn_probe = 1で良いと思います。
90
+
91
+ ## FastScan
92
+ FastScanは直積量子化で大まかに距離を近似するのを、レジスタ内で行うことにより高速に行うようにした手法です。
93
+ 直積量子化は学習時にd次元ごと(通常はd=2)に独立してクラスタリングを行い、クラスタ同士の距離を事前計算してlookup tableを作成します。予測時はlookup tableを見ることで各次元の距離をO(1)で計算できます。
94
+ そのため、PQの次に指定する数字は通常ベクトルの半分の次元を指定します。
95
+
96
+ FastScanに関するより詳細な説明は公式のドキュメントを参照してください。
97
+ https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan)
98
+
99
+ ## RFlat
100
+ RFlatはFastScanで計算した大まかな距離を、index factoryの第三引数で指定した正確な距離で再計算する指示です。
101
+ k個の近傍を取得する際は、k*k_factor個の点について再計算が行われます。
docs/jp/training_tips_ja.md ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ RVCの訓練における説明、およびTIPS
2
+ ===============================
3
+ 本TIPSではどのようにデータの訓練が行われているかを説明します。
4
+
5
+ # 訓練の流れ
6
+ GUIの訓練タブのstepに沿って説明します。
7
+
8
+ ## step1
9
+ 実験名の設定を行います。
10
+
11
+ また、モデルに音高ガイド(ピッチ)を考慮させるかもここで設定できます。考慮させない場合はモデルは軽量になりますが、歌唱には向かなくなります。
12
+
13
+ 各実験のデータは`/logs/実験名/`に配置されます。
14
+
15
+ ## step2a
16
+ 音声の読み込みと前処理を行います。
17
+
18
+ ### load audio
19
+ 音声のあるフォルダを指定すると、そのフォルダ内にある音声ファイルを自動で読み込みます。
20
+ 例えば`C:Users\hoge\voices`を指定した場合、`C:Users\hoge\voices\voice.mp3`は読み込まれますが、`C:Users\hoge\voices\dir\voice.mp3`は読み込まれません。
21
+
22
+ 音声の読み込みには内部でffmpegを利用しているので、ffmpegで対応している拡張子であれば自動的に読み込まれます。
23
+ ffmpegでint16に変換した後、float32に変換し、-1 ~ 1の間に正規化されます。
24
+
25
+ ### denoising
26
+ 音声についてscipyのfiltfiltによる平滑化を行います。
27
+
28
+ ### 音声の分割
29
+ 入力した音声はまず、一定期間(max_sil_kept=5秒?)より長く無音が続く部分を検知して音声を分割します。無音で音声を分割した後は、0.3秒のoverlapを含む4秒ごとに音声を分割します。4秒以内に区切られた音声は、音量の正規化を行った後wavファイルを`/logs/実験名/0_gt_wavs`に、そこから16kのサンプリングレートに変換して`/logs/実験名/1_16k_wavs`にwavファイルで保存します。
30
+
31
+ ## step2b
32
+ ### ピッチの抽出
33
+ wavファイルからピッチ(音の高低)の情報を抽出します。parselmouthやpyworldに内蔵されている手法でピッチ情報(=f0)を抽出し、`/logs/実験名/2a_f0`に保存します。その後、ピッチ情報を対数で変換して1~255の整数に変換し、`/logs/実験名/2b-f0nsf`に保存します。
34
+
35
+ ### feature_printの抽出
36
+ HuBERTを用いてwavファイルを事前にembeddingに変換します。`/logs/実験名/1_16k_wavs`に保存したwavファイルを読み込み、HuBERTでwavファイルを256次元の特徴量に変換し、npy形式で`/logs/実験名/3_feature256`に保存します。
37
+
38
+ ## step3
39
+ モデルのトレーニングを行います。
40
+ ### 初心者向け用語解説
41
+ 深層学習ではデータセットを分割し、少しずつ学習を進めていきます。一回のモデルの更新(step)では、batch_size個のデータを取り出し予測と誤差の修正を行います。これをデータセットに対して一通り行うと一epochと数えます。
42
+
43
+ そのため、学習時間は 1step当たりの学習時間 x (データセット内のデータ数 ÷ バッチサイズ) x epoch数 かかります。一般にバッチサイズを大きくするほど学習は安定し、(1step当たりの学習時間÷バッチサイズ)は小さくなりますが、その分GPUのメモリを多く使用します。GPUのRAMはnvidia-smiコマンド等で確認できます。実行環境のマシンに合わせてバッチサイズをできるだけ大きくするとより短時間で学習が可能です。
44
+
45
+ ### pretrained modelの指定
46
+ RVCではモデルの訓練を0からではなく、事前学習済みの重みから開始するため、少ないデータセットで学習を行えます。
47
+
48
+ デフォルトでは
49
+
50
+ - 音高ガイドを考慮する場合、`RVCのある場所/pretrained/f0G40k.pth`と`RVCのある場所/pretrained/f0D40k.pth`を読み込みます。
51
+ - 音高ガイドを考慮しない場合、`RVCのある場所/pretrained/G40k.pth`と`RVCのある場所/pretrained/D40k.pth`を読み込みます。
52
+
53
+ 学習時はsave_every_epochごとにモデルのパラメータが`logs/実験名/G_{}.pth`と`logs/実験名/D_{}.pth`に保存されますが、このパスを指定することで学習を再開したり、もしくは違う実験で学習したモデルの重みから学習を開始できます。
54
+
55
+ ### indexの学習
56
+ RVCでは学習時に使われたHuBERTの特徴量を保存し、推論時は学習時の特徴量から近い特徴量を探してきて推論を行います。この検索を高速に行うために事前にindexの学習を行います。
57
+ indexの学習には近似近傍探索ライブラリのfaissを用います。`/logs/実験名/3_feature256`の特徴量を読み込み、それを用いて学習したindexを`/logs/実験名/add_XXX.index`として保存します。
58
+ (20230428updateよりtotal_fea.npyはindexから読み込むので不要になりました。)
59
+
60
+ ### ボタンの説明
61
+ - モデルのトレーニング: step2bまでを実行した後、このボタンを押すとモデルの学習を行います。
62
+ - 特徴インデックスのトレーニング: モデルのトレーニング後、indexの学習を行います。
63
+ - ワンクリックトレーニング: step2bまでとモデルのトレーニング、特徴インデックスのトレーニングを一括で行います。
64
+