├── .dockerignore ├── .gitignore ├── .gitmodules ├── Dockerfile ├── LICENSE ├── README.md ├── bin └── .gitkeep ├── changelog.md ├── config ├── .gitignore └── rvc.json ├── deepspeed-0.8.3+6eca037c-cp39-cp39-win_amd64.whl ├── download_ffmpeg.bat ├── models ├── .gitignore ├── .template.dlas.yaml ├── rvc_models │ └── .gitignore ├── tokenizers │ ├── ipa.json │ └── spanish_bpe_tokenizer.json └── tortoise │ └── train_diffusion_vocoder_22k_level.yml ├── modules ├── .gitignore └── rvc │ ├── .gitignore │ ├── Dockerfile │ ├── LICENSE │ ├── MIT协议暨相关引用库协议 │ ├── README.md │ ├── Retrieval_based_Voice_Conversion_WebUI.ipynb │ ├── Retrieval_based_Voice_Conversion_WebUI_v2.ipynb │ ├── changelog.md │ ├── configs │ ├── config.json │ ├── config.py │ ├── v1 │ │ ├── 32k.json │ │ ├── 40k.json │ │ └── 48k.json │ └── v2 │ │ ├── 32k.json │ │ └── 48k.json │ ├── docker-compose.yml │ ├── docs │ ├── cn │ │ ├── Changelog_CN.md │ │ └── faq.md │ ├── en │ │ ├── Changelog_EN.md │ │ ├── README.en.md │ │ ├── faiss_tips_en.md │ │ ├── faq_en.md │ │ └── training_tips_en.md │ ├── fr │ │ ├── Changelog_FR.md │ │ ├── README.fr.md │ │ ├── faiss_tips_fr.md │ │ ├── faq_fr.md │ │ └── training_tips_fr.md │ ├── jp │ │ ├── README.ja.md │ │ ├── faiss_tips_ja.md │ │ └── training_tips_ja.md │ ├── kr │ │ ├── Changelog_KO.md │ │ ├── README.ko.han.md │ │ ├── README.ko.md │ │ ├── faiss_tips_ko.md │ │ └── training_tips_ko.md │ ├── tr │ │ ├── Changelog_TR.md │ │ ├── README.tr.md │ │ ├── faiss_tips_tr.md │ │ ├── faq_tr.md │ │ └── training_tips_tr.md │ └── 小白简易教程.doc │ ├── environment_dml.yaml │ ├── go-realtime-gui-dml.bat │ ├── go-realtime-gui.bat │ ├── go-web-dml.bat │ ├── go-web.bat │ ├── gui_v1.py │ ├── i18n │ ├── i18n.py │ ├── locale │ │ ├── en_US.json │ │ ├── es_ES.json │ │ ├── fr_FR.json │ │ ├── it_IT.json │ │ ├── ja_JP.json │ │ ├── ru_RU.json │ │ ├── tr_TR.json │ │ ├── zh_CN.json │ │ ├── zh_HK.json │ │ ├── zh_SG.json │ │ └── zh_TW.json │ ├── locale_diff.py │ └── scan_i18n.py │ ├── infer-web.py │ ├── infer │ └── modules │ │ ├── ipex │ │ ├── __init__.py │ │ ├── attention.py │ │ ├── gradscaler.py │ │ └── hijacks.py │ │ ├── onnx │ │ └── export.py │ │ ├── train │ │ ├── extract │ │ │ ├── extract_f0_print.py │ │ │ ├── extract_f0_rmvpe.py │ │ │ └── extract_f0_rmvpe_dml.py │ │ ├── extract_feature_print.py │ │ ├── preprocess.py │ │ └── train.py │ │ ├── uvr5 │ │ ├── mdxnet.py │ │ ├── modules.py │ │ └── preprocess.py │ │ └── vc │ │ ├── __init__.py │ │ ├── modules.py │ │ ├── pipeline.py │ │ └── utils.py │ ├── modules.py │ ├── poetry.lock │ ├── pyproject.toml │ ├── requirements-amd.txt │ ├── requirements-dml.txt │ ├── requirements-ipex.txt │ ├── requirements-win-for-realtime_vc_gui-dml.txt │ ├── requirements-win-for-realtime_vc_gui.txt │ ├── requirements.txt │ ├── run.sh │ ├── tools │ ├── app.py │ ├── calc_rvc_model_similarity.py │ ├── dlmodels.bat │ ├── dlmodels.sh │ ├── export_onnx.py │ ├── infer │ │ ├── infer-pm-index256.py │ │ ├── train-index-v2.py │ │ ├── train-index.py │ │ └── trans_weights.py │ ├── infer_batch_rvc.py │ ├── infer_cli.py │ ├── onnx_inference_demo.py │ ├── rvc_for_realtime.py │ └── torchgate │ │ ├── __init__.py │ │ ├── torchgate.py │ │ └── utils.py │ └── venv.sh ├── notebook_colab.ipynb ├── notebook_paperspace.ipynb ├── reload_flag.txt ├── requirements.txt ├── setup-cuda-bnb.bat ├── setup-cuda-cpu.bat ├── setup-cuda-cpu.sh ├── setup-cuda.bat ├── setup-cuda.sh ├── setup-directml.bat ├── setup-docker.sh ├── setup-rocm-bnb.sh ├── setup-rocm.sh ├── setup-whisperx.bat ├── src ├── api │ └── websocket_server.py ├── cli.py ├── list_devices.py ├── main.py ├── train.py ├── train_jard.py ├── utils.py └── webui.py ├── start-docker.sh ├── start.bat ├── start.sh ├── train-docker.sh ├── train.bat ├── train.sh ├── training └── .gitignore ├── update-force.bat ├── update-force.sh ├── update.bat ├── update.sh ├── update_package.bat └── voices ├── .gitignore └── random ├── cond_latents_d1f79232.pth └── cond_latents_f540259e.pth /.dockerignore: -------------------------------------------------------------------------------- 1 | /models 2 | /training 3 | /voices 4 | /bin 5 | Dockerfile 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignores user files 2 | /ffmpeg/ 3 | /personal_testing/ 4 | *.7z 5 | /venv/ 6 | /venv_cpu/ 7 | /training/* 8 | /config/* 9 | output/ 10 | *.wav 11 | fairseq-0.12.2-cp39-cp39-win_amd64.whl 12 | rvc/ 13 | *.zip 14 | pyfastmp3decoder/ 15 | .vscode/ 16 | onnx_test_stuff/ 17 | *.whl 18 | *.exe 19 | 20 | # Byte-compiled / optimized / DLL files 21 | __pycache__/ 22 | *.py[cod] 23 | *$py.class 24 | 25 | # C extensions 26 | *.so 27 | 28 | # Distribution / packaging 29 | .Python 30 | build/ 31 | develop-eggs/ 32 | dist/ 33 | downloads/ 34 | eggs/ 35 | .eggs/ 36 | lib/ 37 | lib64/ 38 | parts/ 39 | sdist/ 40 | var/ 41 | wheels/ 42 | pip-wheel-metadata/ 43 | share/python-wheels/ 44 | *.egg-info/ 45 | .installed.cfg 46 | *.egg 47 | MANIFEST 48 | 49 | # PyInstaller 50 | # Usually these files are written by a python script from a template 51 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 52 | *.manifest 53 | *.spec 54 | 55 | # Installer logs 56 | pip-log.txt 57 | pip-delete-this-directory.txt 58 | 59 | # Unit test / coverage reports 60 | htmlcov/ 61 | .tox/ 62 | .nox/ 63 | .coverage 64 | .coverage.* 65 | .cache 66 | nosetests.xml 67 | coverage.xml 68 | *.cover 69 | *.py,cover 70 | .hypothesis/ 71 | .pytest_cache/ 72 | 73 | # Translations 74 | *.mo 75 | *.pot 76 | 77 | # Django stuff: 78 | *.log 79 | local_settings.py 80 | db.sqlite3 81 | db.sqlite3-journal 82 | 83 | # Flask stuff: 84 | instance/ 85 | .webassets-cache 86 | 87 | # Scrapy stuff: 88 | .scrapy 89 | 90 | # Sphinx documentation 91 | docs/_build/ 92 | 93 | # PyBuilder 94 | target/ 95 | 96 | # Jupyter Notebook 97 | .ipynb_checkpoints 98 | 99 | # IPython 100 | profile_default/ 101 | ipython_config.py 102 | 103 | # pyenv 104 | .python-version 105 | 106 | # pipenv 107 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 108 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 109 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 110 | # install all needed dependencies. 111 | #Pipfile.lock 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | .idea/* 151 | 152 | .custom/* 153 | results/* 154 | debug_states/* 155 | bin/* 156 | 157 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "modules/tortoise-tts"] 2 | path = modules/tortoise-tts 3 | url = https://github.com/JarodMica/tortoise-tts.git 4 | [submodule "modules/dlas"] 5 | path = modules/dlas 6 | url = https://github.com/JarodMica/DL-Art-School.git 7 | [submodule "modules/tortoise_dataset_tools"] 8 | path = modules/tortoise_dataset_tools 9 | url = https://github.com/JarodMica/tortoise_dataset_tools.git 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:12.2.0-devel-ubuntu22.04 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | ARG TZ=UTC 5 | ARG MINICONDA_VERSION=23.1.0-1 6 | ARG PYTHON_VERSION=3.11 7 | ARG UID=1000 8 | ARG GID=1000 9 | 10 | # TZ 11 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 12 | 13 | # Prereqs 14 | RUN apt-get update 15 | RUN apt-get install -y \ 16 | curl \ 17 | wget \ 18 | git \ 19 | ffmpeg \ 20 | p7zip-full \ 21 | gcc \ 22 | g++ \ 23 | vim 24 | 25 | # User 26 | RUN groupadd --gid $GID user 27 | RUN useradd --no-log-init --create-home --shell /bin/bash --uid $UID --gid $GID user 28 | USER user 29 | ENV HOME=/home/user 30 | WORKDIR $HOME 31 | RUN mkdir $HOME/.cache $HOME/.config && chmod -R 777 $HOME 32 | 33 | # Python 34 | RUN wget https://repo.anaconda.com/miniconda/Miniconda3-py39_$MINICONDA_VERSION-Linux-x86_64.sh 35 | RUN chmod +x Miniconda3-py39_$MINICONDA_VERSION-Linux-x86_64.sh 36 | RUN ./Miniconda3-py39_$MINICONDA_VERSION-Linux-x86_64.sh -b -p /home/user/miniconda 37 | ENV PATH="$HOME/miniconda/bin:$PATH" 38 | RUN conda init 39 | RUN conda install python=$PYTHON_VERSION 40 | RUN python3 -m pip install --upgrade pip 41 | RUN pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 42 | 43 | # Base path 44 | RUN mkdir $HOME/ai-voice-cloning 45 | WORKDIR $HOME/ai-voice-cloning 46 | 47 | # Built in modules 48 | COPY --chown=user:user modules modules 49 | RUN python3 -m pip install -r ./modules/tortoise-tts/requirements.txt 50 | RUN python3 -m pip install -e ./modules/tortoise-tts/ 51 | RUN python3 -m pip install -r ./modules/dlas/requirements.txt 52 | RUN python3 -m pip install -e ./modules/dlas/ 53 | 54 | # RVC 55 | RUN \ 56 | curl -L -o /tmp/rvc.zip https://huggingface.co/Jmica/rvc/resolve/main/rvc_lightweight.zip?download=true &&\ 57 | 7z x /tmp/rvc.zip &&\ 58 | rm -f /tmp/rvc.zip 59 | USER root 60 | RUN \ 61 | chown user:user rvc -R &&\ 62 | chmod -R u+rwX,go+rX,go-w rvc 63 | USER user 64 | RUN python3 -m pip install -r ./rvc/requirements.txt 65 | 66 | # Fairseq 67 | # Using patched version for Python 3.11 due to https://github.com/facebookresearch/fairseq/issues/5012 68 | RUN python3 -m pip install git+https://github.com/liyaodev/fairseq 69 | 70 | # RVC Pipeline 71 | RUN python3 -m pip install git+https://github.com/JarodMica/rvc-tts-pipeline.git@lightweight#egg=rvc_tts_pipe 72 | 73 | # Deepspeed 74 | RUN python3 -m pip install deepspeed 75 | 76 | # PyFastMP3Decoder 77 | RUN python3 -m pip install cython 78 | RUN git clone https://github.com/neonbjb/pyfastmp3decoder.git 79 | RUN \ 80 | cd pyfastmp3decoder &&\ 81 | git submodule update --init --recursive &&\ 82 | python setup.py install &&\ 83 | cd .. 84 | 85 | # WhisperX 86 | RUN python3 -m pip install git+https://github.com/m-bain/whisperx.git 87 | 88 | # Main requirements 89 | ADD requirements.txt requirements.txt 90 | RUN python3 -m pip install -r ./requirements.txt 91 | 92 | # The app 93 | ADD --chown=user:user . $HOME/ai-voice-cloning 94 | 95 | ENV IN_DOCKER=true 96 | 97 | CMD ["./start.sh"] 98 | -------------------------------------------------------------------------------- /bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarodMica/ai-voice-cloning/61e46bcbc2676e21623724e66269f48d015b2ccb/bin/.gitkeep -------------------------------------------------------------------------------- /config/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /config/rvc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rvc_model": "azasu.pth", 3 | "f0_up_key": 12, 4 | "file_index": "", 5 | "index_rate": 0, 6 | "filter_radius": 3, 7 | "resample_sr": 48000, 8 | "rms_mix_rate": 0.25, 9 | "protect": 0.33 10 | } -------------------------------------------------------------------------------- /deepspeed-0.8.3+6eca037c-cp39-cp39-win_amd64.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarodMica/ai-voice-cloning/61e46bcbc2676e21623724e66269f48d015b2ccb/deepspeed-0.8.3+6eca037c-cp39-cp39-win_amd64.whl -------------------------------------------------------------------------------- /download_ffmpeg.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set ffmpeg_url=https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-essentials.7z?download=true 4 | set ffmpeg_folder=ffmpeg 5 | set ffmpeg_zip=ffmpeg.7z 6 | 7 | curl -o 7z.exe "https://www.7-zip.org/a/7zr.exe" 8 | 9 | if not exist "%ffmpeg_folder%" ( 10 | if not exist "%ffmpeg_zip%" ( 11 | echo Downloading %ffmpeg_zip%... 12 | curl -L -o "%ffmpeg_zip%" "%ffmpeg_url%" 13 | if errorlevel 1 ( 14 | echo Download failed. Please check your internet connection or the URL and try again. 15 | exit /b 1 16 | ) 17 | ) else ( 18 | echo File %ffmpeg_zip% already exists, skipping download. 19 | ) 20 | 21 | echo Extracting %ffmpeg_zip%... 22 | 7z.exe x %ffmpeg_zip% -o%ffmpeg_folder% 23 | echo FFmpeg has finished downloading and extracting. 24 | ) else ( 25 | echo FFmpeg folder %ffmpeg_folder% already exists, skipping download and extraction. 26 | ) 27 | 28 | :: Move ffmpeg.exe and ffprobe.exe to the ffmpeg folder root 29 | for /D %%i in ("%ffmpeg_folder%\*") do ( 30 | if exist "%%i\bin\ffmpeg.exe" move "%%i\bin\ffmpeg.exe" "ffmpeg.exe" 31 | if exist "%%i\bin\ffprobe.exe" move "%%i\bin\ffprobe.exe" "ffprobe.exe" 32 | ) 33 | 34 | echo FFmpeg moved out of downloaded folder -------------------------------------------------------------------------------- /models/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !tokenizers/ 3 | !.gitignore 4 | !rvc_models/ 5 | !.template.dlas.yaml 6 | !tortoise/ -------------------------------------------------------------------------------- /models/.template.dlas.yaml: -------------------------------------------------------------------------------- 1 | name: '${voice}' 2 | model: extensibletrainer 3 | scale: 1 4 | gpu_ids: [0] # Manually edit this if the GPU you want to train on is not your primary, as this will set the env var that exposes CUDA devices 5 | start_step: 0 6 | checkpointing_enabled: true 7 | fp16: ${half_p} 8 | bitsandbytes: ${bitsandbytes} 9 | gpus: ${gpus} 10 | 11 | datasets: 12 | train: 13 | name: training 14 | n_workers: ${workers} 15 | batch_size: ${batch_size} 16 | mode: paired_voice_audio 17 | path: ${dataset_path} 18 | fetcher_mode: ['lj'] 19 | phase: train 20 | max_wav_length: 255995 # ~11.6 seconds 21 | max_text_length: 200 22 | sample_rate: 22050 23 | load_conditioning: True 24 | num_conditioning_candidates: 2 25 | conditioning_length: 44000 26 | use_bpe_tokenizer: True 27 | tokenizer_vocab: ${tokenizer_json} # ./models/tortoise/bpe_lowercase_asr_256.json 28 | load_aligned_codes: False 29 | val: 30 | name: validation 31 | n_workers: ${workers} 32 | batch_size: ${validation_batch_size} 33 | mode: paired_voice_audio 34 | path: ${validation_path} 35 | fetcher_mode: ['lj'] 36 | phase: val 37 | max_wav_length: 255995 38 | max_text_length: 200 39 | sample_rate: 22050 40 | load_conditioning: True 41 | num_conditioning_candidates: 2 42 | conditioning_length: 44000 43 | use_bpe_tokenizer: True 44 | tokenizer_vocab: ${tokenizer_json} # ./models/tortoise/bpe_lowercase_asr_256.json 45 | load_aligned_codes: False 46 | 47 | steps: 48 | gpt_train: 49 | training: gpt 50 | loss_log_buffer: 500 51 | 52 | # Generally follows the recipe from the DALLE paper. 53 | optimizer: ${optimizer} # this should be adamw_zero if you're using distributed training 54 | optimizer_params: 55 | lr: !!float ${learning_rate} # originally: 1e-4 56 | weight_decay: !!float 1e-2 57 | beta1: 0.9 58 | beta2: 0.96 59 | clip_grad_eps: 4 60 | 61 | injectors: 62 | paired_to_mel: 63 | type: torch_mel_spectrogram 64 | mel_norm_file: ./modules/tortoise-tts/tortoise/data/mel_norms.pth # ./models/tortoise/clips_mel_norms.pth 65 | in: wav 66 | out: paired_mel 67 | paired_cond_to_mel: 68 | type: for_each 69 | subtype: torch_mel_spectrogram 70 | mel_norm_file: ./modules/tortoise-tts/tortoise/data/mel_norms.pth # ./models/tortoise/clips_mel_norms.pth 71 | in: conditioning 72 | out: paired_conditioning_mel 73 | to_codes: 74 | type: discrete_token 75 | in: paired_mel 76 | out: paired_mel_codes 77 | dvae_config: "./models/tortoise/train_diffusion_vocoder_22k_level.yml" 78 | paired_fwd_text: 79 | type: generator 80 | generator: gpt 81 | in: [paired_conditioning_mel, padded_text, text_lengths, paired_mel_codes, wav_lengths] 82 | out: [loss_text_ce, loss_mel_ce, logits] 83 | losses: 84 | text_ce: 85 | type: direct 86 | weight: ${text_lr_weight} 87 | key: loss_text_ce 88 | mel_ce: 89 | type: direct 90 | weight: ${mel_lr_weight} 91 | key: loss_mel_ce 92 | 93 | networks: 94 | gpt: 95 | type: generator 96 | which_model_G: unified_voice2 97 | kwargs: 98 | layers: 30 # originally: 8 99 | model_dim: 1024 # originally: 512 100 | heads: 16 # originally: 8 101 | max_text_tokens: 402 # originally: 120 102 | max_mel_tokens: 604 # originally: 250 103 | max_conditioning_inputs: 2 # originally: 1 104 | mel_length_compression: 1024 105 | number_text_tokens: 256 # supposed to be 255 for newer unified_voice files 106 | number_mel_codes: 8194 107 | start_mel_token: 8192 108 | stop_mel_token: 8193 109 | start_text_token: 255 110 | train_solo_embeddings: False # missing in uv3/4 111 | use_mel_codes_as_input: True # ditto 112 | checkpointing: True 113 | tortoise_compat: True 114 | # freeze_everything_but_position_embeddings: True 115 | 116 | path: 117 | strict_load: true 118 | ${source_model} 119 | ${resume_state} 120 | 121 | train: 122 | niter: ${iterations} 123 | warmup_iter: -1 124 | mega_batch_factor: ${gradient_accumulation_size} 125 | val_freq: ${validation_rate} 126 | 127 | ema_enabled: false # I really don't think EMA matters 128 | 129 | ${learning_rate_scheme} 130 | 131 | eval: 132 | pure: ${validation_enabled} 133 | output_state: gen 134 | 135 | logger: 136 | save_checkpoint_freq: ${save_rate} 137 | visuals: [gen, mel] 138 | visual_debug_rate: ${save_rate} 139 | is_mel_spectrogram: true -------------------------------------------------------------------------------- /models/rvc_models/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.gitkeep -------------------------------------------------------------------------------- /models/tokenizers/ipa.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "truncation": null, 4 | "padding": null, 5 | "normalizer": null, 6 | "pre_tokenizer": null, 7 | "post_processor": null, 8 | "decoder": null, 9 | "added_tokens": [ 10 | { 11 | "id": 0, 12 | "special": true, 13 | "content": "[STOP]", 14 | "single_word": false, 15 | "lstrip": false, 16 | "rstrip": false, 17 | "normalized": false 18 | }, 19 | { 20 | "id": 1, 21 | "special": true, 22 | "content": "[UNK]", 23 | "single_word": false, 24 | "lstrip": false, 25 | "rstrip": false, 26 | "normalized": false 27 | }, 28 | { 29 | "id": 2, 30 | "special": true, 31 | "content": "[SPACE]", 32 | "single_word": false, 33 | "lstrip": false, 34 | "rstrip": false, 35 | "normalized": false 36 | } 37 | ], 38 | "model": { 39 | "type": "BPE", 40 | "dropout": null, 41 | "unk_token": "[UNK]", 42 | "continuing_subword_prefix": null, 43 | "end_of_word_suffix": null, 44 | "fuse_unk": false, 45 | "vocab": { 46 | "[STOP]": 0, 47 | "[UNK]": 1, 48 | "[SPACE]": 2, 49 | "!": 3, 50 | "'": 4, 51 | "(": 5, 52 | ")": 6, 53 | ",": 7, 54 | "-": 8, 55 | ".": 9, 56 | "/": 10, 57 | ":": 11, 58 | ";": 12, 59 | "?": 13, 60 | "a": 14, 61 | "b": 15, 62 | "c": 16, 63 | "d": 17, 64 | "e": 18, 65 | "f": 19, 66 | "g": 20, 67 | "h": 21, 68 | "i": 22, 69 | "j": 23, 70 | "k": 24, 71 | "l": 25, 72 | "m": 26, 73 | "n": 27, 74 | "o": 28, 75 | "p": 29, 76 | "q": 30, 77 | "r": 31, 78 | "s": 32, 79 | "t": 33, 80 | "u": 34, 81 | "v": 35, 82 | "w": 36, 83 | "x": 37, 84 | "y": 38, 85 | "z": 39, 86 | "d͡": 40, 87 | "t͡": 41, 88 | "|": 42, 89 | "æ": 43, 90 | "ð": 44, 91 | "ŋ": 45, 92 | "ɑ": 46, 93 | "ɔ": 47, 94 | "ə": 48, 95 | "ɚ": 49, 96 | "ɛ": 50, 97 | "ɡ": 51, 98 | "ɪ": 52, 99 | "ɹ": 53, 100 | "ʃ": 54, 101 | "ʊ": 55, 102 | "ʌ": 56, 103 | "ʒ": 57, 104 | "θ": 58, 105 | "ɐ": 59, 106 | "ɜ": 60, 107 | "ᵻ": 61, 108 | "ɾ": 62, 109 | "n\u0329": 63, 110 | "ː": 64, 111 | "ˈ": 65, 112 | "ˌ": 66, 113 | "ʔ": 67, 114 | "d͡ʒ": 68, 115 | "aɪ": 69, 116 | "aʊ": 70, 117 | "eɪ": 71, 118 | "oʊ": 72, 119 | "t͡ʃ": 73, 120 | "ɔɪ": 74, 121 | "ɔː": 75, 122 | "uː": 76, 123 | "iː": 77, 124 | "ɑː": 78, 125 | "oː": 79, 126 | "ɜː": 80 127 | }, 128 | "merges": [ 129 | "a ɪ", 130 | "e ɪ", 131 | "ɔ ɪ", 132 | "a ʊ", 133 | "o ʊ", 134 | "d͡ ʒ", 135 | "t͡ ʃ", 136 | "i ː", 137 | "o ː", 138 | "u ː", 139 | "ɑ ː", 140 | "ɔ ː", 141 | "ɜ ː" 142 | ] 143 | } 144 | } -------------------------------------------------------------------------------- /models/tortoise/train_diffusion_vocoder_22k_level.yml: -------------------------------------------------------------------------------- 1 | path: 2 | pretrain_model_dvae: './models/tortoise/dvae.pth' 3 | strict_load: true 4 | #resume_state: ../experiments/train_imgnet_vqvae_stage1/training_state/0.state # <-- Set this to resume from a previous training state. 5 | networks: 6 | dvae: 7 | type: generator 8 | which_model_G: lucidrains_dvae 9 | kwargs: 10 | channels: 80 11 | codebook_dim: 512 12 | hidden_dim: 512 13 | kernel_size: 3 14 | num_layers: 2 15 | num_resnet_blocks: 3 16 | num_tokens: 8192 17 | positional_dims: 1 18 | use_transposed_convs: false 19 | -------------------------------------------------------------------------------- /modules/.gitignore: -------------------------------------------------------------------------------- 1 | bitsandbytes-windows/ -------------------------------------------------------------------------------- /modules/rvc/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | __pycache__ 3 | /TEMP 4 | *.pyd 5 | .venv 6 | /opt 7 | tools/aria2c/ 8 | tools/flag.txt 9 | venv/ 10 | 11 | # Imported from huggingface.co/lj1995/VoiceConversionWebUI 12 | /pretrained 13 | /pretrained_v2 14 | /uvr5_weights 15 | hubert_base.pt 16 | rmvpe.onnx 17 | rmvpe.pt 18 | assets/ 19 | 20 | # Generated by RVC 21 | /logs 22 | /weights 23 | 24 | # To set a Python version for the project 25 | .tool-versions 26 | -------------------------------------------------------------------------------- /modules/rvc/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM nvidia/cuda:11.6.2-cudnn8-runtime-ubuntu20.04 4 | 5 | EXPOSE 7865 6 | 7 | WORKDIR /app 8 | 9 | COPY . . 10 | 11 | # Install dependenceis to add PPAs 12 | RUN apt-get update && \ 13 | apt-get install -y -qq ffmpeg aria2 && apt clean && \ 14 | apt-get install -y software-properties-common && \ 15 | apt-get clean && \ 16 | rm -rf /var/lib/apt/lists/* 17 | 18 | # Add the deadsnakes PPA to get Python 3.9 19 | RUN add-apt-repository ppa:deadsnakes/ppa 20 | 21 | # Install Python 3.9 and pip 22 | RUN apt-get update && \ 23 | apt-get install -y build-essential python-dev python3-dev python3.9-distutils python3.9-dev python3.9 curl && \ 24 | apt-get clean && \ 25 | update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 && \ 26 | curl https://bootstrap.pypa.io/get-pip.py | python3.9 27 | 28 | # Set Python 3.9 as the default 29 | RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1 30 | 31 | RUN python3 -m pip install --no-cache-dir -r requirements.txt 32 | 33 | 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 34 | 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 35 | 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 36 | 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 37 | 38 | 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 39 | 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 40 | 41 | 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 42 | 43 | RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d assets/rmvpe -o rmvpe.pt 44 | 45 | VOLUME [ "/app/weights", "/app/opt" ] 46 | 47 | CMD ["python3", "infer-web.py"] 48 | -------------------------------------------------------------------------------- /modules/rvc/LICENSE: -------------------------------------------------------------------------------- 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. 24 | -------------------------------------------------------------------------------- /modules/rvc/MIT协议暨相关引用库协议: -------------------------------------------------------------------------------- 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 46 | -------------------------------------------------------------------------------- /modules/rvc/README.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | This is a fork of RVC and may not contain the latest features. It is mainly used in my projects so that I have an "rvc package" that is useable for functions that I need. 3 | - I removed fairseq, so this needs to be manually installed or use the prebuilt wheels file 4 | 5 |
6 | 7 |

Retrieval-based-Voice-Conversion-WebUI

8 | 一个基于VITS的简单易用的语音转换(变声器)框架

9 | 10 | [![madewithlove](https://img.shields.io/badge/made_with-%E2%9D%A4-red?style=for-the-badge&labelColor=orange 11 | )](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) 12 | 13 |
14 | 15 | [![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) 16 | [![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) 17 | [![Huggingface](https://img.shields.io/badge/🤗%20-Spaces-yellow.svg?style=for-the-badge)](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/) 18 | 19 | [![Discord](https://img.shields.io/badge/RVC%20Developers-Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/HcsmBBGyVk) 20 | 21 | [**更新日志**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/Changelog_CN.md) | [**常见问题解答**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E8%A7%A3%E7%AD%94) | [**AutoDL·5毛钱训练AI歌手**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/Autodl%E8%AE%AD%E7%BB%83RVC%C2%B7AI%E6%AD%8C%E6%89%8B%E6%95%99%E7%A8%8B) | [**对照实验记录**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/Autodl%E8%AE%AD%E7%BB%83RVC%C2%B7AI%E6%AD%8C%E6%89%8B%E6%95%99%E7%A8%8B](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/wiki/%E5%AF%B9%E7%85%A7%E5%AE%9E%E9%AA%8C%C2%B7%E5%AE%9E%E9%AA%8C%E8%AE%B0%E5%BD%95)) | [**在线演示**](https://huggingface.co/spaces/Ricecake123/RVC-demo) 22 | 23 |
24 | 25 | ------ 26 | 27 | [**English**](./docs/en/README.en.md) | [**中文简体**](./README.md) | [**日本語**](./docs/jp/README.ja.md) | [**한국어**](./docs/kr/README.ko.md) ([**韓國語**](./docs/kr/README.ko.han.md)) | [**Français**](./docs/fr/README.fr.md)| [**Türkçe**](./docs/tr/README.tr.md) 28 | 29 | 点此查看我们的[演示视频](https://www.bilibili.com/video/BV1pm4y1z7Gm/) ! 30 | 31 | > 使用了RVC的实时语音转换: [w-okada/voice-changer](https://github.com/w-okada/voice-changer) 32 | 33 | > 底模使用接近50小时的开源高质量VCTK训练集训练,无版权方面的顾虑,请大家放心使用 34 | 35 | > 请期待RVCv3的底模,参数更大,数据更大,效果更好,基本持平的推理速度,需要训练数据量更少。 36 | 37 | ## 简介 38 | 本仓库具有以下特点 39 | + 使用top1检索替换输入源特征为训练集特征来杜绝音色泄漏 40 | + 即便在相对较差的显卡上也能快速训练 41 | + 使用少量数据进行训练也能得到较好结果(推荐至少收集10分钟低底噪语音数据) 42 | + 可以通过模型融合来改变音色(借助ckpt处理选项卡中的ckpt-merge) 43 | + 简单易用的网页界面 44 | + 可调用UVR5模型来快速分离人声和伴奏 45 | + 使用最先进的[人声音高提取算法InterSpeech2023-RMVPE](#参考项目)根绝哑音问题。效果最好(显著地)但比crepe_full更快、资源占用更小 46 | + A卡I卡加速支持 47 | 48 | ## 环境配置 49 | 以下指令需在 Python 版本大于3.8的环境中执行。 50 | 51 | (Windows/Linux) 52 | 首先通过 pip 安装主要依赖: 53 | ```bash 54 | # 安装Pytorch及其核心依赖,若已安装则跳过 55 | # 参考自: https://pytorch.org/get-started/locally/ 56 | pip install torch torchvision torchaudio 57 | 58 | #如果是win系统+Nvidia Ampere架构(RTX30xx),根据 #21 的经验,需要指定pytorch对应的cuda版本 59 | #pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117 60 | ``` 61 | 62 | 可以使用 poetry 来安装依赖: 63 | ```bash 64 | # 安装 Poetry 依赖管理工具, 若已安装则跳过 65 | # 参考自: https://python-poetry.org/docs/#installation 66 | curl -sSL https://install.python-poetry.org | python3 - 67 | 68 | # 通过poetry安装依赖 69 | poetry install 70 | ``` 71 | 72 | 你也可以通过 pip 来安装依赖: 73 | ```bash 74 | N卡: 75 | 76 | pip install -r requirements.txt 77 | 78 | A卡/I卡: 79 | pip install -r requirements-dml.txt 80 | 81 | ``` 82 | 83 | ------ 84 | Mac 用户可以通过 `run.sh` 来安装依赖: 85 | ```bash 86 | sh ./run.sh 87 | ``` 88 | 89 | ## 其他预模型准备 90 | RVC需要其他一些预模型来推理和训练。 91 | 92 | 你可以从我们的[Hugging Face space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)下载到这些模型。 93 | 94 | 以下是一份清单,包括了所有RVC所需的预模型和其他文件的名称: 95 | ```bash 96 | ./assets/hubert/hubert_base.pt 97 | 98 | ./assets/pretrained 99 | 100 | ./assets/uvr5_weights 101 | 102 | 想测试v2版本模型的话,需要额外下载 103 | 104 | ./assets/pretrained_v2 105 | 106 | 如果你正在使用Windows,则你可能需要这个文件,若ffmpeg和ffprobe已安装则跳过; ubuntu/debian 用户可以通过apt install ffmpeg来安装这2个库, Mac 用户则可以通过brew install ffmpeg来安装 (需要预先安装brew) 107 | 108 | ./ffmpeg 109 | 110 | https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe 111 | 112 | ./ffprobe 113 | 114 | https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe 115 | 116 | 如果你想使用最新的RMVPE人声音高提取算法,则你需要下载音高提取模型参数并放置于RVC根目录 117 | 118 | https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/rmvpe.pt 119 | 120 | A卡I卡用户需要的dml环境要请下载 121 | 122 | https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/rmvpe.onnx 123 | 124 | ``` 125 | 之后使用以下指令来启动WebUI: 126 | ```bash 127 | python infer-web.py 128 | ``` 129 | 130 | 如果你正在使用Windows 或 macOS,你可以直接下载并解压`RVC-beta.7z`,前者可以运行`go-web.bat`以启动WebUI,后者则运行命令`sh ./run.sh`以启动WebUI。 131 | 132 | 仓库内还有一份`小白简易教程.doc`以供参考。 133 | 134 | ## 参考项目 135 | + [ContentVec](https://github.com/auspicious3000/contentvec/) 136 | + [VITS](https://github.com/jaywalnut310/vits) 137 | + [HIFIGAN](https://github.com/jik876/hifi-gan) 138 | + [Gradio](https://github.com/gradio-app/gradio) 139 | + [FFmpeg](https://github.com/FFmpeg/FFmpeg) 140 | + [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui) 141 | + [audio-slicer](https://github.com/openvpi/audio-slicer) 142 | + [Vocal pitch extraction:RMVPE](https://github.com/Dream-High/RMVPE) 143 | + The pretrained model is trained and tested by [yxlllc](https://github.com/yxlllc/RMVPE) and [RVC-Boss](https://github.com/RVC-Boss). 144 | 145 | ## 感谢所有贡献者作出的努力 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /modules/rvc/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 10/6/2023 4 | I removed fairseq from requirements.txt as if you don't have microsoft build tools for c++ 2019, it will fail to install packages. This can be remedied by either installing the build tools, or using a prebuilt wheels (which is the approach I'm going to use for my applications that I distribute) 5 | - Added weights_only=True to all torch.load calls to help mitigate possible security issues with pickle. 6 | - I have not tested to see if the package will still work for training with this new parameter, but I will have to test this at a later time when I get to that fuctionality. -------------------------------------------------------------------------------- /modules/rvc/configs/config.json: -------------------------------------------------------------------------------- 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 | } 16 | -------------------------------------------------------------------------------- /modules/rvc/configs/v1/32k.json: -------------------------------------------------------------------------------- 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 | } 47 | -------------------------------------------------------------------------------- /modules/rvc/configs/v1/40k.json: -------------------------------------------------------------------------------- 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 | } 47 | -------------------------------------------------------------------------------- /modules/rvc/configs/v1/48k.json: -------------------------------------------------------------------------------- 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 | } 47 | -------------------------------------------------------------------------------- /modules/rvc/configs/v2/32k.json: -------------------------------------------------------------------------------- 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 | } 47 | -------------------------------------------------------------------------------- /modules/rvc/configs/v2/48k.json: -------------------------------------------------------------------------------- 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 | } 47 | -------------------------------------------------------------------------------- /modules/rvc/docker-compose.yml: -------------------------------------------------------------------------------- 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 14 | deploy: 15 | resources: 16 | reservations: 17 | devices: 18 | - driver: nvidia 19 | count: 1 20 | capabilities: [gpu] -------------------------------------------------------------------------------- /modules/rvc/docs/cn/Changelog_CN.md: -------------------------------------------------------------------------------- 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 | 97 | -------------------------------------------------------------------------------- /modules/rvc/docs/cn/faq.md: -------------------------------------------------------------------------------- 1 | ## Q1:ffmpeg error/utf8 error. 2 | 3 | 大概率不是ffmpeg问题,而是音频路径问题;
4 | ffmpeg读取路径带空格、()等特殊符号,可能出现ffmpeg error;训练集音频带中文路径,在写入filelist.txt的时候可能出现utf8 error;
5 | 6 | ## Q2:一键训练结束没有索引 7 | 8 | 显示"Training is done. The program is closed."则模型训练成功,后续紧邻的报错是假的;
9 | 10 | 一键训练结束完成没有added开头的索引文件,可能是因为训练集太大卡住了添加索引的步骤;已通过批处理add索引解决内存add索引对内存需求过大的问题。临时可尝试再次点击"训练索引"按钮。
11 | 12 | ## Q3:训练结束推理没看到训练集的音色 13 | 点刷新音色再看看,如果还没有看看训练有没有报错,控制台和webui的截图,logs/实验名下的log,都可以发给开发者看看。
14 | 15 | ## Q4:如何分享模型 16 |   rvc_root/logs/实验名 下面存储的pth不是用来分享模型用来推理的,而是为了存储实验状态供复现,以及继续训练用的。用来分享的模型应该是weights文件夹下大小为60+MB的pth文件;
17 |   后续将把weights/exp_name.pth和logs/exp_name/added_xxx.index合并打包成weights/exp_name.zip省去填写index的步骤,那么zip文件用来分享,不要分享pth文件,除非是想换机器继续训练;
18 |   如果你把logs文件夹下的几百MB的pth文件复制/分享到weights文件夹下强行用于推理,可能会出现f0,tgt_sr等各种key不存在的报错。你需要用ckpt选项卡最下面,手工或自动(本地logs下如果能找到相关信息则会自动)选择是否携带音高、目标音频采样率的选项后进行ckpt小模型提取(输入路径填G开头的那个),提取完在weights文件夹下会出现60+MB的pth文件,刷新音色后可以选择使用。
19 | 20 | ## Q5:Connection Error. 21 | 也许你关闭了控制台(黑色窗口)。
22 | 23 | ## Q6:WebUI弹出Expecting value: line 1 column 1 (char 0). 24 | 请关闭系统局域网代理/全局代理。
25 | 26 | 这个不仅是客户端的代理,也包括服务端的代理(例如你使用autodl设置了http_proxy和https_proxy学术加速,使用时也需要unset关掉)
27 | 28 | ## Q7:不用WebUI如何通过命令训练推理 29 | 训练脚本:
30 | 可先跑通WebUI,消息窗内会显示数据集处理和训练用命令行;
31 | 32 | 推理脚本:
33 | https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/mymodules.rvc.infer.py
34 | 35 | 例子:
36 | 37 | runtime\python.exe mymodules.rvc.infer.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
38 | 39 | f0up_key=sys.argv[1]
40 | input_path=sys.argv[2]
41 | index_path=sys.argv[3]
42 | f0method=sys.argv[4]#harvest or pm
43 | opt_path=sys.argv[5]
44 | model_path=sys.argv[6]
45 | index_rate=float(sys.argv[7])
46 | device=sys.argv[8]
47 | is_half=bool(sys.argv[9])
48 | 49 | ## Q8:Cuda error/Cuda out of memory. 50 | 小概率是cuda配置问题、设备不支持;大概率是显存不够(out of memory);
51 | 52 | 训练的话缩小batch size(如果缩小到1还不够只能更换显卡训练),推理的话酌情缩小config.py结尾的x_pad,x_query,x_center,x_max。4G以下显存(例如1060(3G)和各种2G显卡)可以直接放弃,4G显存显卡还有救。
53 | 54 | ## Q9:total_epoch调多少比较好 55 | 56 | 如果训练集音质差底噪大,20~30足够了,调太高,底模音质无法带高你的低音质训练集
57 | 如果训练集音质高底噪低时长多,可以调高,200是ok的(训练速度很快,既然你有条件准备高音质训练集,显卡想必条件也不错,肯定不在乎多一些训练时间)
58 | 59 | ## Q10:需要多少训练集时长 60 |   推荐10min至50min
61 |   保证音质高底噪低的情况下,如果有个人特色的音色统一,则多多益善
62 |   高水平的训练集(精简+音色有特色),5min至10min也是ok的,仓库作者本人就经常这么玩
63 |   也有人拿1min至2min的数据来训练并且训练成功的,但是成功经验是其他人不可复现的,不太具备参考价值。这要求训练集音色特色非常明显(比如说高频气声较明显的萝莉少女音),且音质高;
64 |   1min以下时长数据目前没见有人尝试(成功)过。不建议进行这种鬼畜行为。
65 | 66 | ## Q11:index rate干嘛用的,怎么调(科普) 67 |   如果底模和推理源的音质高于训练集的音质,他们可以带高推理结果的音质,但代价可能是音色往底模/推理源的音色靠,这种现象叫做"音色泄露";
68 |   index rate用来削减/解决音色泄露问题。调到1,则理论上不存在推理源的音色泄露问题,但音质更倾向于训练集。如果训练集音质比推理源低,则index rate调高可能降低音质。调到0,则不具备利用检索混合来保护训练集音色的效果;
69 |   如果训练集优质时长多,可调高total_epoch,此时模型本身不太会引用推理源和底模的音色,很少存在"音色泄露"问题,此时index_rate不重要,你甚至可以不建立/分享index索引文件。
70 | 71 | ## Q11:推理怎么选gpu 72 | config.py文件里device cuda:后面选择卡号;
73 | 卡号和显卡的映射关系,在训练选项卡的显卡信息栏里能看到。
74 | 75 | ## Q12:如何推理训练中间保存的pth 76 | 通过ckpt选项卡最下面提取小模型。
77 | 78 | 79 | ## Q13:如何中断和继续训练 80 | 现阶段只能关闭WebUI控制台双击go-web.bat重启程序。网页参数也要刷新重新填写;
81 | 继续训练:相同网页参数点训练模型,就会接着上次的checkpoint继续训练。
82 | 83 | ## Q14:训练时出现文件页面/内存error 84 | 进程开太多了,内存炸了。你可能可以通过如下方式解决
85 | 1、"提取音高和处理数据使用的CPU进程数" 酌情拉低;
86 | 2、训练集音频手工切一下,不要太长。
87 | 88 | 89 | ## Q15:如何中途加数据训练 90 | 1、所有数据新建一个实验名;
91 | 2、拷贝上一次的最新的那个G和D文件(或者你想基于哪个中间ckpt训练,也可以拷贝中间的)到新实验名;下
92 | 3、一键训练新实验名,他会继续上一次的最新进度训练。
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)拷贝过去加速训练流程。 109 | -------------------------------------------------------------------------------- /modules/rvc/docs/en/faiss_tips_en.md: -------------------------------------------------------------------------------- 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. 103 | -------------------------------------------------------------------------------- /modules/rvc/docs/en/training_tips_en.md: -------------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------- /modules/rvc/docs/fr/training_tips_fr.md: -------------------------------------------------------------------------------- 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.``` 66 | -------------------------------------------------------------------------------- /modules/rvc/docs/jp/README.ja.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Retrieval-based-Voice-Conversion-WebUI

4 | VITSに基づく使いやすい音声変換(voice changer)framework

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 |
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 |
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 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /modules/rvc/docs/jp/faiss_tips_ja.md: -------------------------------------------------------------------------------- 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個の点について再計算が行われます。 102 | -------------------------------------------------------------------------------- /modules/rvc/docs/jp/training_tips_ja.md: -------------------------------------------------------------------------------- 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 | 65 | -------------------------------------------------------------------------------- /modules/rvc/docs/kr/Changelog_KO.md: -------------------------------------------------------------------------------- 1 | ### 2023-08-13 2 | 1-정기적인 버그 수정 3 | - 최소 총 에포크 수를 1로 변경하고, 최소 총 에포크 수를 2로 변경합니다. 4 | - 사전 훈련(pre-train) 모델을 사용하지 않는 훈련 오류 수정 5 | - 반주 보컬 분리 후 그래픽 메모리 지우기 6 | - 페이즈 저장 경로 절대 경로를 상대 경로로 변경 7 | - 공백이 포함된 경로 지원(훈련 세트 경로와 실험 이름 모두 지원되며 더 이상 오류가 보고되지 않음) 8 | - 파일 목록에서 필수 utf8 인코딩 취소 9 | - 실시간 음성 변경 중 faiss 검색으로 인한 CPU 소모 문제 해결 10 | 11 | 2-키 업데이트 12 | - 현재 가장 강력한 오픈 소스 보컬 피치 추출 모델 RMVPE를 훈련하고, 이를 RVC 훈련, 오프라인/실시간 추론에 사용하며, PyTorch/Onx/DirectML을 지원합니다. 13 | - 파이토치_DML을 통한 AMD 및 인텔 그래픽 카드 지원 14 | (1) 실시간 음성 변화 (2) 추론 (3) 보컬 반주 분리 (4) 현재 지원되지 않는 훈련은 CPU 훈련으로 전환, Onnx_Dml을 통한 gpu의 RMVPE 추론 지원 15 | 16 | ### 2023년 6월 18일 업데이트 17 | 18 | - v2 버전에서 새로운 32k와 48k 사전 학습 모델을 추가. 19 | - non-f0 모델들의 추론 오류 수정. 20 | - 학습 세트가 1시간을 넘어가는 경우, 인덱스 생성 단계에서 minibatch-kmeans을 사용해, 학습속도 가속화. 21 | - [huggingface](https://huggingface.co/spaces/lj1995/vocal2guitar)에서 vocal2guitar 제공. 22 | - 데이터 처리 단계에서 이상 값 자동으로 제거. 23 | - ONNX로 내보내는(export) 옵션 탭 추가. 24 | 25 | 업데이트에 적용되지 않았지만 시도한 것들 : 26 | 27 | - ~~시계열 차원을 추가하여 특징 검색을 진행했지만, 유의미한 효과는 없었습니다.~~ 28 | - ~~PCA 차원 축소를 추가하여 특징 검색을 진행했지만, 유의미한 효과는 없었습니다.~~ 29 | - ~~ONNX 추론을 지원하는 것에 실패했습니다. nsf 생성시, Pytorch가 필요하기 때문입니다.~~ 30 | - ~~훈련 중에 입력에 대한 음고, 성별, 이퀄라이저, 노이즈 등 무작위로 강화하는 것에, 유의미한 효과는 없었습니다.~~ 31 | 32 | 추후 업데이트 목록: 33 | 34 | - ~~Vocos-RVC (소형 보코더) 통합 예정.~~ 35 | - ~~학습 단계에 음고 인식을 위한 Crepe 지원 예정.~~ 36 | - ~~Crepe의 정밀도를 REC-config와 동기화하여 지원 예정.~~ 37 | - FO 에디터 지원 예정. 38 | 39 | ### 2023년 5월 28일 업데이트 40 | 41 | - v2 jupyter notebook 추가, 한국어 업데이트 로그 추가, 의존성 모듈 일부 수정. 42 | - 무성음 및 숨소리 보호 모드 추가. 43 | - crepe-full pitch 감지 지원. 44 | - UVR5 보컬 분리: 디버브 및 디-에코 모델 지원. 45 | - index 이름에 experiment 이름과 버전 추가. 46 | - 배치 음성 변환 처리 및 UVR5 보컬 분리 시, 사용자가 수동으로 출력 오디오의 내보내기(export) 형식을 선택할 수 있도록 지원. 47 | - 32k 훈련 모델 지원 종료. 48 | 49 | ### 2023년 5월 13일 업데이트 50 | 51 | - 원클릭 패키지의 이전 버전 런타임 내, 불필요한 코드(lib.infer_pack 및 uvr5_pack) 제거. 52 | - 훈련 세트 전처리의 유사 다중 처리 버그 수정. 53 | - Harvest 피치 인식 알고리즘에 대한 중위수 필터링 반경 조정 추가. 54 | - 오디오 내보낼 때, 후처리 리샘플링 지원. 55 | - 훈련에 대한 다중 처리 "n_cpu" 설정이 "f0 추출"에서 "데이터 전처리 및 f0 추출"로 변경. 56 | - logs 폴더 하의 인덱스 경로를 자동으로 감지 및 드롭다운 목록 기능 제공. 57 | - 탭 페이지에 "자주 묻는 질문과 답변" 추가. (github RVC wiki 참조 가능) 58 | - 동일한 입력 오디오 경로를 사용할 때 추론, Harvest 피치를 캐시. 59 | (주의: Harvest 피치 추출을 사용하면 전체 파이프라인은 길고 반복적인 피치 추출 과정을 거치게됩니다. 캐싱을 하지 않는다면, 첫 inference 이후의 단계에서 timbre, 인덱스, 피치 중위수 필터링 반경 설정 등 대기시간이 엄청나게 길어집니다!) 60 | 61 | ### 2023년 5월 14일 업데이트 62 | 63 | - 입력의 볼륨 캡슐을 사용하여 출력의 볼륨 캡슐을 혼합하거나 대체. (입력이 무음이거나 출력의 노이즈 문제를 최소화 할 수 있습니다. 입력 오디오의 배경 노이즈(소음)가 큰 경우 해당 기능을 사용하지 않는 것이 좋습니다. 기본적으로 비활성화 되어있는 옵션입니다. (1: 비활성화 상태)) 64 | - 추출된 소형 모델을 지정된 빈도로 저장하는 기능을 지원. (다양한 에폭 하에서의 성능을 보려고 하지만 모든 대형 체크포인트를 저장하고 매번 ckpt 처리를 통해 소형 모델을 수동으로 추출하고 싶지 않은 경우 이 기능은 매우 유용합니다) 65 | - 환경 변수를 설정하여 서버의 전역 프록시로 인한 "연결 오류" 문제 해결. 66 | - 사전 훈련된 v2 모델 지원. (현재 40k 버전만 테스트를 위해 공개적으로 사용 가능하며, 다른 두 개의 샘플링 비율은 아직 완전히 훈련되지 않아 보류되었습니다.) 67 | - 추론 전, 1을 초과하는 과도한 볼륨 제한. 68 | - 데이터 전처리 매개변수 미세 조정. 69 | 70 | ### 2023년 4월 9일 업데이트 71 | 72 | - GPU 이용률 향상을 위해 훈련 파라미터 수정: A100은 25%에서 약 90%로 증가, V100: 50%에서 약 90%로 증가, 2060S: 60%에서 약 85%로 증가, P40: 25%에서 약 95%로 증가. 73 | 훈련 속도가 크게 향상. 74 | - 매개변수 기준 변경: total batch_size는 GPU당 batch_size를 의미. 75 | - total_epoch 변경: 최대 한도가 100에서 1000으로 증가. 기본값이 10에서 20으로 증가. 76 | - ckpt 추출이 피치를 잘못 인식하여 비정상적인 추론을 유발하는 문제 수정. 77 | - 분산 훈련 과정에서 각 랭크마다 ckpt를 저장하는 문제 수정. 78 | - 특성 추출 과정에 나노 특성 필터링 적용. 79 | - 무음 입력/출력이 랜덤하게 소음을 생성하는 문제 수정. (이전 모델은 새 데이터셋으로 다시 훈련해야 합니다) 80 | 81 | ### 2023년 4월 16일 업데이트 82 | 83 | - 로컬 실시간 음성 변경 미니-GUI 추가, go-realtime-gui.bat를 더블 클릭하여 시작. 84 | - 훈련 및 추론 중 50Hz 이하의 주파수 대역에 대해 필터링 적용. 85 | - 훈련 및 추론의 pyworld 최소 피치 추출을 기본 80에서 50으로 낮춤. 이로 인해, 50-80Hz 사이의 남성 저음이 무음화되지 않습니다. 86 | - 시스템 지역에 따른 WebUI 언어 변경 지원. (현재 en_US, ja_JP, zh_CN, zh_HK, zh_SG, zh_TW를 지원하며, 지원되지 않는 경우 기본값은 en_US) 87 | - 일부 GPU의 인식 수정. (예: V100-16G 인식 실패, P4 인식 실패) 88 | 89 | ### 2023년 4월 28일 업데이트 90 | 91 | - Faiss 인덱스 설정 업그레이드로 속도가 더 빨라지고 품질이 향상. 92 | - total_npy에 대한 의존성 제거. 추후의 모델 공유는 total_npy 입력을 필요로 하지 않습니다. 93 | - 16 시리즈 GPU에 대한 제한 해제, 4GB VRAM GPU에 대한 4GB 추론 설정 제공. 94 | - 일부 오디오 형식에 대한 UVR5 보컬 동반 분리에서의 버그 수정. 95 | - 실시간 음성 변경 미니-GUI는 이제 non-40k 및 non-lazy 피치 모델을 지원합니다. 96 | 97 | ### 추후 계획 98 | 99 | Features: 100 | 101 | - 다중 사용자 훈련 탭 지원.(최대 4명) 102 | 103 | Base model: 104 | 105 | - 훈련 데이터셋에 숨소리 wav 파일을 추가하여, 보컬의 호흡이 노이즈로 변환되는 문제 수정. 106 | - 보컬 훈련 세트의 기본 모델을 추가하기 위한 작업을 진행중이며, 이는 향후에 발표될 예정. 107 | -------------------------------------------------------------------------------- /modules/rvc/docs/kr/README.ko.han.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Retrieval-based-Voice-Conversion-WebUI

4 | VITS基盤의 簡單하고使用하기 쉬운音聲變換틀

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 |
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 |
18 | 19 | ------ 20 | [**更新日誌**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/Changelog_KO.md) 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 | > [示範映像](https://www.bilibili.com/video/BV1pm4y1z7Gm/)을 確認해 보세요! 25 | 26 | > RVC를活用한實時間音聲變換: [w-okada/voice-changer](https://github.com/w-okada/voice-changer) 27 | 28 | > 基本모델은 50時間假量의 高品質 오픈 소스 VCTK 데이터셋을 使用하였으므로, 著作權上의 念慮가 없으니 安心하고 使用하시기 바랍니다. 29 | 30 | > 著作權問題가 없는 高品質의 노래를 以後에도 繼續해서 訓練할 豫定입니다. 31 | 32 | ## 紹介 33 | 本Repo는 다음과 같은 特徵을 가지고 있습니다: 34 | + top1檢索을利用하여 入力音色特徵을 訓練세트音色特徵으로 代替하여 音色의漏出을 防止; 35 | + 相對的으로 낮은性能의 GPU에서도 빠른訓練可能; 36 | + 적은量의 데이터로 訓練해도 좋은 結果를 얻을 수 있음 (最小10分以上의 低雜음音聲데이터를 使用하는 것을 勸獎); 37 | + 모델融合을通한 音色의 變調可能 (ckpt處理탭->ckpt混合選擇); 38 | + 使用하기 쉬운 WebUI (웹 使用者인터페이스); 39 | + UVR5 모델을 利用하여 목소리와 背景音樂의 빠른 分離; 40 | 41 | ## 環境의準備 42 | poetry를通해 依存를設置하는 것을 勸獎합니다. 43 | 44 | 다음命令은 Python 버전3.8以上의環境에서 實行되어야 합니다: 45 | ```bash 46 | # PyTorch 關聯主要依存設置, 이미設置되어 있는 境遇 건너뛰기 可能 47 | # 參照: https://pytorch.org/get-started/locally/ 48 | pip install torch torchvision torchaudio 49 | 50 | # Windows + Nvidia Ampere Architecture(RTX30xx)를 使用하고 있다面, #21 에서 명시된 것과 같이 PyTorch에 맞는 CUDA 버전을 指定해야 합니다. 51 | #pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117 52 | 53 | # Poetry 設置, 이미設置되어 있는 境遇 건너뛰기 可能 54 | # Reference: https://python-poetry.org/docs/#installation 55 | curl -sSL https://install.python-poetry.org | python3 - 56 | 57 | # 依存設置 58 | poetry install 59 | ``` 60 | pip를 活用하여依存를 設置하여도 無妨합니다. 61 | 62 | ```bash 63 | pip install -r requirements.txt 64 | ``` 65 | 66 | ## 其他預備모델準備 67 | RVC 모델은 推論과訓練을 依하여 다른 預備모델이 必要합니다. 68 | 69 | [Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 通해서 다운로드 할 수 있습니다. 70 | 71 | 다음은 RVC에 必要한 預備모델 및 其他 파일 目錄입니다: 72 | ```bash 73 | ./assets/hubert/hubert_base.pt 74 | 75 | ./assets/pretrained 76 | 77 | ./assets/uvr5_weights 78 | 79 | V2 버전 모델을 테스트하려면 추가 다운로드가 필요합니다. 80 | 81 | ./assets/pretrained_v2 82 | 83 | # Windows를 使用하는境遇 이 사전도 必要할 수 있습니다. FFmpeg가 設置되어 있으면 건너뛰어도 됩니다. 84 | ffmpeg.exe 85 | ``` 86 | 그後 以下의 命令을 使用하여 WebUI를 始作할 수 있습니다: 87 | ```bash 88 | python infer-web.py 89 | ``` 90 | Windows를 使用하는境遇 `RVC-beta.7z`를 다운로드 및 壓縮解除하여 RVC를 直接使用하거나 `go-web.bat`을 使用하여 WebUi를 直接할 수 있습니다. 91 | 92 | ## 參考 93 | + [ContentVec](https://github.com/auspicious3000/contentvec/) 94 | + [VITS](https://github.com/jaywalnut310/vits) 95 | + [HIFIGAN](https://github.com/jik876/hifi-gan) 96 | + [Gradio](https://github.com/gradio-app/gradio) 97 | + [FFmpeg](https://github.com/FFmpeg/FFmpeg) 98 | + [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui) 99 | + [audio-slicer](https://github.com/openvpi/audio-slicer) 100 | ## 모든寄與者분들의勞力에感謝드립니다 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /modules/rvc/docs/kr/README.ko.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Retrieval-based-Voice-Conversion-WebUI

4 | VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.

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 |
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 |
18 | 19 | --- 20 | 21 | [**업데이트 로그**](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/Changelog_KO.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시간 가량의 고퀄리티 오픈 소스 VCTK 데이터셋을 사용하였으므로, 저작권상의 염려가 없으니 안심하고 사용하시기 바랍니다. 30 | 31 | > 저작권 문제가 없는 고퀄리티의 노래를 이후에도 계속해서 훈련할 예정입니다. 32 | 33 | ## 소개 34 | 35 | 본 Repo는 다음과 같은 특징을 가지고 있습니다: 36 | 37 | - top1 검색을 이용하여 입력 음색 특징을 훈련 세트 음색 특징으로 대체하여 음색의 누출을 방지; 38 | - 상대적으로 낮은 성능의 GPU에서도 빠른 훈련 가능; 39 | - 적은 양의 데이터로 훈련해도 좋은 결과를 얻을 수 있음 (최소 10분 이상의 저잡음 음성 데이터를 사용하는 것을 권장); 40 | - 모델 융합을 통한 음색의 변조 가능 (ckpt 처리 탭->ckpt 병합 선택); 41 | - 사용하기 쉬운 WebUI (웹 인터페이스); 42 | - UVR5 모델을 이용하여 목소리와 배경음악의 빠른 분리; 43 | 44 | ## 환경의 준비 45 | 46 | poetry를 통해 dependecies를 설치하는 것을 권장합니다. 47 | 48 | 다음 명령은 Python 버전 3.8 이상의 환경에서 실행되어야 합니다: 49 | 50 | ```bash 51 | # PyTorch 관련 주요 dependencies 설치, 이미 설치되어 있는 경우 건너뛰기 가능 52 | # 참조: https://pytorch.org/get-started/locally/ 53 | pip install torch torchvision torchaudio 54 | 55 | # Windows + Nvidia Ampere Architecture(RTX30xx)를 사용하고 있다면, https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/issues/21 에서 명시된 것과 같이 PyTorch에 맞는 CUDA 버전을 지정해야 합니다. 56 | #pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117 57 | 58 | # Poetry 설치, 이미 설치되어 있는 경우 건너뛰기 가능 59 | # Reference: https://python-poetry.org/docs/#installation 60 | curl -sSL https://install.python-poetry.org | python3 - 61 | 62 | # Dependecies 설치 63 | poetry install 64 | ``` 65 | 66 | pip를 활용하여 dependencies를 설치하여도 무방합니다. 67 | 68 | ```bash 69 | pip install -r requirements.txt 70 | ``` 71 | 72 | ## 기타 사전 모델 준비 73 | 74 | RVC 모델은 추론과 훈련을 위하여 다른 사전 모델이 필요합니다. 75 | 76 | [Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 통해서 다운로드 할 수 있습니다. 77 | 78 | 다음은 RVC에 필요한 사전 모델 및 기타 파일 목록입니다: 79 | 80 | ```bash 81 | ./assets/hubert/hubert_base.pt 82 | 83 | ./assets/pretrained 84 | 85 | ./assets/uvr5_weights 86 | 87 | V2 버전 모델을 테스트하려면 추가 다운로드가 필요합니다. 88 | 89 | ./assets/pretrained_v2 90 | 91 | # Windows를 사용하는 경우 이 사전도 필요할 수 있습니다. FFmpeg가 설치되어 있으면 건너뛰어도 됩니다. 92 | ffmpeg.exe 93 | ``` 94 | 95 | 그 후 이하의 명령을 사용하여 WebUI를 시작할 수 있습니다: 96 | 97 | ```bash 98 | python infer-web.py 99 | ``` 100 | 101 | Windows를 사용하는 경우 `RVC-beta.7z`를 다운로드 및 압축 해제하여 RVC를 직접 사용하거나 `go-web.bat`을 사용하여 WebUi를 시작할 수 있습니다. 102 | 103 | ## 참고 104 | 105 | - [ContentVec](https://github.com/auspicious3000/contentvec/) 106 | - [VITS](https://github.com/jaywalnut310/vits) 107 | - [HIFIGAN](https://github.com/jik876/hifi-gan) 108 | - [Gradio](https://github.com/gradio-app/gradio) 109 | - [FFmpeg](https://github.com/FFmpeg/FFmpeg) 110 | - [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui) 111 | - [audio-slicer](https://github.com/openvpi/audio-slicer) 112 | 113 | ## 모든 기여자 분들의 노력에 감사드립니다. 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /modules/rvc/docs/kr/faiss_tips_ko.md: -------------------------------------------------------------------------------- 1 | Facebook AI Similarity Search (Faiss) 팁 2 | ================== 3 | # Faiss에 대하여 4 | Faiss 는 Facebook Research가 개발하는, 고밀도 벡터 이웃 검색 라이브러리입니다. 근사 근접 탐색법 (Approximate Neigbor Search)은 약간의 정확성을 희생하여 유사 벡터를 고속으로 찾습니다. 5 | 6 | ## RVC에 있어서 Faiss 7 | RVC에서는 HuBERT로 변환한 feature의 embedding을 위해 훈련 데이터에서 생성된 embedding과 유사한 embadding을 검색하고 혼합하여 원래의 음성에 더욱 가까운 변환을 달성합니다. 그러나, 이 탐색법은 단순히 수행하면 시간이 다소 소모되므로, 근사 근접 탐색법을 통해 고속 변환을 가능케 하고 있습니다. 8 | 9 | # 구현 개요 10 | 모델이 위치한 `/logs/your-experiment/3_feature256`에는 각 음성 데이터에서 HuBERT가 추출한 feature들이 있습니다. 여기에서 파일 이름별로 정렬된 npy 파일을 읽고, 벡터를 연결하여 big_npy ([N, 256] 모양의 벡터) 를 만듭니다. big_npy를 `/logs/your-experiment/total_fea.npy`로 저장한 후, Faiss로 학습시킵니다. 11 | 12 | 2023/04/18 기준으로, Faiss의 Index Factory 기능을 이용해, L2 거리에 근거하는 IVF를 이용하고 있습니다. IVF의 분할수(n_ivf)는 N//39로, n_probe는 int(np.power(n_ivf, 0.3))가 사용되고 있습니다. (infer-web.py의 train_index 주위를 찾으십시오.) 13 | 14 | 이 팁에서는 먼저 이러한 매개 변수의 의미를 설명하고, 개발자가 추후 더 나은 index를 작성할 수 있도록 하는 조언을 작성합니다. 15 | 16 | # 방법의 설명 17 | ## Index factory 18 | index factory는 여러 근사 근접 탐색법을 문자열로 연결하는 pipeline을 문자열로 표기하는 Faiss만의 독자적인 기법입니다. 이를 통해 index factory의 문자열을 변경하는 것만으로 다양한 근사 근접 탐색을 시도해 볼 수 있습니다. RVC에서는 다음과 같이 사용됩니다: 19 | 20 | ```python 21 | index = Faiss.index_factory(256, "IVF%s,Flat" % n_ivf) 22 | ``` 23 | `index_factory`의 인수들 중 첫 번째는 벡터의 차원 수이고, 두번째는 index factory 문자열이며, 세번째에는 사용할 거리를 지정할 수 있습니다. 24 | 25 | 기법의 보다 자세한 설명은 https://github.com/facebookresearch/Faiss/wiki/The-index-factory 를 확인해 주십시오. 26 | 27 | ## 거리에 대한 index 28 | embedding의 유사도로서 사용되는 대표적인 지표로서 이하의 2개가 있습니다. 29 | 30 | - 유클리드 거리 (METRIC_L2) 31 | - 내적(内積) (METRIC_INNER_PRODUCT) 32 | 33 | 유클리드 거리에서는 각 차원에서 제곱의 차를 구하고, 각 차원에서 구한 차를 모두 더한 후 제곱근을 취합니다. 이것은 일상적으로 사용되는 2차원, 3차원에서의 거리의 연산법과 같습니다. 내적은 그 값을 그대로 유사도 지표로 사용하지 않고, L2 정규화를 한 이후 내적을 취하는 코사인 유사도를 사용합니다. 34 | 35 | 어느 쪽이 더 좋은지는 경우에 따라 다르지만, word2vec에서 얻은 embedding 및 ArcFace를 활용한 이미지 검색 모델은 코사인 유사성이 이용되는 경우가 많습니다. numpy를 사용하여 벡터 X에 대해 L2 정규화를 하고자 하는 경우, 0 division을 피하기 위해 충분히 작은 값을 eps로 한 뒤 이하에 코드를 활용하면 됩니다. 36 | 37 | ```python 38 | X_normed = X / np.maximum(eps, np.linalg.norm(X, ord=2, axis=-1, keepdims=True)) 39 | ``` 40 | 41 | 또한, `index factory`의 3번째 인수에 건네주는 값을 선택하는 것을 통해 계산에 사용하는 거리 index를 변경할 수 있습니다. 42 | 43 | ```python 44 | index = Faiss.index_factory(dimention, text, Faiss.METRIC_INNER_PRODUCT) 45 | ``` 46 | 47 | ## IVF 48 | IVF (Inverted file indexes)는 역색인 탐색법과 유사한 알고리즘입니다. 학습시에는 검색 대상에 대해 k-평균 군집법을 실시하고 클러스터 중심을 이용해 보로노이 분할을 실시합니다. 각 데이터 포인트에는 클러스터가 할당되므로, 클러스터에서 데이터 포인트를 조회하는 dictionary를 만듭니다. 49 | 50 | 예를 들어, 클러스터가 다음과 같이 할당된 경우 51 | |index|Cluster| 52 | |-----|-------| 53 | |1|A| 54 | |2|B| 55 | |3|A| 56 | |4|C| 57 | |5|B| 58 | 59 | IVF 이후의 결과는 다음과 같습니다: 60 | 61 | |cluster|index| 62 | |-------|-----| 63 | |A|1, 3| 64 | |B|2, 5| 65 | |C|4| 66 | 67 | 탐색 시, 우선 클러스터에서 `n_probe`개의 클러스터를 탐색한 다음, 각 클러스터에 속한 데이터 포인트의 거리를 계산합니다. 68 | 69 | # 권장 매개변수 70 | index의 선택 방법에 대해서는 공식적으로 가이드 라인이 있으므로, 거기에 준해 설명합니다. 71 | https://github.com/facebookresearch/Faiss/wiki/Guidelines-to-choose-an-index 72 | 73 | 1M 이하의 데이터 세트에 있어서는 4bit-PQ가 2023년 4월 시점에서는 Faiss로 이용할 수 있는 가장 효율적인 수법입니다. 이것을 IVF와 조합해, 4bit-PQ로 후보를 추려내고, 마지막으로 이하의 index factory를 이용하여 정확한 지표로 거리를 재계산하면 됩니다. 74 | 75 | ```python 76 | index = Faiss.index_factory(256, "IVF1024,PQ128x4fs,RFlat") 77 | ``` 78 | 79 | ## IVF 권장 매개변수 80 | IVF의 수가 너무 많으면, 가령 데이터 수의 수만큼 IVF로 양자화(Quantization)를 수행하면, 이것은 완전탐색과 같아져 효율이 나빠지게 됩니다. 1M 이하의 경우 IVF 값은 데이터 포인트 수 N에 대해 4sqrt(N) ~ 16sqrt(N)를 사용하는 것을 권장합니다. 81 | 82 | n_probe는 n_probe의 수에 비례하여 계산 시간이 늘어나므로 정확도와 시간을 적절히 균형을 맞추어 주십시오. 개인적으로 RVC에 있어서 그렇게까지 정확도는 필요 없다고 생각하기 때문에 n_probe = 1이면 된다고 생각합니다. 83 | 84 | ## FastScan 85 | FastScan은 직적 양자화를 레지스터에서 수행함으로써 거리의 고속 근사를 가능하게 하는 방법입니다.직적 양자화는 학습시에 d차원마다(보통 d=2)에 독립적으로 클러스터링을 실시해, 클러스터끼리의 거리를 사전 계산해 lookup table를 작성합니다. 예측시는 lookup table을 보면 각 차원의 거리를 O(1)로 계산할 수 있습니다. 따라서 PQ 다음에 지정하는 숫자는 일반적으로 벡터의 절반 차원을 지정합니다. 86 | 87 | FastScan에 대한 자세한 설명은 공식 문서를 참조하십시오. 88 | https://github.com/facebookresearch/Faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan) 89 | 90 | ## RFlat 91 | RFlat은 FastScan이 계산한 대략적인 거리를 index factory의 3번째 인수로 지정한 정확한 거리로 다시 계산하라는 인스트럭션입니다. k개의 근접 변수를 가져올 때 k*k_factor개의 점에 대해 재계산이 이루어집니다. 92 | 93 | # Embedding 테크닉 94 | ## Alpha 쿼리 확장 95 | 퀴리 확장이란 탐색에서 사용되는 기술로, 예를 들어 전문 탐색 시, 입력된 검색문에 단어를 몇 개를 추가함으로써 검색 정확도를 올리는 방법입니다. 백터 탐색을 위해서도 몇가지 방법이 제안되었는데, 그 중 α-쿼리 확장은 추가 학습이 필요 없는 매우 효과적인 방법으로 알려져 있습니다. [Attention-Based Query Expansion Learning](https://arxiv.org/abs/2007.08019)와 [2nd place solution of kaggle shopee competition](https://www.kaggle.com/code/lyakaap/2nd-place-solution/notebook) 논문에서 소개된 바 있습니다.. 96 | 97 | α-쿼리 확장은 한 벡터에 인접한 벡터를 유사도의 α곱한 가중치로 더해주면 됩니다. 코드로 예시를 들어 보겠습니다. big_npy를 α query expansion로 대체합니다. 98 | 99 | ```python 100 | alpha = 3. 101 | index = Faiss.index_factory(256, "IVF512,PQ128x4fs,RFlat") 102 | original_norm = np.maximum(np.linalg.norm(big_npy, ord=2, axis=1, keepdims=True), 1e-9) 103 | big_npy /= original_norm 104 | index.train(big_npy) 105 | index.add(big_npy) 106 | dist, neighbor = index.search(big_npy, num_expand) 107 | 108 | expand_arrays = [] 109 | ixs = np.arange(big_npy.shape[0]) 110 | for i in range(-(-big_npy.shape[0]//batch_size)): 111 | ix = ixs[i*batch_size:(i+1)*batch_size] 112 | weight = np.power(np.einsum("nd,nmd->nm", big_npy[ix], big_npy[neighbor[ix]]), alpha) 113 | expand_arrays.append(np.sum(big_npy[neighbor[ix]] * np.expand_dims(weight, axis=2),axis=1)) 114 | big_npy = np.concatenate(expand_arrays, axis=0) 115 | 116 | # index version 정규화 117 | big_npy = big_npy / np.maximum(np.linalg.norm(big_npy, ord=2, axis=1, keepdims=True), 1e-9) 118 | ``` 119 | 120 | 위 테크닉은 탐색을 수행하는 쿼리에도, 탐색 대상 DB에도 적응 가능한 테크닉입니다. 121 | 122 | ## MiniBatch KMeans에 의한 embedding 압축 123 | 124 | total_fea.npy가 너무 클 경우 K-means를 이용하여 벡터를 작게 만드는 것이 가능합니다. 이하 코드로 embedding의 압축이 가능합니다. n_clusters에 압축하고자 하는 크기를 지정하고 batch_size에 256 * CPU의 코어 수를 지정함으로써 CPU 병렬화의 혜택을 충분히 얻을 수 있습니다. 125 | 126 | ```python 127 | import multiprocessing 128 | from sklearn.cluster import MiniBatchKMeans 129 | kmeans = MiniBatchKMeans(n_clusters=10000, batch_size=256 * multiprocessing.cpu_count(), init="random") 130 | kmeans.fit(big_npy) 131 | sample_npy = kmeans.cluster_centers_ 132 | ``` -------------------------------------------------------------------------------- /modules/rvc/docs/kr/training_tips_ko.md: -------------------------------------------------------------------------------- 1 | RVC 훈련에 대한 설명과 팁들 2 | ====================================== 3 | 본 팁에서는 어떻게 데이터 훈련이 이루어지고 있는지 설명합니다. 4 | 5 | # 훈련의 흐름 6 | GUI의 훈련 탭의 단계를 따라 설명합니다. 7 | 8 | ## step1 9 | 실험 이름을 지정합니다. 또한, 모델이 피치(소리의 높낮이)를 고려해야 하는지 여부를 여기에서 설정할 수도 있습니다.. 10 | 각 실험을 위한 데이터는 `/logs/experiment name/`에 배치됩니다.. 11 | 12 | ## step2a 13 | 음성 파일을 불러오고 전처리합니다. 14 | 15 | ### 음성 파일 불러오기 16 | 음성 파일이 있는 폴더를 지정하면 해당 폴더에 있는 음성 파일이 자동으로 가져와집니다. 17 | 예를 들어 `C:Users\hoge\voices`를 지정하면 `C:Users\hoge\voices\voice.mp3`가 읽히지만 `C:Users\hoge\voices\dir\voice.mp3`는 읽히지 않습니다. 18 | 19 | 음성 로드에는 내부적으로 ffmpeg를 이용하고 있으므로, ffmpeg로 대응하고 있는 확장자라면 자동적으로 읽힙니다. 20 | ffmpeg에서 int16으로 변환한 후 float32로 변환하고 -1과 1 사이에 정규화됩니다. 21 | 22 | ### 잡음 제거 23 | 음성 파일에 대해 scipy의 filtfilt를 이용하여 잡음을 처리합니다. 24 | 25 | ### 음성 분할 26 | 입력한 음성 파일은 먼저 일정 기간(max_sil_kept=5초?)보다 길게 무음이 지속되는 부분을 감지하여 음성을 분할합니다.무음으로 음성을 분할한 후에는 0.3초의 overlap을 포함하여 4초마다 음성을 분할합니다.4초 이내에 구분된 음성은 음량의 정규화를 실시한 후 wav 파일을 `/logs/실험명/0_gt_wavs`로, 거기에서 16k의 샘플링 레이트로 변환해 `/logs/실험명/1_16k_wavs`에 wav 파일로 저장합니다. 27 | 28 | ## step2b 29 | ### 피치 추출 30 | wav 파일에서 피치(소리의 높낮이) 정보를 추출합니다. parselmouth나 pyworld에 내장되어 있는 메서드으로 피치 정보(=f0)를 추출해, `/logs/실험명/2a_f0`에 저장합니다. 그 후 피치 정보를 로그로 변환하여 1~255 정수로 변환하고 `/logs/실험명/2b-f0nsf`에 저장합니다. 31 | 32 | ### feature_print 추출 33 | HuBERT를 이용하여 wav 파일을 미리 embedding으로 변환합니다. `/logs/실험명/1_16k_wavs`에 저장한 wav 파일을 읽고 HuBERT에서 wav 파일을 256차원 feature들로 변환한 후 npy 형식으로 `/logs/실험명/3_feature256`에 저장합니다. 34 | 35 | ## step3 36 | 모델의 훈련을 진행합니다. 37 | 38 | ### 초보자용 용어 해설 39 | 심층학습(딥러닝)에서는 데이터셋을 분할하여 조금씩 학습을 진행합니다.한 번의 모델 업데이트(step) 단계 당 batch_size개의 데이터를 탐색하여 예측과 오차를 수정합니다. 데이터셋 전부에 대해 이 작업을 한 번 수행하는 이를 하나의 epoch라고 계산합니다. 40 | 41 | 따라서 학습 시간은 단계당 학습 시간 x (데이터셋 내 데이터의 수 / batch size) x epoch 수가 소요됩니다. 일반적으로 batch size가 클수록 학습이 안정적이게 됩니다. (step당 학습 시간 ÷ batch size)는 작아지지만 GPU 메모리를 더 많이 사용합니다. GPU RAM은 nvidia-smi 명령어를 통해 확인할 수 있습니다. 실행 환경에 따라 배치 크기를 최대한 늘리면 짧은 시간 내에 학습이 가능합니다. 42 | 43 | ### 사전 학습된 모델 지정 44 | RVC는 적은 데이터셋으로도 훈련이 가능하도록 사전 훈련된 가중치에서 모델 훈련을 시작합니다. 기본적으로 `rvc-location/pretrained/f0G40k.pth` 및 `rvc-location/pretrained/f0D40k.pth`를 불러옵니다. 학습을 할 시에, 모델 파라미터는 각 save_every_epoch별로 `logs/experiment name/G_{}.pth` 와 `logs/experiment name/D_{}.pth`로 저장이 되는데, 이 경로를 지정함으로써 학습을 재개하거나, 다른 실험에서 학습한 모델의 가중치에서 학습을 시작할 수 있습니다. 45 | 46 | ### index의 학습 47 | RVC에서는 학습시에 사용된 HuBERT의 feature값을 저장하고, 추론 시에는 학습 시 사용한 feature값과 유사한 feature 값을 탐색해 추론을 진행합니다. 이 탐색을 고속으로 수행하기 위해 사전에 index을 학습하게 됩니다. 48 | Index 학습에는 근사 근접 탐색법 라이브러리인 Faiss를 사용하게 됩니다. `/logs/실험명/3_feature256`의 feature값을 불러와, 이를 모두 결합시킨 feature값을 `/logs/실험명/total_fea.npy`로서 저장, 그것을 사용해 학습한 index를`/logs/실험명/add_XXX.index`로 저장합니다. 49 | 50 | ### 버튼 설명 51 | - モデルのトレーニング (모델 학습): step2b까지 실행한 후, 이 버튼을 눌러 모델을 학습합니다. 52 | - 特徴インデックスのトレーニング (특징 지수 훈련): 모델의 훈련 후, index를 학습합니다. 53 | - ワンクリックトレーニング (원클릭 트레이닝): step2b까지의 모델 훈련, feature index 훈련을 일괄로 실시합니다. -------------------------------------------------------------------------------- /modules/rvc/docs/tr/faiss_tips_tr.md: -------------------------------------------------------------------------------- 1 | 2 | # faiss Ayar İpuçları 3 | ================== 4 | 5 | # faiss Hakkında 6 | faiss, yoğun vektörler için komşuluk aramalarının bir kütüphanesidir ve birçok yaklaşık komşuluk arama yöntemini verimli bir şekilde uygular. Facebook araştırma tarafından geliştirilen faiss, benzer vektörleri hızlı bir şekilde bulurken bazı doğruluğu feda eder. 7 | 8 | ## RVC'de faiss Kullanımı 9 | RVC'de, HuBERT tarafından dönüştürülen özelliklerin gömülmesi için eğitim verisinden oluşturulan gömme ile benzer gömlemeleri ararız ve bunları karıştırarak orijinal konuşmaya daha yakın bir dönüşüm elde ederiz. Ancak bu arama basitçe yapıldığında zaman alır, bu nedenle yaklaşık komşuluk araması kullanarak yüksek hızlı dönüşüm sağlanır. 10 | 11 | # Uygulama Genel Bakış 12 | Modelin bulunduğu '/logs/your-experiment/3_feature256' dizininde, her ses verisinden HuBERT tarafından çıkarılan özellikler bulunur. 13 | Buradan, dosya adına göre sıralanmış npy dosyalarını okuyarak vektörleri birleştirip büyük_npy'yi oluştururuz. (Bu vektörün şekli [N, 256] şeklindedir.) 14 | Büyük_npy'yi /logs/your-experiment/total_fea.npy olarak kaydettikten sonra, onu faiss ile eğitiriz. 15 | 16 | Bu makalede, bu parametrelerin anlamını açıklayacağım. 17 | 18 | # Yöntemin Açıklaması 19 | ## İndeks Fabrikası 20 | Bir indeks fabrikası, birden fazla yaklaşık komşuluk arama yöntemini bir dizi olarak bağlayan benzersiz bir faiss gösterimidir. Bu, indeks fabrikası dizesini değiştirerek basitçe çeşitli yaklaşık komşuluk arama yöntemlerini denemenizi sağlar. 21 | RVC'de bunu şu şekilde kullanırız: 22 | 23 | ```python 24 | index = faiss.index_factory(256, "IVF%s,Flat" % n_ivf) 25 | ``` 26 | index_factory'nin argümanları arasında ilk vektör boyutu, ikinci indeks fabrikası dizesi ve üçüncü kullanılacak mesafe yer alır. 27 | 28 | Daha ayrıntılı gösterim için 29 | https://github.com/facebookresearch/faiss/wiki/The-index-factory 30 | 31 | ## Mesafe İçin İndeks 32 | Aşağıdaki gibi gömme benzerliği olarak kullanılan iki tipik indeks bulunur. 33 | 34 | - Öklidyen mesafe (METRIC_L2) 35 | - iç çarpım (METRIC_INNER_PRODUCT) 36 | 37 | Öklidyen mesafe, her boyutta karesel farkı alır, tüm boyutlardaki farkları toplar ve ardından karekök alır. Bu, günlük hayatta kullandığımız 2D ve 3D'deki mesafeye benzer. 38 | İç çarpım, çoğunlukla L2 norm ile normalize edildikten sonra iç çarpımı alan ve genellikle kosinüs benzerliği olarak kullanılan bir benzerlik göstergesi olarak kullanılır. 39 | 40 | Hangisinin daha iyi olduğu duruma bağlıdır, ancak kosinüs benzerliği genellikle word2vec tarafından elde edilen gömme ve ArcFace tarafından öğrenilen benzer görüntü alım modellerinde kullanılır. Vektör X'i numpy ile l2 normalize yapmak isterseniz, 0 bölme hatasından kaçınmak için yeterince küçük bir eps ile şu kodu kullanabilirsiniz: 41 | 42 | ```python 43 | X_normed = X / np.maximum(eps, np.linalg.norm(X, ord=2, axis=-1, keepdims=True)) 44 | ``` 45 | 46 | Ayrıca, indeks fabrikası için üçüncü argüman olarak geçirilecek değeri seçerek hesaplamada kullanılan mesafe indeksini değiştirebilirsiniz. 47 | 48 | ```python 49 | index = faiss.index_factory(dimention, text, faiss.METRIC_INNER_PRODUCT) 50 | ``` 51 | 52 | ## IVF 53 | IVF (Ters dosya indeksleri), tam metin aramasındaki ters indeksle benzer bir algoritmadır. 54 | Öğrenme sırasında, arama hedefi kmeans ile kümelendirilir ve küme merkezi kullanılarak Voronoi bölütleme gerçekleştirilir. Her veri noktasına bir küme atanır, bu nedenle veri noktalarını kümeden arayan bir sözlük oluştururuz. 55 | 56 | Örneğin, kümelere aşağıdaki gibi atanmışsa 57 | |index|Cluster| 58 | |-----|-------| 59 | |1|A| 60 | |2|B| 61 | |3|A| 62 | |4|C| 63 | |5|B| 64 | 65 | Elde edilen ters indeks şu şekildedir: 66 | 67 | |cluster|index| 68 | |-------|-----| 69 | |A|1, 3| 70 | |B|2, 5| 71 | |C|4| 72 | 73 | Arama yaparken, önce kümeden n_probe küme ararız ve ardından her küme için ait veri noktalarının mesafelerini hesaplarız. 74 | 75 | # Tavsiye Edilen Parametreler 76 | Resmi olarak nasıl bir indeks seçileceği konusunda rehberler bulunmaktadır, bu nedenle buna uygun olarak açıklayacağım. 77 | https://github.com/facebookresearch/faiss/wiki/Guidelines-to-choose-an-index 78 | 79 | 1M'den düşük veri kümeleri için, N sayısı için 4bit-PQ, Nisan 2023 itibariyle faiss'de mevcut en verimli yöntemdir. 80 | Bunu IVF ile birleştirerek adayları 4bit-PQ ile daraltmak ve nihayet doğru bir indeksle mesafeyi yeniden hesaplamak, aşağıdaki indeks fabrikas 81 | 82 | ını kullanarak açıklanabilir. 83 | 84 | ```python 85 | index = faiss.index_factory(256, "IVF1024,PQ128x4fs,RFlat") 86 | ``` 87 | 88 | ## IVF İçin Tavsiye Edilen Parametreler 89 | Çok sayıda IVF durumunu düşünün. Örneğin, veri sayısı için IVF tarafından kabaca nicelleme yapılırsa, bu basit bir tükenmez arama ile aynıdır ve verimsizdir. 90 | 1M veya daha az için IVF değerleri, N veri noktaları için 4*sqrt(N) ~ 16*sqrt(N) arasında tavsiye edilir. 91 | 92 | Hesaplama süresi n_probes sayısına orantılı olarak arttığından, doğrulukla danışmanlık yapın ve uygun şekilde seçin. Kişisel olarak, RVC'nin bu kadar doğruluk gerektirmediğini düşünüyorum, bu nedenle n_probe = 1 uygundur. 93 | 94 | ## FastScan 95 | FastScan, bunları kaydedicilerde gerçekleştirerek onları Kartez ürünü nicelleme ile hızlı yaklaşık mesafe sağlayan bir yöntemdir. 96 | Kartez ürünü nicelleme öğrenme sırasında her d boyut için (genellikle d = 2) kümeleme yapar, küme merkezlerini önceden hesaplar ve küme merkezleri arasındaki mesafeyi hesaplar ve bir arama tablosu oluşturur. Tahmin yaparken, her boyutun mesafesi arama tablosuna bakarak O(1) hesaplanabilir. 97 | PQ sonrası belirttiğiniz sayı genellikle vektörün yarısı olan boyutu belirtir. 98 | 99 | FastScan hakkında daha ayrıntılı açıklama için lütfen resmi belgelere başvurun. 100 | https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan) 101 | 102 | ## RFlat 103 | RFlat, FastScan ile hesaplanan kesirli mesafeyi indeks fabrikasının üçüncü argümanı tarafından belirtilen doğru mesafe ile yeniden hesaplamak için bir talimattır. 104 | k komşuları alırken, k*k_factor nokta yeniden hesaplanır. 105 | -------------------------------------------------------------------------------- /modules/rvc/docs/tr/training_tips_tr.md: -------------------------------------------------------------------------------- 1 | ## RVC Eğitimi için Talimatlar ve İpuçları 2 | ====================================== 3 | Bu TALİMAT, veri eğitiminin nasıl yapıldığını açıklamaktadır. 4 | 5 | # Eğitim Akışı 6 | Eğitim sekmesindeki adımları takip ederek açıklayacağım. 7 | 8 | ## Adım 1 9 | Deney adını burada belirleyin. 10 | 11 | Ayrıca burada modelin pitch'i dikkate alıp almayacağını da belirleyebilirsiniz. 12 | Eğer model pitch'i dikkate almazsa, model daha hafif olacak, ancak şarkı söyleme için uygun olmayacaktır. 13 | 14 | Her deney için veriler `/logs/your-experiment-name/` dizinine yerleştirilir. 15 | 16 | ## Adım 2a 17 | Ses yüklenir ve ön işleme yapılır. 18 | 19 | ### Ses Yükleme 20 | Ses içeren bir klasör belirtirseniz, bu klasördeki ses dosyaları otomatik olarak okunur. 21 | Örneğin, `C:Users\hoge\voices` belirtirseniz, `C:Users\hoge\voices\voice.mp3` yüklenecek, ancak `C:Users\hoge\voices\dir\voice.mp3` yüklenmeyecektir. 22 | 23 | Ses okumak için dahili olarak ffmpeg kullanıldığından, uzantı ffmpeg tarafından destekleniyorsa otomatik olarak okunacaktır. 24 | ffmpeg ile int16'ya dönüştürüldükten sonra float32'ye dönüştürülüp -1 ile 1 arasında normalize edilir. 25 | 26 | ### Gürültü Temizleme 27 | Ses scipy'nin filtfilt işlevi ile yumuşatılır. 28 | 29 | ### Ses Ayırma 30 | İlk olarak, giriş sesi belirli bir süreden (max_sil_kept=5 saniye?) daha uzun süren sessiz kısımları tespit ederek böler. Sessizlik üzerinde ses bölündükten sonra sesi 4 saniyede bir 0.3 saniyelik bir örtüşme ile böler. 4 saniye içinde ayrılan sesler için ses normalleştirildikten sonra wav dosyası olarak `/logs/your-experiment-name/0_gt_wavs`'a, ardından 16 kHz örnekleme hızına dönüştürülerek `/logs/your-experiment-name/1_16k_wavs` olarak kaydedilir. 31 | 32 | ## Adım 2b 33 | ### Pitch Çıkarımı 34 | Wav dosyalarından pitch bilgisi çıkarılır. ParSelMouth veya PyWorld'e dahili olarak yerleştirilmiş yöntemi kullanarak pitch bilgisi (=f0) çıkarılır ve `/logs/your-experiment-name/2a_f0` dizinine kaydedilir. Ardından pitch bilgisi logaritmik olarak 1 ile 255 arasında bir tamsayıya dönüştürülüp `/logs/your-experiment-name/2b-f0nsf` dizinine kaydedilir. 35 | 36 | ### Özellik Çıkarımı 37 | HuBERT'i kullanarak önceden gömme olarak wav dosyasını çıkarır. `/logs/your-experiment-name/1_16k_wavs`'a kaydedilen wav dosyasını okuyarak, wav dosyasını 256 boyutlu HuBERT özelliklerine dönüştürür ve npy formatında `/logs/your-experiment-name/3_feature256` dizinine kaydeder. 38 | 39 | ## Adım 3 40 | Modeli eğit. 41 | ### Başlangıç Seviyesi Sözlüğü 42 | Derin öğrenmede, veri kümesi bölmeye ve öğrenmeye adım adım devam eder. Bir model güncellemesinde (adım), batch_size veri alınır ve tahminler ve hata düzeltmeleri yapılır. Bunun bir defa bir veri kümesi için yapılması bir dönem olarak sayılır. 43 | 44 | Bu nedenle, öğrenme zamanı adım başına öğrenme zamanı x (veri kümesindeki veri sayısı / batch boyutu) x dönem sayısıdır. Genel olarak, batch boyutu ne kadar büyükse, öğrenme daha istikrarlı hale gelir (adım başına öğrenme süresi ÷ batch boyutu) küçülür, ancak daha fazla GPU belleği kullanır. GPU RAM'ı nvidia-smi komutu ile kontrol edilebilir. Çalışma ortamının makinesine göre batch boyutunu mümkün olduğunca artırarak öğrenme süresini kısa sürede yapabilirsiniz. 45 | 46 | ### Önceden Eğitilmiş Modeli Belirtme 47 | RVC, modeli 0'dan değil önceden eğitilmiş ağırlıklardan başlatarak eğitir, bu nedenle küçük bir veri kümesi ile eğitilebilir. 48 | 49 | Varsayılan olarak 50 | 51 | - Eğer pitch'i dikkate alıyorsanız, `rvc-location/pretrained/f0G40k.pth` ve `rvc-location/pretrained/f0D40k.pth` yüklenir. 52 | - Eğer pitch'i dikkate almıyorsanız, yine `rvc-location/pretrained/f0G40k.pth` ve `rvc-location/pretrained/f0D40k.pth` yüklenir. 53 | 54 | Öğrenirken model parametreleri her save_every_epoch için `logs/your-experiment-name/G_{}.pth` ve `logs/your-experiment-name/D_{}.pth` olarak kaydedilir, ancak bu yolu belirterek öğrenmeye başlayabilirsiniz. Farklı bir deneyde öğrenilen model ağırlıklarından öğrenmeye yeniden başlayabilir veya eğitimi başlatabilirsiniz. 55 | 56 | ### Öğrenme İndeksi 57 | RVC, eğitim sırasında kullanılan HuBERT özellik değerlerini kaydeder ve çıkarım sırasında, öğrenme sırasında kullanılan özellik değerlerine benzer özellik değerlerini arayarak çıkarım yapar. Bu aramayı yüksek hızda gerçekleştirebilmek için indeks öğrenilir. 58 | İndeks öğrenimi için yaklaş 59 | 60 | ık komşuluk arama kütüphanesi faiss kullanılır. `/logs/your-experiment-name/3_feature256`'daki özellik değerini okur ve indeksi öğrenmek için kullanır, `logs/your-experiment-name/add_XXX.index` olarak kaydedilir. 61 | 62 | (20230428 güncelleme sürümünden itibaren indeks okunur ve kaydetmek/belirtmek artık gerekli değildir.) 63 | 64 | ### Düğme Açıklaması 65 | - Modeli Eğit: Adım 2b'yi çalıştırdıktan sonra, modeli eğitmek için bu düğmeye basın. 66 | - Özellik İndeksini Eğit: Modeli eğittikten sonra, indeks öğrenme işlemi yapın. 67 | - Tek Tıklamayla Eğitim: Adım 2b, model eğitimi ve özellik indeks eğitimini bir arada yapar. 68 | -------------------------------------------------------------------------------- /modules/rvc/docs/小白简易教程.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarodMica/ai-voice-cloning/61e46bcbc2676e21623724e66269f48d015b2ccb/modules/rvc/docs/小白简易教程.doc -------------------------------------------------------------------------------- /modules/rvc/go-realtime-gui-dml.bat: -------------------------------------------------------------------------------- 1 | runtime\python.exe gui_v1.py --pycmd runtime\python.exe --dml 2 | pause 3 | -------------------------------------------------------------------------------- /modules/rvc/go-realtime-gui.bat: -------------------------------------------------------------------------------- 1 | runtime\python.exe gui_v1.py 2 | pause 3 | -------------------------------------------------------------------------------- /modules/rvc/go-web-dml.bat: -------------------------------------------------------------------------------- 1 | runtime\python.exe infer-web.py --pycmd runtime\python.exe --port 7897 --dml 2 | pause 3 | -------------------------------------------------------------------------------- /modules/rvc/go-web.bat: -------------------------------------------------------------------------------- 1 | runtime\python.exe infer-web.py --pycmd runtime\python.exe --port 7897 2 | pause 3 | -------------------------------------------------------------------------------- /modules/rvc/i18n/i18n.py: -------------------------------------------------------------------------------- 1 | import json 2 | import locale 3 | import os 4 | 5 | 6 | def load_language_list(language): 7 | with open(f"./i18n/locale/{language}.json", "r", encoding="utf-8") as f: 8 | language_list = json.load(f) 9 | return language_list 10 | 11 | 12 | class I18nAuto: 13 | def __init__(self, language=None): 14 | if language in ["Auto", None]: 15 | language = locale.getdefaultlocale()[ 16 | 0 17 | ] # getlocale can't identify the system's language ((None, None)) 18 | if not os.path.exists(f"./i18n/locale/{language}.json"): 19 | language = "en_US" 20 | self.language = language 21 | self.language_map = load_language_list(language) 22 | 23 | def __call__(self, key): 24 | return self.language_map.get(key, key) 25 | 26 | def __repr__(self): 27 | return "Use Language: " + self.language 28 | -------------------------------------------------------------------------------- /modules/rvc/i18n/locale_diff.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from collections import OrderedDict 4 | 5 | # Define the standard file name 6 | standard_file = "locale/zh_CN.json" 7 | 8 | # Find all JSON files in the directory 9 | dir_path = "locale/" 10 | languages = [ 11 | os.path.join(dir_path, f) 12 | for f in os.listdir(dir_path) 13 | if f.endswith(".json") and f != standard_file 14 | ] 15 | 16 | # Load the standard file 17 | with open(standard_file, "r", encoding="utf-8") as f: 18 | standard_data = json.load(f, object_pairs_hook=OrderedDict) 19 | 20 | # Loop through each language file 21 | for lang_file in languages: 22 | # Load the language file 23 | with open(lang_file, "r", encoding="utf-8") as f: 24 | lang_data = json.load(f, object_pairs_hook=OrderedDict) 25 | 26 | # Find the difference between the language file and the standard file 27 | diff = set(standard_data.keys()) - set(lang_data.keys()) 28 | 29 | miss = set(lang_data.keys()) - set(standard_data.keys()) 30 | 31 | # Add any missing keys to the language file 32 | for key in diff: 33 | lang_data[key] = key 34 | 35 | # Del any extra keys to the language file 36 | for key in miss: 37 | del lang_data[key] 38 | 39 | # Sort the keys of the language file to match the order of the standard file 40 | lang_data = OrderedDict( 41 | sorted(lang_data.items(), key=lambda x: list(standard_data.keys()).index(x[0])) 42 | ) 43 | 44 | # Save the updated language file 45 | with open(lang_file, "w", encoding="utf-8") as f: 46 | json.dump(lang_data, f, ensure_ascii=False, indent=4, sort_keys=True) 47 | f.write("\n") 48 | -------------------------------------------------------------------------------- /modules/rvc/i18n/scan_i18n.py: -------------------------------------------------------------------------------- 1 | import ast 2 | import glob 3 | import json 4 | from collections import OrderedDict 5 | 6 | 7 | def extract_i18n_strings(node): 8 | i18n_strings = [] 9 | 10 | if ( 11 | isinstance(node, ast.Call) 12 | and isinstance(node.func, ast.Name) 13 | and node.func.id == "i18n" 14 | ): 15 | for arg in node.args: 16 | if isinstance(arg, ast.Str): 17 | i18n_strings.append(arg.s) 18 | 19 | for child_node in ast.iter_child_nodes(node): 20 | i18n_strings.extend(extract_i18n_strings(child_node)) 21 | 22 | return i18n_strings 23 | 24 | 25 | # scan the directory for all .py files (recursively) 26 | # for each file, parse the code into an AST 27 | # for each AST, extract the i18n strings 28 | 29 | strings = [] 30 | for filename in glob.iglob("**/*.py", recursive=True): 31 | with open(filename, "r") as f: 32 | code = f.read() 33 | if "I18nAuto" in code: 34 | tree = ast.parse(code) 35 | i18n_strings = extract_i18n_strings(tree) 36 | print(filename, len(i18n_strings)) 37 | strings.extend(i18n_strings) 38 | code_keys = set(strings) 39 | """ 40 | n_i18n.py 41 | gui_v1.py 26 42 | app.py 16 43 | infer-web.py 147 44 | scan_i18n.py 0 45 | i18n.py 0 46 | lib/train/process_ckpt.py 1 47 | """ 48 | print() 49 | print("Total unique:", len(code_keys)) 50 | 51 | 52 | standard_file = "i18n/locale/zh_CN.json" 53 | with open(standard_file, "r", encoding="utf-8") as f: 54 | standard_data = json.load(f, object_pairs_hook=OrderedDict) 55 | standard_keys = set(standard_data.keys()) 56 | 57 | # Define the standard file name 58 | unused_keys = standard_keys - code_keys 59 | print("Unused keys:", len(unused_keys)) 60 | for unused_key in unused_keys: 61 | print("\t", unused_key) 62 | 63 | missing_keys = code_keys - standard_keys 64 | print("Missing keys:", len(missing_keys)) 65 | for missing_key in missing_keys: 66 | print("\t", missing_key) 67 | 68 | code_keys_dict = OrderedDict() 69 | for s in strings: 70 | code_keys_dict[s] = s 71 | 72 | # write back 73 | with open(standard_file, "w", encoding="utf-8") as f: 74 | json.dump(code_keys_dict, f, ensure_ascii=False, indent=4, sort_keys=True) 75 | f.write("\n") 76 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/onnx/export.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from modules.rvc.infer.lib.infer_pack.models_onnx import SynthesizerTrnMsNSFsidM 4 | 5 | 6 | def export_onnx(ModelPath, ExportedPath): 7 | cpt = torch.load(ModelPath, map_location="cpu", weights_only=True) 8 | cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] 9 | vec_channels = 256 if cpt.get("version", "v1") == "v1" else 768 10 | 11 | test_phone = torch.rand(1, 200, vec_channels) # hidden unit 12 | test_phone_lengths = torch.tensor([200]).long() # hidden unit 长度(貌似没啥用) 13 | test_pitch = torch.randint(size=(1, 200), low=5, high=255) # 基频(单位赫兹) 14 | test_pitchf = torch.rand(1, 200) # nsf基频 15 | test_ds = torch.LongTensor([0]) # 说话人ID 16 | test_rnd = torch.rand(1, 192, 200) # 噪声(加入随机因子) 17 | 18 | device = "cpu" # 导出时设备(不影响使用模型) 19 | 20 | net_g = SynthesizerTrnMsNSFsidM( 21 | *cpt["config"], is_half=False, version=cpt.get("version", "v1") 22 | ) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16) 23 | net_g.load_state_dict(cpt["weight"], strict=False) 24 | input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"] 25 | output_names = [ 26 | "audio", 27 | ] 28 | # net_g.construct_spkmixmap(n_speaker) 多角色混合轨道导出 29 | torch.onnx.export( 30 | net_g, 31 | ( 32 | test_phone.to(device), 33 | test_phone_lengths.to(device), 34 | test_pitch.to(device), 35 | test_pitchf.to(device), 36 | test_ds.to(device), 37 | test_rnd.to(device), 38 | ), 39 | ExportedPath, 40 | dynamic_axes={ 41 | "phone": [1], 42 | "pitch": [1], 43 | "pitchf": [1], 44 | "rnd": [2], 45 | }, 46 | do_constant_folding=False, 47 | opset_version=13, 48 | verbose=False, 49 | input_names=input_names, 50 | output_names=output_names, 51 | ) 52 | return "Finished" 53 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/train/extract/extract_f0_print.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import traceback 4 | 5 | import parselmouth 6 | 7 | now_dir = os.getcwd() 8 | sys.path.append(now_dir) 9 | import logging 10 | 11 | import numpy as np 12 | import pyworld 13 | 14 | from modules.rvc.infer.lib.audio import load_audio 15 | 16 | logging.getLogger("numba").setLevel(logging.WARNING) 17 | from multiprocessing import Process 18 | 19 | exp_dir = sys.argv[1] 20 | f = open("%s/extract_f0_feature.log" % exp_dir, "a+") 21 | 22 | 23 | def printt(strr): 24 | print(strr) 25 | f.write("%s\n" % strr) 26 | f.flush() 27 | 28 | 29 | n_p = int(sys.argv[2]) 30 | f0method = sys.argv[3] 31 | 32 | 33 | class FeatureInput(object): 34 | def __init__(self, samplerate=16000, hop_size=160): 35 | self.fs = samplerate 36 | self.hop = hop_size 37 | 38 | self.f0_bin = 256 39 | self.f0_max = 1100.0 40 | self.f0_min = 50.0 41 | self.f0_mel_min = 1127 * np.log(1 + self.f0_min / 700) 42 | self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700) 43 | 44 | def compute_f0(self, path, f0_method): 45 | x = load_audio(path, self.fs) 46 | p_len = x.shape[0] // self.hop 47 | if f0_method == "pm": 48 | time_step = 160 / 16000 * 1000 49 | f0_min = 50 50 | f0_max = 1100 51 | f0 = ( 52 | parselmouth.Sound(x, self.fs) 53 | .to_pitch_ac( 54 | time_step=time_step / 1000, 55 | voicing_threshold=0.6, 56 | pitch_floor=f0_min, 57 | pitch_ceiling=f0_max, 58 | ) 59 | .selected_array["frequency"] 60 | ) 61 | pad_size = (p_len - len(f0) + 1) // 2 62 | if pad_size > 0 or p_len - len(f0) - pad_size > 0: 63 | f0 = np.pad( 64 | f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant" 65 | ) 66 | elif f0_method == "harvest": 67 | f0, t = pyworld.harvest( 68 | x.astype(np.double), 69 | fs=self.fs, 70 | f0_ceil=self.f0_max, 71 | f0_floor=self.f0_min, 72 | frame_period=1000 * self.hop / self.fs, 73 | ) 74 | f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs) 75 | elif f0_method == "dio": 76 | f0, t = pyworld.dio( 77 | x.astype(np.double), 78 | fs=self.fs, 79 | f0_ceil=self.f0_max, 80 | f0_floor=self.f0_min, 81 | frame_period=1000 * self.hop / self.fs, 82 | ) 83 | f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs) 84 | elif f0_method == "rmvpe": 85 | if hasattr(self, "model_rmvpe") == False: 86 | from modules.rvc.infer.lib.rmvpe import RMVPE 87 | 88 | print("Loading rmvpe model") 89 | self.model_rmvpe = RMVPE( 90 | "modules/rvc/assets/rmvpe/rmvpe.pt", is_half=False, device="cpu" 91 | ) 92 | f0 = self.model_rmvpe.infer_from_audio(x, thred=0.03) 93 | return f0 94 | 95 | def coarse_f0(self, f0): 96 | f0_mel = 1127 * np.log(1 + f0 / 700) 97 | f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - self.f0_mel_min) * ( 98 | self.f0_bin - 2 99 | ) / (self.f0_mel_max - self.f0_mel_min) + 1 100 | 101 | # use 0 or 1 102 | f0_mel[f0_mel <= 1] = 1 103 | f0_mel[f0_mel > self.f0_bin - 1] = self.f0_bin - 1 104 | f0_coarse = np.rint(f0_mel).astype(int) 105 | assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, ( 106 | f0_coarse.max(), 107 | f0_coarse.min(), 108 | ) 109 | return f0_coarse 110 | 111 | def go(self, paths, f0_method): 112 | if len(paths) == 0: 113 | printt("no-f0-todo") 114 | else: 115 | printt("todo-f0-%s" % len(paths)) 116 | n = max(len(paths) // 5, 1) # 每个进程最多打印5条 117 | for idx, (inp_path, opt_path1, opt_path2) in enumerate(paths): 118 | try: 119 | if idx % n == 0: 120 | printt("f0ing,now-%s,all-%s,-%s" % (idx, len(paths), inp_path)) 121 | if ( 122 | os.path.exists(opt_path1 + ".npy") == True 123 | and os.path.exists(opt_path2 + ".npy") == True 124 | ): 125 | continue 126 | featur_pit = self.compute_f0(inp_path, f0_method) 127 | np.save( 128 | opt_path2, 129 | featur_pit, 130 | allow_pickle=False, 131 | ) # nsf 132 | coarse_pit = self.coarse_f0(featur_pit) 133 | np.save( 134 | opt_path1, 135 | coarse_pit, 136 | allow_pickle=False, 137 | ) # ori 138 | except: 139 | printt("f0fail-%s-%s-%s" % (idx, inp_path, traceback.format_exc())) 140 | 141 | 142 | if __name__ == "__main__": 143 | # exp_dir=r"E:\codes\py39\dataset\mi-test" 144 | # n_p=16 145 | # f = open("%s/log_extract_f0.log"%exp_dir, "w") 146 | printt(sys.argv) 147 | featureInput = FeatureInput() 148 | paths = [] 149 | inp_root = "%s/1_16k_wavs" % (exp_dir) 150 | opt_root1 = "%s/2a_f0" % (exp_dir) 151 | opt_root2 = "%s/2b-f0nsf" % (exp_dir) 152 | 153 | os.makedirs(opt_root1, exist_ok=True) 154 | os.makedirs(opt_root2, exist_ok=True) 155 | for name in sorted(list(os.listdir(inp_root))): 156 | inp_path = "%s/%s" % (inp_root, name) 157 | if "spec" in inp_path: 158 | continue 159 | opt_path1 = "%s/%s" % (opt_root1, name) 160 | opt_path2 = "%s/%s" % (opt_root2, name) 161 | paths.append([inp_path, opt_path1, opt_path2]) 162 | 163 | ps = [] 164 | for i in range(n_p): 165 | p = Process( 166 | target=featureInput.go, 167 | args=( 168 | paths[i::n_p], 169 | f0method, 170 | ), 171 | ) 172 | ps.append(p) 173 | p.start() 174 | for i in range(n_p): 175 | ps[i].join() 176 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/train/extract/extract_f0_rmvpe.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import traceback 4 | 5 | import parselmouth 6 | 7 | now_dir = os.getcwd() 8 | sys.path.append(now_dir) 9 | import logging 10 | 11 | import numpy as np 12 | import pyworld 13 | 14 | from modules.rvc.infer.lib.audio import load_audio 15 | 16 | logging.getLogger("numba").setLevel(logging.WARNING) 17 | 18 | n_part = int(sys.argv[1]) 19 | i_part = int(sys.argv[2]) 20 | i_gpu = sys.argv[3] 21 | os.environ["CUDA_VISIBLE_DEVICES"] = str(i_gpu) 22 | exp_dir = sys.argv[4] 23 | is_half = sys.argv[5] 24 | f = open("%s/extract_f0_feature.log" % exp_dir, "a+") 25 | 26 | 27 | def printt(strr): 28 | print(strr) 29 | f.write("%s\n" % strr) 30 | f.flush() 31 | 32 | 33 | class FeatureInput(object): 34 | def __init__(self, samplerate=16000, hop_size=160): 35 | self.fs = samplerate 36 | self.hop = hop_size 37 | 38 | self.f0_bin = 256 39 | self.f0_max = 1100.0 40 | self.f0_min = 50.0 41 | self.f0_mel_min = 1127 * np.log(1 + self.f0_min / 700) 42 | self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700) 43 | 44 | def compute_f0(self, path, f0_method): 45 | x = load_audio(path, self.fs) 46 | # p_len = x.shape[0] // self.hop 47 | if f0_method == "rmvpe": 48 | if hasattr(self, "model_rmvpe") == False: 49 | from modules.rvc.infer.lib.rmvpe import RMVPE 50 | 51 | print("Loading rmvpe model") 52 | self.model_rmvpe = RMVPE( 53 | "assets/rmvpe/rmvpe.pt", is_half=is_half, device="cuda" 54 | ) 55 | f0 = self.model_rmvpe.infer_from_audio(x, thred=0.03) 56 | return f0 57 | 58 | def coarse_f0(self, f0): 59 | f0_mel = 1127 * np.log(1 + f0 / 700) 60 | f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - self.f0_mel_min) * ( 61 | self.f0_bin - 2 62 | ) / (self.f0_mel_max - self.f0_mel_min) + 1 63 | 64 | # use 0 or 1 65 | f0_mel[f0_mel <= 1] = 1 66 | f0_mel[f0_mel > self.f0_bin - 1] = self.f0_bin - 1 67 | f0_coarse = np.rint(f0_mel).astype(int) 68 | assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, ( 69 | f0_coarse.max(), 70 | f0_coarse.min(), 71 | ) 72 | return f0_coarse 73 | 74 | def go(self, paths, f0_method): 75 | if len(paths) == 0: 76 | printt("no-f0-todo") 77 | else: 78 | printt("todo-f0-%s" % len(paths)) 79 | n = max(len(paths) // 5, 1) # 每个进程最多打印5条 80 | for idx, (inp_path, opt_path1, opt_path2) in enumerate(paths): 81 | try: 82 | if idx % n == 0: 83 | printt("f0ing,now-%s,all-%s,-%s" % (idx, len(paths), inp_path)) 84 | if ( 85 | os.path.exists(opt_path1 + ".npy") == True 86 | and os.path.exists(opt_path2 + ".npy") == True 87 | ): 88 | continue 89 | featur_pit = self.compute_f0(inp_path, f0_method) 90 | np.save( 91 | opt_path2, 92 | featur_pit, 93 | allow_pickle=False, 94 | ) # nsf 95 | coarse_pit = self.coarse_f0(featur_pit) 96 | np.save( 97 | opt_path1, 98 | coarse_pit, 99 | allow_pickle=False, 100 | ) # ori 101 | except: 102 | printt("f0fail-%s-%s-%s" % (idx, inp_path, traceback.format_exc())) 103 | 104 | 105 | if __name__ == "__main__": 106 | # exp_dir=r"E:\codes\py39\dataset\mi-test" 107 | # n_p=16 108 | # f = open("%s/log_extract_f0.log"%exp_dir, "w") 109 | printt(sys.argv) 110 | featureInput = FeatureInput() 111 | paths = [] 112 | inp_root = "%s/1_16k_wavs" % (exp_dir) 113 | opt_root1 = "%s/2a_f0" % (exp_dir) 114 | opt_root2 = "%s/2b-f0nsf" % (exp_dir) 115 | 116 | os.makedirs(opt_root1, exist_ok=True) 117 | os.makedirs(opt_root2, exist_ok=True) 118 | for name in sorted(list(os.listdir(inp_root))): 119 | inp_path = "%s/%s" % (inp_root, name) 120 | if "spec" in inp_path: 121 | continue 122 | opt_path1 = "%s/%s" % (opt_root1, name) 123 | opt_path2 = "%s/%s" % (opt_root2, name) 124 | paths.append([inp_path, opt_path1, opt_path2]) 125 | try: 126 | featureInput.go(paths[i_part::n_part], "rmvpe") 127 | except: 128 | printt("f0_all_fail-%s" % (traceback.format_exc())) 129 | # ps = [] 130 | # for i in range(n_p): 131 | # p = Process( 132 | # target=featureInput.go, 133 | # args=( 134 | # paths[i::n_p], 135 | # f0method, 136 | # ), 137 | # ) 138 | # ps.append(p) 139 | # p.start() 140 | # for i in range(n_p): 141 | # ps[i].join() 142 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/train/extract/extract_f0_rmvpe_dml.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import traceback 4 | 5 | import parselmouth 6 | 7 | now_dir = os.getcwd() 8 | sys.path.append(now_dir) 9 | import logging 10 | 11 | import numpy as np 12 | import pyworld 13 | 14 | from modules.rvc.infer.lib.audio import load_audio 15 | 16 | logging.getLogger("numba").setLevel(logging.WARNING) 17 | 18 | exp_dir = sys.argv[1] 19 | import torch_directml 20 | 21 | device = torch_directml.device(torch_directml.default_device()) 22 | f = open("%s/extract_f0_feature.log" % exp_dir, "a+") 23 | 24 | 25 | def printt(strr): 26 | print(strr) 27 | f.write("%s\n" % strr) 28 | f.flush() 29 | 30 | 31 | class FeatureInput(object): 32 | def __init__(self, samplerate=16000, hop_size=160): 33 | self.fs = samplerate 34 | self.hop = hop_size 35 | 36 | self.f0_bin = 256 37 | self.f0_max = 1100.0 38 | self.f0_min = 50.0 39 | self.f0_mel_min = 1127 * np.log(1 + self.f0_min / 700) 40 | self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700) 41 | 42 | def compute_f0(self, path, f0_method): 43 | x = load_audio(path, self.fs) 44 | # p_len = x.shape[0] // self.hop 45 | if f0_method == "rmvpe": 46 | if hasattr(self, "model_rmvpe") == False: 47 | from modules.rvc.infer.lib.rmvpe import RMVPE 48 | 49 | print("Loading rmvpe model") 50 | self.model_rmvpe = RMVPE( 51 | "assets/rmvpe/rmvpe.pt", is_half=False, device=device 52 | ) 53 | f0 = self.model_rmvpe.infer_from_audio(x, thred=0.03) 54 | return f0 55 | 56 | def coarse_f0(self, f0): 57 | f0_mel = 1127 * np.log(1 + f0 / 700) 58 | f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - self.f0_mel_min) * ( 59 | self.f0_bin - 2 60 | ) / (self.f0_mel_max - self.f0_mel_min) + 1 61 | 62 | # use 0 or 1 63 | f0_mel[f0_mel <= 1] = 1 64 | f0_mel[f0_mel > self.f0_bin - 1] = self.f0_bin - 1 65 | f0_coarse = np.rint(f0_mel).astype(int) 66 | assert f0_coarse.max() <= 255 and f0_coarse.min() >= 1, ( 67 | f0_coarse.max(), 68 | f0_coarse.min(), 69 | ) 70 | return f0_coarse 71 | 72 | def go(self, paths, f0_method): 73 | if len(paths) == 0: 74 | printt("no-f0-todo") 75 | else: 76 | printt("todo-f0-%s" % len(paths)) 77 | n = max(len(paths) // 5, 1) # 每个进程最多打印5条 78 | for idx, (inp_path, opt_path1, opt_path2) in enumerate(paths): 79 | try: 80 | if idx % n == 0: 81 | printt("f0ing,now-%s,all-%s,-%s" % (idx, len(paths), inp_path)) 82 | if ( 83 | os.path.exists(opt_path1 + ".npy") == True 84 | and os.path.exists(opt_path2 + ".npy") == True 85 | ): 86 | continue 87 | featur_pit = self.compute_f0(inp_path, f0_method) 88 | np.save( 89 | opt_path2, 90 | featur_pit, 91 | allow_pickle=False, 92 | ) # nsf 93 | coarse_pit = self.coarse_f0(featur_pit) 94 | np.save( 95 | opt_path1, 96 | coarse_pit, 97 | allow_pickle=False, 98 | ) # ori 99 | except: 100 | printt("f0fail-%s-%s-%s" % (idx, inp_path, traceback.format_exc())) 101 | 102 | 103 | if __name__ == "__main__": 104 | # exp_dir=r"E:\codes\py39\dataset\mi-test" 105 | # n_p=16 106 | # f = open("%s/log_extract_f0.log"%exp_dir, "w") 107 | printt(sys.argv) 108 | featureInput = FeatureInput() 109 | paths = [] 110 | inp_root = "%s/1_16k_wavs" % (exp_dir) 111 | opt_root1 = "%s/2a_f0" % (exp_dir) 112 | opt_root2 = "%s/2b-f0nsf" % (exp_dir) 113 | 114 | os.makedirs(opt_root1, exist_ok=True) 115 | os.makedirs(opt_root2, exist_ok=True) 116 | for name in sorted(list(os.listdir(inp_root))): 117 | inp_path = "%s/%s" % (inp_root, name) 118 | if "spec" in inp_path: 119 | continue 120 | opt_path1 = "%s/%s" % (opt_root1, name) 121 | opt_path2 = "%s/%s" % (opt_root2, name) 122 | paths.append([inp_path, opt_path1, opt_path2]) 123 | try: 124 | featureInput.go(paths, "rmvpe") 125 | except: 126 | printt("f0_all_fail-%s" % (traceback.format_exc())) 127 | # ps = [] 128 | # for i in range(n_p): 129 | # p = Process( 130 | # target=featureInput.go, 131 | # args=( 132 | # paths[i::n_p], 133 | # f0method, 134 | # ), 135 | # ) 136 | # ps.append(p) 137 | # p.start() 138 | # for i in range(n_p): 139 | # ps[i].join() 140 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/train/extract_feature_print.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import traceback 4 | 5 | os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1" 6 | os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0" 7 | 8 | device = sys.argv[1] 9 | n_part = int(sys.argv[2]) 10 | i_part = int(sys.argv[3]) 11 | if len(sys.argv) == 6: 12 | exp_dir = sys.argv[4] 13 | version = sys.argv[5] 14 | else: 15 | i_gpu = sys.argv[4] 16 | exp_dir = sys.argv[5] 17 | os.environ["CUDA_VISIBLE_DEVICES"] = str(i_gpu) 18 | version = sys.argv[6] 19 | import fairseq 20 | import numpy as np 21 | import soundfile as sf 22 | import torch 23 | import torch.nn.functional as F 24 | 25 | if "privateuseone" not in device: 26 | device = "cpu" 27 | if torch.cuda.is_available(): 28 | device = "cuda" 29 | elif torch.backends.mps.is_available(): 30 | device = "mps" 31 | else: 32 | import torch_directml 33 | 34 | device = torch_directml.device(torch_directml.default_device()) 35 | 36 | def forward_dml(ctx, x, scale): 37 | ctx.scale = scale 38 | res = x.clone().detach() 39 | return res 40 | 41 | fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml 42 | 43 | f = open("%s/extract_f0_feature.log" % exp_dir, "a+") 44 | 45 | 46 | def printt(strr): 47 | print(strr) 48 | f.write("%s\n" % strr) 49 | f.flush() 50 | 51 | 52 | printt(sys.argv) 53 | model_path = "assets/hubert/hubert_base.pt" 54 | 55 | printt(exp_dir) 56 | wavPath = "%s/1_16k_wavs" % exp_dir 57 | outPath = ( 58 | "%s/3_feature256" % exp_dir if version == "v1" else "%s/3_feature768" % exp_dir 59 | ) 60 | os.makedirs(outPath, exist_ok=True) 61 | 62 | 63 | # wave must be 16k, hop_size=320 64 | def readwave(wav_path, normalize=False): 65 | wav, sr = sf.read(wav_path) 66 | assert sr == 16000 67 | feats = torch.from_numpy(wav).float() 68 | if feats.dim() == 2: # double channels 69 | feats = feats.mean(-1) 70 | assert feats.dim() == 1, feats.dim() 71 | if normalize: 72 | with torch.no_grad(): 73 | feats = F.layer_norm(feats, feats.shape) 74 | feats = feats.view(1, -1) 75 | return feats 76 | 77 | 78 | # HuBERT model 79 | printt("load model(s) from {}".format(model_path)) 80 | # if hubert model is exist 81 | if os.access(model_path, os.F_OK) == False: 82 | printt( 83 | "Error: Extracting is shut down because %s does not exist, you may download it from https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main" 84 | % model_path 85 | ) 86 | exit(0) 87 | models, saved_cfg, task = fairseq.checkpoint_utils.load_model_ensemble_and_task( 88 | [model_path], 89 | suffix="", 90 | ) 91 | model = models[0] 92 | model = model.to(device) 93 | printt("move model to %s" % device) 94 | if device not in ["mps", "cpu"]: 95 | model = model.half() 96 | model.eval() 97 | 98 | todo = sorted(list(os.listdir(wavPath)))[i_part::n_part] 99 | n = max(1, len(todo) // 10) # 最多打印十条 100 | if len(todo) == 0: 101 | printt("no-feature-todo") 102 | else: 103 | printt("all-feature-%s" % len(todo)) 104 | for idx, file in enumerate(todo): 105 | try: 106 | if file.endswith(".wav"): 107 | wav_path = "%s/%s" % (wavPath, file) 108 | out_path = "%s/%s" % (outPath, file.replace("wav", "npy")) 109 | 110 | if os.path.exists(out_path): 111 | continue 112 | 113 | feats = readwave(wav_path, normalize=saved_cfg.task.normalize) 114 | padding_mask = torch.BoolTensor(feats.shape).fill_(False) 115 | inputs = { 116 | "source": feats.half().to(device) 117 | if device not in ["mps", "cpu"] 118 | else feats.to(device), 119 | "padding_mask": padding_mask.to(device), 120 | "output_layer": 9 if version == "v1" else 12, # layer 9 121 | } 122 | with torch.no_grad(): 123 | logits = model.extract_features(**inputs) 124 | feats = ( 125 | model.final_proj(logits[0]) if version == "v1" else logits[0] 126 | ) 127 | 128 | feats = feats.squeeze(0).float().cpu().numpy() 129 | if np.isnan(feats).sum() == 0: 130 | np.save(out_path, feats, allow_pickle=False) 131 | else: 132 | printt("%s-contains nan" % file) 133 | if idx % n == 0: 134 | printt("now-%s,all-%s,%s,%s" % (len(todo), idx, file, feats.shape)) 135 | except: 136 | printt(traceback.format_exc()) 137 | printt("all-feature-done") 138 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/train/preprocess.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import os 3 | import sys 4 | 5 | from scipy import signal 6 | 7 | now_dir = os.getcwd() 8 | sys.path.append(now_dir) 9 | print(sys.argv) 10 | inp_root = sys.argv[1] 11 | sr = int(sys.argv[2]) 12 | n_p = int(sys.argv[3]) 13 | exp_dir = sys.argv[4] 14 | noparallel = sys.argv[5] == "True" 15 | per = float(sys.argv[6]) 16 | import multiprocessing 17 | import os 18 | import traceback 19 | 20 | import librosa 21 | import numpy as np 22 | from scipy.io import wavfile 23 | 24 | from modules.rvc.infer.lib.audio import load_audio 25 | from modules.rvc.infer.lib.slicer2 import Slicer 26 | 27 | mutex = multiprocessing.Lock() 28 | f = open("%s/preprocess.log" % exp_dir, "a+") 29 | 30 | 31 | def println(strr): 32 | mutex.acquire() 33 | print(strr) 34 | f.write("%s\n" % strr) 35 | f.flush() 36 | mutex.release() 37 | 38 | 39 | class PreProcess: 40 | def __init__(self, sr, exp_dir, per=3.7): 41 | self.slicer = Slicer( 42 | sr=sr, 43 | threshold=-42, 44 | min_length=1500, 45 | min_interval=400, 46 | hop_size=15, 47 | max_sil_kept=500, 48 | ) 49 | self.sr = sr 50 | self.bh, self.ah = signal.butter(N=5, Wn=48, btype="high", fs=self.sr) 51 | self.per = per 52 | self.overlap = 0.3 53 | self.tail = self.per + self.overlap 54 | self.max = 0.9 55 | self.alpha = 0.75 56 | self.exp_dir = exp_dir 57 | self.gt_wavs_dir = "%s/0_gt_wavs" % exp_dir 58 | self.wavs16k_dir = "%s/1_16k_wavs" % exp_dir 59 | os.makedirs(self.exp_dir, exist_ok=True) 60 | os.makedirs(self.gt_wavs_dir, exist_ok=True) 61 | os.makedirs(self.wavs16k_dir, exist_ok=True) 62 | 63 | def norm_write(self, tmp_audio, idx0, idx1): 64 | tmp_max = np.abs(tmp_audio).max() 65 | if tmp_max > 2.5: 66 | print("%s-%s-%s-filtered" % (idx0, idx1, tmp_max)) 67 | return 68 | tmp_audio = (tmp_audio / tmp_max * (self.max * self.alpha)) + ( 69 | 1 - self.alpha 70 | ) * tmp_audio 71 | wavfile.write( 72 | "%s/%s_%s.wav" % (self.gt_wavs_dir, idx0, idx1), 73 | self.sr, 74 | tmp_audio.astype(np.float32), 75 | ) 76 | tmp_audio = librosa.resample( 77 | tmp_audio, orig_sr=self.sr, target_sr=16000 78 | ) # , res_type="soxr_vhq" 79 | wavfile.write( 80 | "%s/%s_%s.wav" % (self.wavs16k_dir, idx0, idx1), 81 | 16000, 82 | tmp_audio.astype(np.float32), 83 | ) 84 | 85 | def pipeline(self, path, idx0): 86 | try: 87 | audio = load_audio(path, self.sr) 88 | # zero phased digital filter cause pre-ringing noise... 89 | # audio = signal.filtfilt(self.bh, self.ah, audio) 90 | audio = signal.lfilter(self.bh, self.ah, audio) 91 | 92 | idx1 = 0 93 | for audio in self.slicer.slice(audio): 94 | i = 0 95 | while 1: 96 | start = int(self.sr * (self.per - self.overlap) * i) 97 | i += 1 98 | if len(audio[start:]) > self.tail * self.sr: 99 | tmp_audio = audio[start : start + int(self.per * self.sr)] 100 | self.norm_write(tmp_audio, idx0, idx1) 101 | idx1 += 1 102 | else: 103 | tmp_audio = audio[start:] 104 | idx1 += 1 105 | break 106 | self.norm_write(tmp_audio, idx0, idx1) 107 | println("%s->Suc." % path) 108 | except: 109 | println("%s->%s" % (path, traceback.format_exc())) 110 | 111 | def pipeline_mp(self, infos): 112 | for path, idx0 in infos: 113 | self.pipeline(path, idx0) 114 | 115 | def pipeline_mp_inp_dir(self, inp_root, n_p): 116 | try: 117 | infos = [ 118 | ("%s/%s" % (inp_root, name), idx) 119 | for idx, name in enumerate(sorted(list(os.listdir(inp_root)))) 120 | ] 121 | if noparallel: 122 | for i in range(n_p): 123 | self.pipeline_mp(infos[i::n_p]) 124 | else: 125 | ps = [] 126 | for i in range(n_p): 127 | p = multiprocessing.Process( 128 | target=self.pipeline_mp, args=(infos[i::n_p],) 129 | ) 130 | ps.append(p) 131 | p.start() 132 | for i in range(n_p): 133 | ps[i].join() 134 | except: 135 | println("Fail. %s" % traceback.format_exc()) 136 | 137 | 138 | def preprocess_trainset(inp_root, sr, n_p, exp_dir, per): 139 | pp = PreProcess(sr, exp_dir, per) 140 | println("start preprocess") 141 | println(sys.argv) 142 | pp.pipeline_mp_inp_dir(inp_root, n_p) 143 | println("end preprocess") 144 | 145 | 146 | if __name__ == "__main__": 147 | preprocess_trainset(inp_root, sr, n_p, exp_dir, per) 148 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/uvr5/modules.py: -------------------------------------------------------------------------------- 1 | import os 2 | import traceback 3 | import logging 4 | 5 | logger = logging.getLogger(__name__) 6 | 7 | import ffmpeg 8 | import torch 9 | 10 | from configs.config import Config 11 | from modules.rvc.infer.modules.uvr5.mdxnet import MDXNetDereverb 12 | from modules.rvc.infer.modules.uvr5.preprocess import AudioPre, AudioPreDeEcho 13 | 14 | config = Config() 15 | 16 | 17 | def uvr(model_name, inp_root, save_root_vocal, paths, save_root_ins, agg, format0): 18 | infos = [] 19 | try: 20 | inp_root = inp_root.strip(" ").strip('"').strip("\n").strip('"').strip(" ") 21 | save_root_vocal = ( 22 | save_root_vocal.strip(" ").strip('"').strip("\n").strip('"').strip(" ") 23 | ) 24 | save_root_ins = ( 25 | save_root_ins.strip(" ").strip('"').strip("\n").strip('"').strip(" ") 26 | ) 27 | if model_name == "onnx_dereverb_By_FoxJoy": 28 | pre_fun = MDXNetDereverb(15, config.device) 29 | else: 30 | func = AudioPre if "DeEcho" not in model_name else AudioPreDeEcho 31 | pre_fun = func( 32 | agg=int(agg), 33 | model_path=os.path.join( 34 | os.getenv("weight_uvr5_root"), model_name + ".pth" 35 | ), 36 | device=config.device, 37 | is_half=config.is_half, 38 | ) 39 | if inp_root != "": 40 | paths = [os.path.join(inp_root, name) for name in os.listdir(inp_root)] 41 | else: 42 | paths = [path.name for path in paths] 43 | for path in paths: 44 | inp_path = os.path.join(inp_root, path) 45 | need_reformat = 1 46 | done = 0 47 | try: 48 | info = ffmpeg.probe(inp_path, cmd="ffprobe") 49 | if ( 50 | info["streams"][0]["channels"] == 2 51 | and info["streams"][0]["sample_rate"] == "44100" 52 | ): 53 | need_reformat = 0 54 | pre_fun._path_audio_( 55 | inp_path, save_root_ins, save_root_vocal, format0 56 | ) 57 | done = 1 58 | except: 59 | need_reformat = 1 60 | traceback.print_exc() 61 | if need_reformat == 1: 62 | tmp_path = "%s/%s.reformatted.wav" % ( 63 | os.path.join(os.environ["TEMP"]), 64 | os.path.basename(inp_path), 65 | ) 66 | os.system( 67 | "ffmpeg -i %s -vn -acodec pcm_s16le -ac 2 -ar 44100 %s -y" 68 | % (inp_path, tmp_path) 69 | ) 70 | inp_path = tmp_path 71 | try: 72 | if done == 0: 73 | pre_fun.path_audio( 74 | inp_path, save_root_ins, save_root_vocal, format0 75 | ) 76 | infos.append("%s->Success" % (os.path.basename(inp_path))) 77 | yield "\n".join(infos) 78 | except: 79 | try: 80 | if done == 0: 81 | pre_fun._path_audio_( 82 | inp_path, save_root_ins, save_root_vocal, format0 83 | ) 84 | infos.append("%s->Success" % (os.path.basename(inp_path))) 85 | yield "\n".join(infos) 86 | except: 87 | infos.append( 88 | "%s->%s" % (os.path.basename(inp_path), traceback.format_exc()) 89 | ) 90 | yield "\n".join(infos) 91 | except: 92 | infos.append(traceback.format_exc()) 93 | yield "\n".join(infos) 94 | finally: 95 | try: 96 | if model_name == "onnx_dereverb_By_FoxJoy": 97 | del pre_fun.pred.model 98 | del pre_fun.pred.model_ 99 | else: 100 | del pre_fun.model 101 | del pre_fun 102 | except: 103 | traceback.print_exc() 104 | if torch.cuda.is_available(): 105 | torch.cuda.empty_cache() 106 | logger.info("Executed torch.cuda.empty_cache()") 107 | yield "\n".join(infos) 108 | -------------------------------------------------------------------------------- /modules/rvc/infer/modules/vc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarodMica/ai-voice-cloning/61e46bcbc2676e21623724e66269f48d015b2ccb/modules/rvc/infer/modules/vc/__init__.py -------------------------------------------------------------------------------- /modules/rvc/infer/modules/vc/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from fairseq import checkpoint_utils 4 | 5 | 6 | def get_index_path_from_model(sid): 7 | target_folder = "modules/rvc/assets/index/" 8 | return next( 9 | ( 10 | f 11 | for f in [ 12 | os.path.join(root, name) 13 | for root, _, files in os.walk(target_folder, topdown=False) 14 | for name in files 15 | if name.endswith(".index") and "trained" not in name 16 | ] 17 | if sid.split(".")[0] in f 18 | ), 19 | "", 20 | ) 21 | 22 | 23 | def load_hubert(config): 24 | models, _, _ = checkpoint_utils.load_model_ensemble_and_task( 25 | ["modules/rvc/assets/hubert/hubert_base.pt"], 26 | suffix="", 27 | ) 28 | hubert_model = models[0] 29 | hubert_model = hubert_model.to(config.device) 30 | if config.is_half: 31 | hubert_model = hubert_model.half() 32 | else: 33 | hubert_model = hubert_model.float() 34 | return hubert_model.eval() 35 | -------------------------------------------------------------------------------- /modules/rvc/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "rvc-beta" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["lj1995"] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | torch = "^2.0.0" 11 | torchaudio = "^2.0.1" 12 | Cython = "^0.29.34" 13 | gradio = "^3.34.0" 14 | future = "^0.18.3" 15 | pydub = "^0.25.1" 16 | soundfile = "^0.12.1" 17 | ffmpeg-python = "^0.2.0" 18 | tensorboardX = "^2.6" 19 | functorch = "^2.0.0" 20 | fairseq = "^0.12.2" 21 | faiss-cpu = "^1.7.2" 22 | Jinja2 = "^3.1.2" 23 | json5 = "^0.9.11" 24 | librosa = "0.9.1" 25 | llvmlite = "0.39.0" 26 | Markdown = "^3.4.3" 27 | matplotlib = "^3.7.1" 28 | matplotlib-inline = "^0.1.6" 29 | numba = "0.56.4" 30 | numpy = "1.23.5" 31 | scipy = "1.9.3" 32 | praat-parselmouth = "^0.4.3" 33 | Pillow = "9.3.0" 34 | pyworld = "^0.3.2" 35 | resampy = "^0.4.2" 36 | scikit-learn = "^1.2.2" 37 | starlette = "^0.27.0" 38 | tensorboard = "^2.12.1" 39 | tensorboard-data-server = "^0.7.0" 40 | tensorboard-plugin-wit = "^1.8.1" 41 | torchgen = "^0.0.1" 42 | tqdm = "^4.65.0" 43 | tornado = "^6.3" 44 | Werkzeug = "^2.2.3" 45 | uc-micro-py = "^1.0.1" 46 | sympy = "^1.11.1" 47 | tabulate = "^0.9.0" 48 | PyYAML = "^6.0" 49 | pyasn1 = "^0.4.8" 50 | pyasn1-modules = "^0.2.8" 51 | fsspec = "^2023.3.0" 52 | absl-py = "^1.4.0" 53 | audioread = "^3.0.0" 54 | uvicorn = "^0.21.1" 55 | colorama = "^0.4.6" 56 | torchcrepe = "0.0.20" 57 | python-dotenv = "^1.0.0" 58 | 59 | [tool.poetry.dev-dependencies] 60 | 61 | [build-system] 62 | requires = ["poetry-core>=1.0.0"] 63 | build-backend = "poetry.core.masonry.api" 64 | -------------------------------------------------------------------------------- /modules/rvc/requirements-amd.txt: -------------------------------------------------------------------------------- 1 | tensorflow-rocm 2 | joblib>=1.1.0 3 | numba==0.56.4 4 | numpy==1.23.5 5 | scipy 6 | librosa==0.9.1 7 | llvmlite==0.39.0 8 | fairseq==0.12.2 9 | faiss-cpu==1.7.3 10 | gradio==3.34.0 11 | Cython 12 | pydub>=0.25.1 13 | soundfile>=0.12.1 14 | ffmpeg-python>=0.2.0 15 | tensorboardX 16 | Jinja2>=3.1.2 17 | json5 18 | Markdown 19 | matplotlib>=3.7.0 20 | matplotlib-inline>=0.1.3 21 | praat-parselmouth>=0.4.2 22 | Pillow>=9.1.1 23 | resampy>=0.4.2 24 | scikit-learn 25 | tensorboard 26 | tqdm>=4.63.1 27 | tornado>=6.1 28 | Werkzeug>=2.2.3 29 | uc-micro-py>=1.0.1 30 | sympy>=1.11.1 31 | tabulate>=0.8.10 32 | PyYAML>=6.0 33 | pyasn1>=0.4.8 34 | pyasn1-modules>=0.2.8 35 | fsspec>=2022.11.0 36 | absl-py>=1.2.0 37 | audioread 38 | uvicorn>=0.21.1 39 | colorama>=0.4.5 40 | pyworld==0.3.2 41 | httpx 42 | onnxruntime 43 | onnxruntime-gpu 44 | torchcrepe==0.0.20 45 | fastapi==0.88 46 | ffmpy==0.3.1 47 | python-dotenv>=1.0.0 48 | av 49 | -------------------------------------------------------------------------------- /modules/rvc/requirements-dml.txt: -------------------------------------------------------------------------------- 1 | joblib>=1.1.0 2 | numba==0.56.4 3 | numpy==1.23.5 4 | scipy 5 | librosa==0.9.1 6 | llvmlite==0.39.0 7 | fairseq==0.12.2 8 | faiss-cpu==1.7.3 9 | gradio==3.34.0 10 | Cython 11 | pydub>=0.25.1 12 | soundfile>=0.12.1 13 | ffmpeg-python>=0.2.0 14 | tensorboardX 15 | Jinja2>=3.1.2 16 | json5 17 | Markdown 18 | matplotlib>=3.7.0 19 | matplotlib-inline>=0.1.3 20 | praat-parselmouth>=0.4.2 21 | Pillow>=9.1.1 22 | resampy>=0.4.2 23 | scikit-learn 24 | tensorboard 25 | tqdm>=4.63.1 26 | tornado>=6.1 27 | Werkzeug>=2.2.3 28 | uc-micro-py>=1.0.1 29 | sympy>=1.11.1 30 | tabulate>=0.8.10 31 | PyYAML>=6.0 32 | pyasn1>=0.4.8 33 | pyasn1-modules>=0.2.8 34 | fsspec>=2022.11.0 35 | absl-py>=1.2.0 36 | audioread 37 | uvicorn>=0.21.1 38 | colorama>=0.4.5 39 | pyworld==0.3.2 40 | httpx 41 | onnxruntime-directml 42 | torchcrepe==0.0.20 43 | fastapi==0.88 44 | ffmpy==0.3.1 45 | python-dotenv>=1.0.0 46 | av 47 | -------------------------------------------------------------------------------- /modules/rvc/requirements-ipex.txt: -------------------------------------------------------------------------------- 1 | torch==2.0.1a0 2 | intel_extension_for_pytorch==2.0.110+xpu 3 | torchvision==0.15.2a0 4 | https://github.com/Disty0/Retrieval-based-Voice-Conversion-WebUI/releases/download/torchaudio_wheels_for_ipex/torchaudio-2.0.2+31de77d-cp310-cp310-linux_x86_64.whl 5 | -f https://developer.intel.com/ipex-whl-stable-xpu 6 | joblib>=1.1.0 7 | numba==0.56.4 8 | numpy==1.23.5 9 | scipy 10 | librosa==0.9.1 11 | llvmlite==0.39.0 12 | fairseq==0.12.2 13 | faiss-cpu==1.7.3 14 | gradio==3.34.0 15 | Cython 16 | pydub>=0.25.1 17 | soundfile>=0.12.1 18 | ffmpeg-python>=0.2.0 19 | tensorboardX 20 | Jinja2>=3.1.2 21 | json5 22 | Markdown 23 | matplotlib>=3.7.0 24 | matplotlib-inline>=0.1.3 25 | praat-parselmouth>=0.4.2 26 | Pillow>=9.1.1 27 | resampy>=0.4.2 28 | scikit-learn 29 | tensorboard 30 | tqdm>=4.63.1 31 | tornado>=6.1 32 | Werkzeug>=2.2.3 33 | uc-micro-py>=1.0.1 34 | sympy>=1.11.1 35 | tabulate>=0.8.10 36 | PyYAML>=6.0 37 | pyasn1>=0.4.8 38 | pyasn1-modules>=0.2.8 39 | fsspec>=2022.11.0 40 | absl-py>=1.2.0 41 | audioread 42 | uvicorn>=0.21.1 43 | colorama>=0.4.5 44 | pyworld==0.3.2 45 | httpx 46 | onnxruntime; sys_platform == 'darwin' 47 | onnxruntime-gpu; sys_platform != 'darwin' 48 | torchcrepe==0.0.20 49 | fastapi==0.88 50 | ffmpy==0.3.1 51 | python-dotenv>=1.0.0 52 | av 53 | PySimpleGUI 54 | sounddevice -------------------------------------------------------------------------------- /modules/rvc/requirements-win-for-realtime_vc_gui-dml.txt: -------------------------------------------------------------------------------- 1 | #1.Install torch from pytorch.org: 2 | #torch 2.0 with cuda 11.8 3 | #pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 4 | #torch 1.11.0 with cuda 11.3 5 | #pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 torchaudio==0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113 6 | einops 7 | fairseq 8 | flask 9 | flask_cors 10 | gin 11 | gin_config 12 | librosa 13 | local_attention 14 | matplotlib 15 | praat-parselmouth 16 | pyworld 17 | PyYAML 18 | resampy 19 | scikit_learn 20 | scipy 21 | SoundFile 22 | tensorboard 23 | tqdm 24 | wave 25 | PySimpleGUI 26 | sounddevice 27 | gradio 28 | noisereduce 29 | onnxruntime-directml -------------------------------------------------------------------------------- /modules/rvc/requirements-win-for-realtime_vc_gui.txt: -------------------------------------------------------------------------------- 1 | #1.Install torch from pytorch.org: 2 | #torch 2.0 with cuda 11.8 3 | #pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 4 | #torch 1.11.0 with cuda 11.3 5 | #pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 torchaudio==0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113 6 | einops 7 | fairseq 8 | flask 9 | flask_cors 10 | gin 11 | gin_config 12 | librosa 13 | local_attention 14 | matplotlib 15 | praat-parselmouth 16 | pyworld 17 | PyYAML 18 | resampy 19 | scikit_learn 20 | scipy 21 | SoundFile 22 | tensorboard 23 | tqdm 24 | wave 25 | PySimpleGUI 26 | sounddevice 27 | gradio 28 | noisereduce 29 | -------------------------------------------------------------------------------- /modules/rvc/requirements.txt: -------------------------------------------------------------------------------- 1 | joblib>=1.1.0 2 | numba==0.56.4 3 | numpy==1.23.5 4 | scipy 5 | librosa==0.9.1 6 | llvmlite==0.39.0 7 | faiss-cpu==1.7.3 8 | gradio==3.34.0 9 | Cython 10 | pydub>=0.25.1 11 | soundfile>=0.12.1 12 | ffmpeg-python>=0.2.0 13 | tensorboardX 14 | Jinja2>=3.1.2 15 | json5 16 | Markdown 17 | matplotlib>=3.7.0 18 | matplotlib-inline>=0.1.3 19 | praat-parselmouth>=0.4.2 20 | Pillow>=9.1.1 21 | resampy>=0.4.2 22 | scikit-learn 23 | tensorboard 24 | tqdm>=4.63.1 25 | tornado>=6.1 26 | Werkzeug>=2.2.3 27 | uc-micro-py>=1.0.1 28 | sympy>=1.11.1 29 | tabulate>=0.8.10 30 | PyYAML>=6.0 31 | pyasn1>=0.4.8 32 | pyasn1-modules>=0.2.8 33 | fsspec>=2022.11.0 34 | absl-py>=1.2.0 35 | audioread 36 | uvicorn>=0.21.1 37 | colorama>=0.4.5 38 | pyworld==0.3.2 39 | httpx 40 | onnxruntime; sys_platform == 'darwin' 41 | onnxruntime-gpu; sys_platform != 'darwin' 42 | torchcrepe==0.0.20 43 | fastapi==0.88 44 | ffmpy==0.3.1 45 | python-dotenv>=1.0.0 46 | av 47 | -------------------------------------------------------------------------------- /modules/rvc/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$(uname)" == "Darwin" ]]; then 4 | # macOS specific env: 5 | export PYTORCH_ENABLE_MPS_FALLBACK=1 6 | export PYTORCH_MPS_HIGH_WATERMARK_RATIO=0.0 7 | elif [[ "$(uname)" != "Linux" ]]; then 8 | echo "Unsupported operating system." 9 | exit 1 10 | fi 11 | 12 | if [ -d ".venv" ]; then 13 | echo "Activate venv..." 14 | source .venv/bin/activate 15 | else 16 | echo "Create venv..." 17 | requirements_file="requirements.txt" 18 | 19 | # Check if Python 3.8 is installed 20 | if ! command -v python3 &> /dev/null; then 21 | echo "Python 3 not found. Attempting to install 3.8..." 22 | if [[ "$(uname)" == "Darwin" ]] && command -v brew &> /dev/null; then 23 | brew install python@3.8 24 | elif [[ "$(uname)" == "Linux" ]] && command -v apt-get &> /dev/null; then 25 | sudo apt-get update 26 | sudo apt-get install python3.8 27 | else 28 | echo "Please install Python 3.8 manually." 29 | exit 1 30 | fi 31 | fi 32 | 33 | python3 -m venv .venv 34 | source .venv/bin/activate 35 | 36 | # Check if required packages are installed and install them if not 37 | if [ -f "${requirements_file}" ]; then 38 | installed_packages=$(python3 -m pip freeze) 39 | while IFS= read -r package; do 40 | [[ "${package}" =~ ^#.* ]] && continue 41 | package_name=$(echo "${package}" | sed 's/[<>=!].*//') 42 | if ! echo "${installed_packages}" | grep -q "${package_name}"; then 43 | echo "${package_name} not found. Attempting to install..." 44 | python3 -m pip install --upgrade "${package}" 45 | fi 46 | done < "${requirements_file}" 47 | else 48 | echo "${requirements_file} not found. Please ensure the requirements file with required packages exists." 49 | exit 1 50 | fi 51 | fi 52 | 53 | # Download models 54 | ./tools/dlmodels.sh 55 | 56 | if [[ $? -ne 0 ]]; then 57 | exit 1 58 | fi 59 | 60 | # Run the main script 61 | python3 infer-web.py --pycmd python3 62 | -------------------------------------------------------------------------------- /modules/rvc/tools/app.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | # os.system("wget -P cvec/ https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt") 5 | import gradio as gr 6 | from dotenv import load_dotenv 7 | 8 | from configs.config import Config 9 | from i18n.i18n import I18nAuto 10 | from modules.rvc.infer.modules.vc.modules import VC 11 | 12 | logging.getLogger("numba").setLevel(logging.WARNING) 13 | logging.getLogger("markdown_it").setLevel(logging.WARNING) 14 | logging.getLogger("urllib3").setLevel(logging.WARNING) 15 | logging.getLogger("matplotlib").setLevel(logging.WARNING) 16 | logger = logging.getLogger(__name__) 17 | 18 | i18n = I18nAuto() 19 | logger.info(i18n) 20 | 21 | load_dotenv() 22 | config = Config() 23 | vc = VC(config) 24 | 25 | weight_root = os.getenv("weight_root") 26 | weight_uvr5_root = os.getenv("weight_uvr5_root") 27 | index_root = os.getenv("index_root") 28 | names = [] 29 | hubert_model = None 30 | for name in os.listdir(weight_root): 31 | if name.endswith(".pth"): 32 | names.append(name) 33 | index_paths = [] 34 | for root, dirs, files in os.walk(index_root, topdown=False): 35 | for name in files: 36 | if name.endswith(".index") and "trained" not in name: 37 | index_paths.append("%s/%s" % (root, name)) 38 | 39 | 40 | app = gr.Blocks() 41 | with app: 42 | with gr.Tabs(): 43 | with gr.TabItem("在线demo"): 44 | gr.Markdown( 45 | value=""" 46 | RVC 在线demo 47 | """ 48 | ) 49 | sid = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names)) 50 | with gr.Column(): 51 | spk_item = gr.Slider( 52 | minimum=0, 53 | maximum=2333, 54 | step=1, 55 | label=i18n("请选择说话人id"), 56 | value=0, 57 | visible=False, 58 | interactive=True, 59 | ) 60 | sid.change(fn=vc.get_vc, inputs=[sid], outputs=[spk_item]) 61 | gr.Markdown( 62 | value=i18n("男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ") 63 | ) 64 | vc_input3 = gr.Audio(label="上传音频(长度小于90秒)") 65 | vc_transform0 = gr.Number(label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0) 66 | f0method0 = gr.Radio( 67 | label=i18n("选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU"), 68 | choices=["pm", "harvest", "crepe", "rmvpe"], 69 | value="pm", 70 | interactive=True, 71 | ) 72 | filter_radius0 = gr.Slider( 73 | minimum=0, 74 | maximum=7, 75 | label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"), 76 | value=3, 77 | step=1, 78 | interactive=True, 79 | ) 80 | with gr.Column(): 81 | file_index1 = gr.Textbox( 82 | label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"), 83 | value="", 84 | interactive=False, 85 | visible=False, 86 | ) 87 | file_index2 = gr.Dropdown( 88 | label=i18n("自动检测index路径,下拉式选择(dropdown)"), 89 | choices=sorted(index_paths), 90 | interactive=True, 91 | ) 92 | index_rate1 = gr.Slider( 93 | minimum=0, 94 | maximum=1, 95 | label=i18n("检索特征占比"), 96 | value=0.88, 97 | interactive=True, 98 | ) 99 | resample_sr0 = gr.Slider( 100 | minimum=0, 101 | maximum=48000, 102 | label=i18n("后处理重采样至最终采样率,0为不进行重采样"), 103 | value=0, 104 | step=1, 105 | interactive=True, 106 | ) 107 | rms_mix_rate0 = gr.Slider( 108 | minimum=0, 109 | maximum=1, 110 | label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"), 111 | value=1, 112 | interactive=True, 113 | ) 114 | protect0 = gr.Slider( 115 | minimum=0, 116 | maximum=0.5, 117 | label=i18n("保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"), 118 | value=0.33, 119 | step=0.01, 120 | interactive=True, 121 | ) 122 | f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调")) 123 | but0 = gr.Button(i18n("转换"), variant="primary") 124 | vc_output1 = gr.Textbox(label=i18n("输出信息")) 125 | vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)")) 126 | but0.click( 127 | vc.vc_single, 128 | [ 129 | spk_item, 130 | vc_input3, 131 | vc_transform0, 132 | f0_file, 133 | f0method0, 134 | file_index1, 135 | file_index2, 136 | # file_big_npy1, 137 | index_rate1, 138 | filter_radius0, 139 | resample_sr0, 140 | rms_mix_rate0, 141 | protect0, 142 | ], 143 | [vc_output1, vc_output2], 144 | ) 145 | 146 | 147 | app.launch() 148 | -------------------------------------------------------------------------------- /modules/rvc/tools/calc_rvc_model_similarity.py: -------------------------------------------------------------------------------- 1 | # This code references https://huggingface.co/JosephusCheung/ASimilarityCalculatior/blob/main/qwerty.py 2 | # Fill in the path of the model to be queried and the root directory of the reference models, and this script will return the similarity between the model to be queried and all reference models. 3 | import os 4 | import logging 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | import torch 9 | import torch.nn as nn 10 | import torch.nn.functional as F 11 | 12 | 13 | def cal_cross_attn(to_q, to_k, to_v, rand_input): 14 | hidden_dim, embed_dim = to_q.shape 15 | attn_to_q = nn.Linear(hidden_dim, embed_dim, bias=False) 16 | attn_to_k = nn.Linear(hidden_dim, embed_dim, bias=False) 17 | attn_to_v = nn.Linear(hidden_dim, embed_dim, bias=False) 18 | attn_to_q.load_state_dict({"weight": to_q}) 19 | attn_to_k.load_state_dict({"weight": to_k}) 20 | attn_to_v.load_state_dict({"weight": to_v}) 21 | 22 | return torch.einsum( 23 | "ik, jk -> ik", 24 | F.softmax( 25 | torch.einsum("ij, kj -> ik", attn_to_q(rand_input), attn_to_k(rand_input)), 26 | dim=-1, 27 | ), 28 | attn_to_v(rand_input), 29 | ) 30 | 31 | 32 | def model_hash(filename): 33 | try: 34 | with open(filename, "rb") as file: 35 | import hashlib 36 | 37 | m = hashlib.sha256() 38 | 39 | file.seek(0x100000) 40 | m.update(file.read(0x10000)) 41 | return m.hexdigest()[0:8] 42 | except FileNotFoundError: 43 | return "NOFILE" 44 | 45 | 46 | def eval(model, n, input): 47 | qk = f"enc_p.encoder.attn_layers.{n}.conv_q.weight" 48 | uk = f"enc_p.encoder.attn_layers.{n}.conv_k.weight" 49 | vk = f"enc_p.encoder.attn_layers.{n}.conv_v.weight" 50 | atoq, atok, atov = model[qk][:, :, 0], model[uk][:, :, 0], model[vk][:, :, 0] 51 | 52 | attn = cal_cross_attn(atoq, atok, atov, input) 53 | return attn 54 | 55 | 56 | def main(path, root): 57 | torch.manual_seed(114514) 58 | model_a = torch.load(path, map_location="cpu", weights_only=True)["weight"] 59 | 60 | logger.info("Query:\t\t%s\t%s" % (path, model_hash(path))) 61 | 62 | map_attn_a = {} 63 | map_rand_input = {} 64 | for n in range(6): 65 | hidden_dim, embed_dim, _ = model_a[ 66 | f"enc_p.encoder.attn_layers.{n}.conv_v.weight" 67 | ].shape 68 | rand_input = torch.randn([embed_dim, hidden_dim]) 69 | 70 | map_attn_a[n] = eval(model_a, n, rand_input) 71 | map_rand_input[n] = rand_input 72 | 73 | del model_a 74 | 75 | for name in sorted(list(os.listdir(root))): 76 | path = "%s/%s" % (root, name) 77 | model_b = torch.load(path, map_location="cpu", weights_only=True)["weight"] 78 | 79 | sims = [] 80 | for n in range(6): 81 | attn_a = map_attn_a[n] 82 | attn_b = eval(model_b, n, map_rand_input[n]) 83 | 84 | sim = torch.mean(torch.cosine_similarity(attn_a, attn_b)) 85 | sims.append(sim) 86 | 87 | logger.info( 88 | "Reference:\t%s\t%s\t%s" 89 | % (path, model_hash(path), f"{torch.mean(torch.stack(sims)) * 1e2:.2f}%") 90 | ) 91 | 92 | 93 | if __name__ == "__main__": 94 | query_path = r"assets\weights\mi v3.pth" 95 | reference_root = r"assets\weights" 96 | main(query_path, reference_root) 97 | -------------------------------------------------------------------------------- /modules/rvc/tools/export_onnx.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from modules.rvc.infer.lib.infer_pack.models_onnx import SynthesizerTrnMsNSFsidM 3 | 4 | if __name__ == "__main__": 5 | MoeVS = True # 模型是否为MoeVoiceStudio(原MoeSS)使用 6 | 7 | ModelPath = "Shiroha/shiroha.pth" # 模型路径 8 | ExportedPath = "model.onnx" # 输出路径 9 | hidden_channels = 256 # hidden_channels,为768Vec做准备 10 | cpt = torch.load(ModelPath, map_location="cpu", weights_only=True) 11 | cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk 12 | print(*cpt["config"]) 13 | 14 | test_phone = torch.rand(1, 200, hidden_channels) # hidden unit 15 | test_phone_lengths = torch.tensor([200]).long() # hidden unit 长度(貌似没啥用) 16 | test_pitch = torch.randint(size=(1, 200), low=5, high=255) # 基频(单位赫兹) 17 | test_pitchf = torch.rand(1, 200) # nsf基频 18 | test_ds = torch.LongTensor([0]) # 说话人ID 19 | test_rnd = torch.rand(1, 192, 200) # 噪声(加入随机因子) 20 | 21 | device = "cpu" # 导出时设备(不影响使用模型) 22 | 23 | net_g = SynthesizerTrnMsNSFsidM( 24 | *cpt["config"], is_half=False 25 | ) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16) 26 | net_g.load_state_dict(cpt["weight"], strict=False) 27 | input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"] 28 | output_names = [ 29 | "audio", 30 | ] 31 | # net_g.construct_spkmixmap(n_speaker) 多角色混合轨道导出 32 | torch.onnx.export( 33 | net_g, 34 | ( 35 | test_phone.to(device), 36 | test_phone_lengths.to(device), 37 | test_pitch.to(device), 38 | test_pitchf.to(device), 39 | test_ds.to(device), 40 | test_rnd.to(device), 41 | ), 42 | ExportedPath, 43 | dynamic_axes={ 44 | "phone": [1], 45 | "pitch": [1], 46 | "pitchf": [1], 47 | "rnd": [2], 48 | }, 49 | do_constant_folding=False, 50 | opset_version=16, 51 | verbose=False, 52 | input_names=input_names, 53 | output_names=output_names, 54 | ) 55 | -------------------------------------------------------------------------------- /modules/rvc/tools/infer/train-index-v2.py: -------------------------------------------------------------------------------- 1 | """ 2 | 格式:直接cid为自带的index位;aid放不下了,通过字典来查,反正就5w个 3 | """ 4 | import os 5 | import traceback 6 | import logging 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | from multiprocessing import cpu_count 11 | 12 | import faiss 13 | import numpy as np 14 | from sklearn.cluster import MiniBatchKMeans 15 | 16 | # ###########如果是原始特征要先写save 17 | n_cpu = 0 18 | if n_cpu == 0: 19 | n_cpu = cpu_count() 20 | inp_root = r"./logs/anz/3_feature768" 21 | npys = [] 22 | listdir_res = list(os.listdir(inp_root)) 23 | for name in sorted(listdir_res): 24 | phone = np.load("%s/%s" % (inp_root, name)) 25 | npys.append(phone) 26 | big_npy = np.concatenate(npys, 0) 27 | big_npy_idx = np.arange(big_npy.shape[0]) 28 | np.random.shuffle(big_npy_idx) 29 | big_npy = big_npy[big_npy_idx] 30 | logger.debug(big_npy.shape) # (6196072, 192)#fp32#4.43G 31 | if big_npy.shape[0] > 2e5: 32 | # if(1): 33 | info = "Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0] 34 | logger.info(info) 35 | try: 36 | big_npy = ( 37 | MiniBatchKMeans( 38 | n_clusters=10000, 39 | verbose=True, 40 | batch_size=256 * n_cpu, 41 | compute_labels=False, 42 | init="random", 43 | ) 44 | .fit(big_npy) 45 | .cluster_centers_ 46 | ) 47 | except: 48 | info = traceback.format_exc() 49 | logger.warning(info) 50 | 51 | np.save("tools/infer/big_src_feature_mi.npy", big_npy) 52 | 53 | ##################train+add 54 | # big_npy=np.load("/bili-coeus/jupyter/jupyterhub-liujing04/vits_ch/inference_f0/big_src_feature_mi.npy") 55 | n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39) 56 | index = faiss.index_factory(768, "IVF%s,Flat" % n_ivf) # mi 57 | logger.info("Training...") 58 | index_ivf = faiss.extract_index_ivf(index) # 59 | index_ivf.nprobe = 1 60 | index.train(big_npy) 61 | faiss.write_index( 62 | index, "tools/infer/trained_IVF%s_Flat_baseline_src_feat_v2.index" % (n_ivf) 63 | ) 64 | logger.info("Adding...") 65 | batch_size_add = 8192 66 | for i in range(0, big_npy.shape[0], batch_size_add): 67 | index.add(big_npy[i : i + batch_size_add]) 68 | faiss.write_index( 69 | index, "tools/infer/added_IVF%s_Flat_mi_baseline_src_feat.index" % (n_ivf) 70 | ) 71 | """ 72 | 大小(都是FP32) 73 | big_src_feature 2.95G 74 | (3098036, 256) 75 | big_emb 4.43G 76 | (6196072, 192) 77 | big_emb双倍是因为求特征要repeat后再加pitch 78 | 79 | """ 80 | -------------------------------------------------------------------------------- /modules/rvc/tools/infer/train-index.py: -------------------------------------------------------------------------------- 1 | """ 2 | 格式:直接cid为自带的index位;aid放不下了,通过字典来查,反正就5w个 3 | """ 4 | import os 5 | import logging 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | import faiss 10 | import numpy as np 11 | 12 | # ###########如果是原始特征要先写save 13 | inp_root = r"E:\codes\py39\dataset\mi\2-co256" 14 | npys = [] 15 | for name in sorted(list(os.listdir(inp_root))): 16 | phone = np.load("%s/%s" % (inp_root, name)) 17 | npys.append(phone) 18 | big_npy = np.concatenate(npys, 0) 19 | logger.debug(big_npy.shape) # (6196072, 192)#fp32#4.43G 20 | np.save("infer/big_src_feature_mi.npy", big_npy) 21 | 22 | ##################train+add 23 | # big_npy=np.load("/bili-coeus/jupyter/jupyterhub-liujing04/vits_ch/inference_f0/big_src_feature_mi.npy") 24 | logger.debug(big_npy.shape) 25 | index = faiss.index_factory(256, "IVF512,Flat") # mi 26 | logger.info("Training...") 27 | index_ivf = faiss.extract_index_ivf(index) # 28 | index_ivf.nprobe = 9 29 | index.train(big_npy) 30 | faiss.write_index(index, "infer/trained_IVF512_Flat_mi_baseline_src_feat.index") 31 | logger.info("Adding...") 32 | index.add(big_npy) 33 | faiss.write_index(index, "infer/added_IVF512_Flat_mi_baseline_src_feat.index") 34 | """ 35 | 大小(都是FP32) 36 | big_src_feature 2.95G 37 | (3098036, 256) 38 | big_emb 4.43G 39 | (6196072, 192) 40 | big_emb双倍是因为求特征要repeat后再加pitch 41 | 42 | """ 43 | -------------------------------------------------------------------------------- /modules/rvc/tools/infer/trans_weights.py: -------------------------------------------------------------------------------- 1 | import pdb 2 | 3 | import torch 4 | 5 | # a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-suc\G_1000.pth")["model"]#sim_nsf# 6 | # a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-freeze-vocoder-flow-enc_q\G_1000.pth")["model"]#sim_nsf# 7 | # a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-freeze-vocoder\G_1000.pth")["model"]#sim_nsf# 8 | # a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-test\G_1000.pth")["model"]#sim_nsf# 9 | a = torch.load( 10 | r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-no_opt-no_dropout\G_1000.pth", weights_only=True 11 | )[ 12 | "model" 13 | ] # sim_nsf# 14 | for key in a.keys(): 15 | a[key] = a[key].half() 16 | # torch.save(a,"ft-mi-freeze-vocoder_true_1k.pt")# 17 | # torch.save(a,"ft-mi-sim1k.pt")# 18 | torch.save(a, "ft-mi-no_opt-no_dropout.pt") # 19 | -------------------------------------------------------------------------------- /modules/rvc/tools/infer_batch_rvc.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import sys 4 | 5 | print("Command-line arguments:", sys.argv) 6 | 7 | now_dir = os.getcwd() 8 | sys.path.append(now_dir) 9 | import sys 10 | 11 | import tqdm as tq 12 | from dotenv import load_dotenv 13 | from scipy.io import wavfile 14 | 15 | from configs.config import Config 16 | from modules.rvc.infer.modules.vc.modules import VC 17 | 18 | 19 | def arg_parse() -> tuple: 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument("--f0up_key", type=int, default=0) 22 | parser.add_argument("--input_path", type=str, help="input path") 23 | parser.add_argument("--index_path", type=str, help="index path") 24 | parser.add_argument("--f0method", type=str, default="harvest", help="harvest or pm") 25 | parser.add_argument("--opt_path", type=str, help="opt path") 26 | parser.add_argument("--model_name", type=str, help="store in assets/weight_root") 27 | parser.add_argument("--index_rate", type=float, default=0.66, help="index rate") 28 | parser.add_argument("--device", type=str, help="device") 29 | parser.add_argument("--is_half", type=bool, help="use half -> True") 30 | parser.add_argument("--filter_radius", type=int, default=3, help="filter radius") 31 | parser.add_argument("--resample_sr", type=int, default=0, help="resample sr") 32 | parser.add_argument("--rms_mix_rate", type=float, default=1, help="rms mix rate") 33 | parser.add_argument("--protect", type=float, default=0.33, help="protect") 34 | 35 | args = parser.parse_args() 36 | sys.argv = sys.argv[:1] 37 | 38 | return args 39 | 40 | 41 | def main(): 42 | load_dotenv() 43 | args = arg_parse() 44 | config = Config() 45 | config.device = args.device if args.device else config.device 46 | config.is_half = args.is_half if args.is_half else config.is_half 47 | vc = VC(config) 48 | vc.get_vc(args.model_name) 49 | audios = os.listdir(args.input_path) 50 | for file in tq.tqdm(audios): 51 | if file.endswith(".wav"): 52 | file_path = os.path.join(args.input_path, file) 53 | _, wav_opt = vc.vc_single( 54 | 0, 55 | file_path, 56 | args.f0up_key, 57 | None, 58 | args.f0method, 59 | args.index_path, 60 | None, 61 | args.index_rate, 62 | args.filter_radius, 63 | args.resample_sr, 64 | args.rms_mix_rate, 65 | args.protect, 66 | ) 67 | out_path = os.path.join(args.opt_path, file) 68 | wavfile.write(out_path, wav_opt[0], wav_opt[1]) 69 | 70 | 71 | if __name__ == "__main__": 72 | main() 73 | -------------------------------------------------------------------------------- /modules/rvc/tools/infer_cli.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import sys 4 | 5 | now_dir = os.getcwd() 6 | sys.path.append(now_dir) 7 | from dotenv import load_dotenv 8 | from scipy.io import wavfile 9 | 10 | from configs.config import Config 11 | from modules.rvc.infer.modules.vc.modules import VC 12 | 13 | #### 14 | # USAGE 15 | # 16 | # In your Terminal or CMD or whatever 17 | 18 | 19 | def arg_parse() -> tuple: 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument("--f0up_key", type=int, default=0) 22 | parser.add_argument("--input_path", type=str, help="input path") 23 | parser.add_argument("--index_path", type=str, help="index path") 24 | parser.add_argument("--f0method", type=str, default="harvest", help="harvest or pm") 25 | parser.add_argument("--opt_path", type=str, help="opt path") 26 | parser.add_argument("--model_name", type=str, help="store in assets/weight_root") 27 | parser.add_argument("--index_rate", type=float, default=0.66, help="index rate") 28 | parser.add_argument("--device", type=str, help="device") 29 | parser.add_argument("--is_half", type=bool, help="use half -> True") 30 | parser.add_argument("--filter_radius", type=int, default=3, help="filter radius") 31 | parser.add_argument("--resample_sr", type=int, default=0, help="resample sr") 32 | parser.add_argument("--rms_mix_rate", type=float, default=1, help="rms mix rate") 33 | parser.add_argument("--protect", type=float, default=0.33, help="protect") 34 | 35 | args = parser.parse_args() 36 | sys.argv = sys.argv[:1] 37 | 38 | return args 39 | 40 | 41 | def main(): 42 | load_dotenv() 43 | args = arg_parse() 44 | config = Config() 45 | config.device = args.device if args.device else config.device 46 | config.is_half = args.is_half if args.is_half else config.is_half 47 | vc = VC(config) 48 | vc.get_vc(args.model_name) 49 | _, wav_opt = vc.vc_single( 50 | 0, 51 | args.input_path, 52 | args.f0up_key, 53 | None, 54 | args.f0method, 55 | args.index_path, 56 | None, 57 | args.index_rate, 58 | args.filter_radius, 59 | args.resample_sr, 60 | args.rms_mix_rate, 61 | args.protect, 62 | ) 63 | wavfile.write(args.opt_path, wav_opt[0], wav_opt[1]) 64 | 65 | 66 | if __name__ == "__main__": 67 | main() 68 | -------------------------------------------------------------------------------- /modules/rvc/tools/onnx_inference_demo.py: -------------------------------------------------------------------------------- 1 | import soundfile 2 | 3 | from ..modules.rvc.infer.lib.infer_pack.onnx_inference import OnnxRVC 4 | 5 | hop_size = 512 6 | sampling_rate = 40000 # 采样率 7 | f0_up_key = 0 # 升降调 8 | sid = 0 # 角色ID 9 | f0_method = "dio" # F0提取算法 10 | model_path = "ShirohaRVC.onnx" # 模型的完整路径 11 | vec_name = "vec-256-layer-9" # 内部自动补齐为 f"pretrained/{vec_name}.onnx" 需要onnx的vec模型 12 | wav_path = "123.wav" # 输入路径或ByteIO实例 13 | out_path = "out.wav" # 输出路径或ByteIO实例 14 | 15 | model = OnnxRVC( 16 | model_path, vec_path=vec_name, sr=sampling_rate, hop_size=hop_size, device="cuda" 17 | ) 18 | 19 | audio = model.inference(wav_path, sid, f0_method=f0_method, f0_up_key=f0_up_key) 20 | 21 | soundfile.write(out_path, audio, sampling_rate) 22 | -------------------------------------------------------------------------------- /modules/rvc/tools/torchgate/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | TorchGating is a PyTorch-based implementation of Spectral Gating 3 | ================================================ 4 | Author: Asaf Zorea 5 | 6 | Contents 7 | -------- 8 | torchgate imports all the functions from PyTorch, and in addition provides: 9 | TorchGating --- A PyTorch module that applies a spectral gate to an input signal 10 | 11 | """ 12 | from .torchgate import TorchGate 13 | -------------------------------------------------------------------------------- /modules/rvc/tools/torchgate/utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.types import Number 3 | 4 | 5 | @torch.no_grad() 6 | def amp_to_db( 7 | x: torch.Tensor, eps=torch.finfo(torch.float64).eps, top_db=40 8 | ) -> torch.Tensor: 9 | """ 10 | Convert the input tensor from amplitude to decibel scale. 11 | 12 | Arguments: 13 | x {[torch.Tensor]} -- [Input tensor.] 14 | 15 | Keyword Arguments: 16 | eps {[float]} -- [Small value to avoid numerical instability.] 17 | (default: {torch.finfo(torch.float64).eps}) 18 | top_db {[float]} -- [threshold the output at ``top_db`` below the peak] 19 | ` (default: {40}) 20 | 21 | Returns: 22 | [torch.Tensor] -- [Output tensor in decibel scale.] 23 | """ 24 | x_db = 20 * torch.log10(x.abs() + eps) 25 | return torch.max(x_db, (x_db.max(-1).values - top_db).unsqueeze(-1)) 26 | 27 | 28 | @torch.no_grad() 29 | def temperature_sigmoid(x: torch.Tensor, x0: float, temp_coeff: float) -> torch.Tensor: 30 | """ 31 | Apply a sigmoid function with temperature scaling. 32 | 33 | Arguments: 34 | x {[torch.Tensor]} -- [Input tensor.] 35 | x0 {[float]} -- [Parameter that controls the threshold of the sigmoid.] 36 | temp_coeff {[float]} -- [Parameter that controls the slope of the sigmoid.] 37 | 38 | Returns: 39 | [torch.Tensor] -- [Output tensor after applying the sigmoid with temperature scaling.] 40 | """ 41 | return torch.sigmoid((x - x0) / temp_coeff) 42 | 43 | 44 | @torch.no_grad() 45 | def linspace( 46 | start: Number, stop: Number, num: int = 50, endpoint: bool = True, **kwargs 47 | ) -> torch.Tensor: 48 | """ 49 | Generate a linearly spaced 1-D tensor. 50 | 51 | Arguments: 52 | start {[Number]} -- [The starting value of the sequence.] 53 | stop {[Number]} -- [The end value of the sequence, unless `endpoint` is set to False. 54 | In that case, the sequence consists of all but the last of ``num + 1`` 55 | evenly spaced samples, so that `stop` is excluded. Note that the step 56 | size changes when `endpoint` is False.] 57 | 58 | Keyword Arguments: 59 | num {[int]} -- [Number of samples to generate. Default is 50. Must be non-negative.] 60 | endpoint {[bool]} -- [If True, `stop` is the last sample. Otherwise, it is not included. 61 | Default is True.] 62 | **kwargs -- [Additional arguments to be passed to the underlying PyTorch `linspace` function.] 63 | 64 | Returns: 65 | [torch.Tensor] -- [1-D tensor of `num` equally spaced samples from `start` to `stop`.] 66 | """ 67 | if endpoint: 68 | return torch.linspace(start, stop, num, **kwargs) 69 | else: 70 | return torch.linspace(start, stop, num + 1, **kwargs)[:-1] 71 | -------------------------------------------------------------------------------- /modules/rvc/venv.sh: -------------------------------------------------------------------------------- 1 | python3.8 -m venv .venv 2 | -------------------------------------------------------------------------------- /notebook_paperspace.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "ni41hmE03DL6" 7 | }, 8 | "source": [ 9 | "## Initialization" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "metadata": { 15 | "id": "FtsMKKfH18iM" 16 | }, 17 | "source": [ 18 | "!sudo apt update\n", 19 | "!sudo apt-get install python3.9-venv -y\n", 20 | "%cd /notebooks/\n", 21 | "!git clone https://git.ecker.tech/mrq/ai-voice-cloning/\n", 22 | "!ln -s ./ai-voice-cloning/models/ ./\n", 23 | "%cd ai-voice-cloning\n", 24 | "!./setup-cuda.sh\n", 25 | "#!./update.sh" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "IzrGt5IcHlAD" 32 | }, 33 | "source": [ 34 | "# Update Repos" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "metadata": { 40 | "id": "3DktoOXSHmtw" 41 | }, 42 | "source": [ 43 | "# for my debugging purposes\n", 44 | "%cd /notebooks/ai-voice-cloning/\n", 45 | "!sudo apt update\n", 46 | "!sudo apt-get install python3.9-venv -y\n", 47 | "!mkdir -p ~/.cache\n", 48 | "!ln -s /notebooks/ai-voice-cloning/models/voicefixer ~/.cache/.\n", 49 | "!./update-force.sh\n", 50 | "#!git pull\n", 51 | "#!git submodule update --remote" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": { 57 | "id": "o1gkfw3B3JSk" 58 | }, 59 | "source": [ 60 | "## Running" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "metadata": { 66 | "id": "c_EQZLTA19c7" 67 | }, 68 | "source": [ 69 | "%cd /notebooks/ai-voice-cloning\n", 70 | "\n", 71 | "!export TORTOISE_MODELS_DIR=/notebooks/ai-voice-cloning/models/tortoise/\n", 72 | "!export TRANSFORMERS_CACHE=/notebooks/ai-voice-cloning/models/transformers/\n", 73 | "\n", 74 | "!./start.sh --share" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": { 80 | "id": "2AnVQxEJx47p" 81 | }, 82 | "source": [ 83 | "## Exporting" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "metadata": { 89 | "id": "YOACiDCXx72G" 90 | }, 91 | "source": [ 92 | "%cd /notebooks/ai-voice-cloning\n", 93 | "!apt install -y p7zip-full\n", 94 | "from datetime import datetime\n", 95 | "timestamp = datetime.now().strftime('%m-%d-%Y_%H:%M:%S')\n", 96 | "!mkdir -p \"../{timestamp}/results\"\n", 97 | "!mv ./results/* \"../{timestamp}/results/.\"\n", 98 | "!mv ./training/* \"../{timestamp}/training/.\"\n", 99 | "!7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on \"../{timestamp}.7z\" \"../{timestamp}/\"\n", 100 | "!ls ~/\n", 101 | "!echo \"Finished zipping, archive is available at {timestamp}.7z\"" 102 | ] 103 | } 104 | ], 105 | "metadata": { 106 | "accelerator": "GPU", 107 | "colab": { 108 | "private_outputs": true, 109 | "provenance": [] 110 | }, 111 | "gpuClass": "standard", 112 | "kernelspec": { 113 | "display_name": "Python 3 (ipykernel)", 114 | "language": "python", 115 | "name": "python3" 116 | }, 117 | "language_info": { 118 | "codemirror_mode": { 119 | "name": "ipython", 120 | "version": 3 121 | }, 122 | "file_extension": ".py", 123 | "mimetype": "text/x-python", 124 | "name": "python", 125 | "nbconvert_exporter": "python", 126 | "pygments_lexer": "ipython3", 127 | "version": "3.9.13" 128 | } 129 | }, 130 | "nbformat": 4, 131 | "nbformat_minor": 4 132 | } 133 | -------------------------------------------------------------------------------- /reload_flag.txt: -------------------------------------------------------------------------------- 1 | reload -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | openai-whisper 2 | more-itertools 3 | ffmpeg-python 4 | gradio==4.22.0 5 | music-tag 6 | voicefixer 7 | psutil 8 | phonemizer 9 | pydantic==2.6.4 10 | websockets 11 | beartype==0.15.0 12 | pykakasi 13 | rotary-embedding-torch==0.4.0 14 | transformers==4.29.2 15 | omegaconf==2.3 16 | pysrt 17 | librosa==0.9.1 18 | fastapi==0.112.1 19 | starlette==0.38.2 -------------------------------------------------------------------------------- /setup-cuda-bnb.bat: -------------------------------------------------------------------------------- 1 | 2 | git clone https://github.com/JarodMica/bitsandbytes-windows.git .\modules\bitsandbytes-windows\ 3 | 4 | xcopy .\modules\bitsandbytes-windows\bin\* .\venv\Lib\site-packages\bitsandbytes\. /Y 5 | xcopy .\modules\bitsandbytes-windows\bin\cuda_setup\* .\venv\Lib\site-packages\bitsandbytes\cuda_setup\. /Y 6 | xcopy .\modules\bitsandbytes-windows\bin\nn\* .\venv\Lib\site-packages\bitsandbytes\nn\. /Y 7 | -------------------------------------------------------------------------------- /setup-cuda-cpu.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | :: Check if Python 3.9 is installed 5 | py -3.9 --version >nul 2>&1 6 | if errorlevel 1 ( 7 | echo Python 3.9 is not installed. Please install it and try again. 8 | pause 9 | exit /b 1 10 | ) 11 | 12 | :: Initialize and update git submodules 13 | git submodule init 14 | git submodule update --remote 15 | 16 | :: Set up virtual environment with Python 3.9 17 | py -3.9 -m venv venv 18 | call .\venv\Scripts\activate.bat 19 | 20 | :: Upgrade pip and install required packages 21 | python -m pip install --upgrade pip 22 | python -m pip install torch torchvision torchaudio 23 | python -m pip install -r .\modules\tortoise-tts\requirements.txt 24 | python -m pip install -e .\modules\tortoise-tts\ 25 | python -m pip install -r .\modules\dlas\requirements.txt 26 | python -m pip install -e .\modules\dlas\ 27 | @REM python -m pip install deepspeed-0.8.3+6eca037c-cp39-cp39-win_amd64.whl 28 | 29 | :: Download and extract RVC if not already done 30 | set file_name=rvc.zip 31 | set download_rvc=https://huggingface.co/Jmica/rvc/resolve/main/rvc_lightweight.zip?download=true 32 | set extracted_folder=rvc 33 | 34 | if exist "%extracted_folder%" ( 35 | echo The folder %extracted_folder% already exists. 36 | choice /C YN /M "Do you want to delete it and re-extract (Y/N)?" 37 | if errorlevel 2 goto SkipDeletion 38 | if errorlevel 1 ( 39 | echo Deleting %extracted_folder%... 40 | rmdir /S /Q "%extracted_folder%" 41 | ) 42 | ) 43 | 44 | :SkipDeletion 45 | if not exist "%file_name%" ( 46 | echo Downloading %file_name%... 47 | curl -L %download_rvc% -o %file_name% 48 | ) else ( 49 | echo File %file_name% already exists, skipping download. 50 | ) 51 | 52 | echo Extracting %file_name%... 53 | tar -xf %file_name% 54 | echo RVC has finished downloading and Extracting. 55 | 56 | :: Install RVC requirements 57 | python -m pip install -r .\rvc\requirements.txt 58 | 59 | :: Download and install Fairseq if not already done 60 | set download_fairseq=https://huggingface.co/Jmica/rvc/resolve/main/fairseq-0.12.2-cp39-cp39-win_amd64.whl?download=true 61 | set file_name=fairseq-0.12.2-cp39-cp39-win_amd64.whl 62 | 63 | if not exist "%file_name%" ( 64 | echo Downloading %file_name%... 65 | curl -L -O "%download_fairseq%" 66 | if errorlevel 1 ( 67 | echo Download failed. Please check your internet connection or the URL and try again. 68 | exit /b 1 69 | ) 70 | ) else ( 71 | echo File %file_name% already exists, skipping download. 72 | ) 73 | 74 | :: Install Fairseq and RVC TTS Pipeline 75 | python -m pip install .\fairseq-0.12.2-cp39-cp39-win_amd64.whl 76 | python -m pip install git+https://github.com/JarodMica/rvc-tts-pipeline.git@lightweight#egg=rvc_tts_pipe 77 | 78 | :: Install other requirements (this is done last due to potential package conflicts) 79 | python -m pip install -r .\requirements.txt 80 | 81 | :: Setup BnB 82 | .\setup-cuda-bnb.bat 83 | 84 | :: Clean up 85 | del *.sh 86 | 87 | pause 88 | deactivate 89 | -------------------------------------------------------------------------------- /setup-cuda-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if Python 3.9 is installed 4 | python_bin='python3.9' 5 | min_python_version='"3.9.0"' 6 | 7 | $python_bin -m pip install --upgrade packaging 8 | $python_bin -c "import platform; from packaging.version import Version; exit(Version(platform.python_version()) < Version(${min_python_version}))" 9 | if [[ $? = 1 ]]; then 10 | echo "Python >= ${min_python_version} is not installed. Please install it and try again." 11 | exit 1 12 | fi 13 | 14 | # Initialize and update git submodules 15 | git submodule init 16 | git submodule update --remote 17 | 18 | # Set up virtual environment with Python 3.9 19 | $python_bin -m venv venv 20 | source ./venv/bin/activate 21 | 22 | # Upgrade pip and install required packages 23 | pip install --upgrade pip 24 | pip install torch torchvision torchaudio 25 | pip install -r ./modules/tortoise-tts/requirements.txt 26 | pip install -e ./modules/tortoise-tts/ 27 | pip install -r ./modules/dlas/requirements.txt 28 | pip install -e ./modules/dlas/ 29 | 30 | # Download and extract RVC if not already done 31 | file_name='rvc.zip' 32 | download_rvc='https://huggingface.co/Jmica/rvc/resolve/main/rvc_lightweight.zip?download=true' 33 | extracted_folder='rvc' 34 | 35 | if [ -d $extracted_folder ]; then 36 | echo "The folder ${extracted_folder} already exists." 37 | read -p "Do you want to delete it and re-extract? [y/N] " choice 38 | if [[ $choice == [Yy]* ]]; then 39 | echo "Deleting ${extracted_folder}..." 40 | rm -rf $extracted_folder 41 | fi 42 | fi 43 | 44 | if ! [ -f $file_name ]; then 45 | echo "Downloading ${file_name}..." 46 | curl -L $download_rvc -o $file_name 47 | else 48 | echo "File ${file_name} already exists, skipping download." 49 | fi 50 | 51 | echo "Extracting ${file_name}..." 52 | $python_bin -m zipfile -e $file_name ./ 53 | echo "RVC has finished downloading and Extracting." 54 | 55 | # Install RVC requirements 56 | pip install -r ./rvc/requirements.txt 57 | 58 | # Prepare fairseq 59 | fairseq_repo='https://github.com/pytorch/fairseq' 60 | fairseq_folder='fairseq' 61 | 62 | if [ -d $fairseq_folder ]; then 63 | git -C $fairseq_folder pull 64 | else 65 | git clone $fairseq_repo 66 | fi 67 | 68 | if [ -d $fairseq_folder/wheels ]; then 69 | rm -rf $fairseq_folder/wheels 70 | fi 71 | 72 | # Install Fairseq and RVC TTS Pipeline 73 | pip wheel ./$fairseq_folder/ -w ./$fairseq_folder/wheels/ 74 | pip install ./$fairseq_folder/wheels/fairseq-*.whl 75 | pip install git+https://github.com/JarodMica/rvc-tts-pipeline.git@lightweight#egg=rvc_tts_pipe 76 | 77 | # Install other requirements (this is done last due to potential package conflicts) 78 | pip install -r requirements.txt 79 | 80 | # Clean up 81 | rm -f *.bat 82 | 83 | deactivate 84 | -------------------------------------------------------------------------------- /setup-cuda.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | :: Check if Python 3.11 is installed 5 | py -3.11 --version >nul 2>&1 6 | if errorlevel 1 ( 7 | echo Python 3.11 is not installed. Please install it and try again. 8 | pause 9 | exit /b 1 10 | ) 11 | 12 | :: Initialize and update git submodules 13 | git submodule init 14 | git submodule update 15 | 16 | :: Set up virtual environment with Python 3.11 17 | py -3.11 -m venv venv 18 | call .\venv\Scripts\activate.bat 19 | 20 | :: Upgrade pip and install required packages 21 | python -m pip install --upgrade pip 22 | python -m pip install -r .\modules\tortoise-tts\requirements.txt 23 | python -m pip install -e .\modules\tortoise-tts\ 24 | python -m pip install -r .\modules\dlas\requirements.txt 25 | python -m pip install -e .\modules\dlas\ 26 | 27 | :: Download and extract RVC if not already done 28 | set file_name=rvc.zip 29 | set download_rvc=https://huggingface.co/Jmica/rvc/resolve/main/rvc_lightweight.zip?download=true 30 | set extracted_folder=rvc 31 | 32 | :: Delete previous rvc.zip if it exists 33 | if exist "%file_name%" ( 34 | echo Deleting previous %file_name%... 35 | del "%file_name%" 36 | ) 37 | 38 | if exist "%extracted_folder%" ( 39 | echo The folder %extracted_folder% already exists. 40 | choice /C YN /M "Do you want to delete it and re-extract (Y/N)?" 41 | if errorlevel 2 goto SkipDeletion 42 | if errorlevel 1 ( 43 | echo Deleting %extracted_folder%... 44 | rmdir /S /Q "%extracted_folder%" 45 | ) 46 | ) 47 | 48 | :SkipDeletion 49 | if not exist "%file_name%" ( 50 | echo Downloading %file_name%... 51 | curl -L %download_rvc% -o %file_name% 52 | ) else ( 53 | echo File %file_name% already exists, skipping download. 54 | ) 55 | 56 | echo Extracting %file_name%... 57 | tar -xf %file_name% 58 | echo RVC has finished downloading and Extracting. 59 | 60 | :: Install RVC requirements 61 | python -m pip install -r .\rvc\requirements.txt 62 | 63 | :: Download and install Fairseq if not already done 64 | set download_fairseq=https://huggingface.co/Jmica/rvc/resolve/main/fairseq-0.12.4-cp311-cp311-win_amd64.whl?download=true 65 | set file_name=fairseq-0.12.4-cp311-cp311-win_amd64.whl 66 | 67 | if not exist "%file_name%" ( 68 | echo Downloading %file_name%... 69 | curl -L -O "%download_fairseq%" 70 | if errorlevel 1 ( 71 | echo Download failed. Please check your internet connection or the URL and try again. 72 | exit /b 1 73 | ) 74 | ) else ( 75 | echo File %file_name% already exists, skipping download. 76 | ) 77 | 78 | set download_deepspeed=https://huggingface.co/Jmica/rvc/resolve/main/deepspeed-0.14.0-cp311-cp311-win_amd64.whl?download=true 79 | set fileds_name=deepspeed-0.14.0-cp311-cp311-win_amd64.whl 80 | 81 | if not exist "%fileds_name%" ( 82 | echo Downloading %fileds_name%... 83 | curl -L -O "%download_deepspeed%" 84 | if errorlevel 1 ( 85 | echo Download failed. Please check your internet connection or the URL and try again. 86 | exit /b 1 87 | ) 88 | ) else ( 89 | echo File %fileds_name% already exists, skipping download. 90 | ) 91 | 92 | set download_pyfastmp3decoder=https://huggingface.co/Jmica/rvc/resolve/main/pyfastmp3decoder-0.0.1-cp311-cp311-win_amd64.whl?download=true 93 | set filepyfast_name=pyfastmp3decoder-0.0.1-cp311-cp311-win_amd64.whl 94 | 95 | if not exist "%filepyfast_name%" ( 96 | echo Downloading %filepyfast_name%... 97 | curl -L -O "%download_pyfastmp3decoder%" 98 | if errorlevel 1 ( 99 | echo Download failed. Please check your internet connection or the URL and try again. 100 | exit /b 1 101 | ) 102 | ) else ( 103 | echo File %filepyfast_name% already exists, skipping download. 104 | ) 105 | 106 | :: Install Fairseq, Deepspeed, pyfast, and RVC TTS Pipeline 107 | python -m pip install .\fairseq-0.12.4-cp311-cp311-win_amd64.whl 108 | python -m pip install git+https://github.com/JarodMica/rvc-tts-pipeline.git@lightweight#egg=rvc_tts_pipe 109 | python -m pip install deepspeed-0.14.0-cp311-cp311-win_amd64.whl 110 | python -m pip install pyfastmp3decoder-0.0.1-cp311-cp311-win_amd64.whl 111 | 112 | :: Install whisperx 113 | python -m pip install git+https://github.com/m-bain/whisperx.git 114 | 115 | :: Install other requirements (this is done last due to potential package conflicts) 116 | python -m pip install -r requirements.txt 117 | python -m pip uninstall torch 118 | python -m pip install torch==2.2.2 torchvision==0.17.2 torchaudio==2.2.2 --index-url https://download.pytorch.org/whl/cu121 119 | 120 | 121 | :: Download and install ffmpeg 122 | call download_ffmpeg.bat 123 | 124 | :: Setup BnB 125 | call setup-cuda-bnb.bat 126 | 127 | .\start.bat 128 | :: Clean up 129 | del *.sh 130 | 131 | pause 132 | deactivate 133 | -------------------------------------------------------------------------------- /setup-cuda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if Python 3.11 is installed 4 | python_bin='python3.11' 5 | 6 | if ! command -v $python_bin &> /dev/null; then 7 | echo "Python 3.11 is not installed. Please install it using the following command:" 8 | echo "sudo apt install -y python3.11" 9 | echo "After installing Python 3.11, please run the script again." 10 | exit 1 11 | fi 12 | 13 | # Check if python3.11-venv is installed 14 | if ! $python_bin -m venv --help &> /dev/null; then 15 | echo "The python3.11-venv package is not installed. Please install it using the following command:" 16 | echo "sudo apt install -y python3.11-venv" 17 | echo "After installing the python3.11-venv package, please run the script again." 18 | exit 1 19 | fi 20 | 21 | # Set up virtual environment with Python 3.11 22 | $python_bin -m venv venv 23 | if [ $? -ne 0 ]; then 24 | echo "Failed to create virtual environment. Please check the error message above and try again." 25 | exit 1 26 | fi 27 | 28 | # Initialize and update git submodules 29 | git submodule init 30 | git submodule update --remote 31 | 32 | # Upgrade pip and install required packages 33 | pip install --upgrade pip 34 | pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 35 | pip install -r ./modules/tortoise-tts/requirements.txt 36 | pip install -e ./modules/tortoise-tts/ 37 | pip install -r ./modules/dlas/requirements.txt 38 | pip install -e ./modules/dlas/ 39 | 40 | # Download and extract RVC if not already done 41 | file_name='rvc.zip' 42 | download_rvc='https://huggingface.co/Jmica/rvc/resolve/main/rvc_lightweight.zip?download=true' 43 | extracted_folder='rvc' 44 | 45 | # Delete previous rvc.zip if it exists 46 | if [ -f $file_name ]; then 47 | echo "Deleting previous ${file_name}..." 48 | rm -f $file_name 49 | fi 50 | 51 | if [ -d $extracted_folder ]; then 52 | echo "The folder ${extracted_folder} already exists." 53 | read -p "Do you want to delete it and re-extract? [y/N] " choice 54 | if [[ $choice == [Yy]* ]]; then 55 | echo "Deleting ${extracted_folder}..." 56 | rm -rf $extracted_folder 57 | fi 58 | fi 59 | 60 | if ! [ -f $file_name ]; then 61 | echo "Downloading ${file_name}..." 62 | curl -L $download_rvc -o $file_name 63 | else 64 | echo "File ${file_name} already exists, skipping download." 65 | fi 66 | 67 | echo "Extracting ${file_name}..." 68 | $python_bin -m zipfile -e $file_name ./ 69 | echo "RVC has finished downloading and Extracting." 70 | 71 | # Install RVC requirements 72 | pip install -r ./rvc/requirements.txt 73 | 74 | # Prepare fairseq 75 | fairseq_repo='https://github.com/VarunGumma/fairseq' 76 | fairseq_folder='fairseq' 77 | 78 | if [ -d $fairseq_folder ]; then 79 | git -C $fairseq_folder pull 80 | else 81 | git clone $fairseq_repo 82 | fi 83 | 84 | if [ -d $fairseq_folder/wheels ]; then 85 | rm -rf $fairseq_folder/wheels 86 | fi 87 | 88 | # Prepare pyfastmp3decoder 89 | pyfastmp3decoder_repo='https://github.com/neonbjb/pyfastmp3decoder.git' 90 | pyfastmp3decoder_folder='pyfastmp3decoder' 91 | 92 | if [ -d $pyfastmp3decoder_folder ]; then 93 | git -C $pyfastmp3decoder_folder pull 94 | else 95 | git clone --recurse-submodules $pyfastmp3decoder_repo 96 | fi 97 | 98 | if [ -d $pyfastmp3decoder_folder/wheels ]; then 99 | rm -rf $pyfastmp3decoder_folder/wheels 100 | fi 101 | 102 | # Install Fairseq, Deepspeed, pyfast, and RVC TTS Pipeline 103 | pip wheel ./$fairseq_folder/ -w ./$fairseq_folder/wheels/ 104 | pip install ./$fairseq_folder/wheels/fairseq-*.whl 105 | pip install git+https://github.com/JarodMica/rvc-tts-pipeline.git@lightweight#egg=rvc_tts_pipe 106 | pip install deepspeed 107 | pip wheel ./$pyfastmp3decoder_folder/ -w ./$pyfastmp3decoder_folder/wheels/ 108 | pip install ./$pyfastmp3decoder_folder/wheels/pyfastmp3decoder-*.whl 109 | 110 | # Install whisperx 111 | pip install git+https://github.com/m-bain/whisperx.git 112 | 113 | # Install other requirements (this is done last due to potential package conflicts) 114 | pip install -r requirements.txt 115 | 116 | chmod +x ./start.sh 117 | ./start.sh 118 | # Clean up 119 | rm -f *.bat 120 | 121 | deactivate 122 | -------------------------------------------------------------------------------- /setup-directml.bat: -------------------------------------------------------------------------------- 1 | git submodule init 2 | git submodule update --remote 3 | 4 | python -m venv venv 5 | call .\venv\Scripts\activate.bat 6 | python -m pip install --upgrade pip 7 | python -m pip install torch torchvision torchaudio torch-directml 8 | python -m pip install -r .\modules\tortoise-tts\requirements.txt 9 | python -m pip install -e .\modules\tortoise-tts\ 10 | python -m pip install -r .\modules\dlas\requirements.txt 11 | python -m pip install -e .\modules\dlas\ 12 | python -m pip install -r .\requirements.txt 13 | 14 | del *.sh 15 | 16 | pause 17 | deactivate -------------------------------------------------------------------------------- /setup-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function main() { 4 | if [ ! -f modules/tortoise-tts/README.md ]; then 5 | git submodule init 6 | git submodule update 7 | fi 8 | docker build \ 9 | --build-arg UID=$(id -u) \ 10 | --build-arg GID=$(id -g) \ 11 | -t ai-voice-cloning \ 12 | . 13 | } 14 | 15 | main 16 | -------------------------------------------------------------------------------- /setup-rocm-bnb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ./venv/bin/activate 3 | # swap to ROCm version of BitsAndBytes 4 | pip3 uninstall -y bitsandbytes 5 | 6 | git clone https://git.ecker.tech/mrq/bitsandbytes-rocm modules/bitsandbytes-rocm 7 | cd modules/bitsandbytes-rocm 8 | make hip 9 | CUDA_VERSION=gfx1030 python setup.py install # assumes you're using a 6XXX series card 10 | python3 -m bitsandbytes # to validate it works 11 | cd ../.. -------------------------------------------------------------------------------- /setup-rocm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # get local dependencies 3 | git submodule init 4 | git submodule update --remote 5 | # setup venv 6 | python3 -m venv venv 7 | source ./venv/bin/activate 8 | python3 -m pip install --upgrade pip # just to be safe 9 | # ROCM 10 | pip3 install torch==1.13.1 torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm5.2 # 5.4.2 doesn't work for me desu 11 | # install requirements 12 | python3 -m pip install -r ./modules/tortoise-tts/requirements.txt # install TorToiSe requirements 13 | python3 -m pip install -e ./modules/tortoise-tts/ # install TorToiSe 14 | python3 -m pip install -r ./modules/dlas/requirements.txt # instal DLAS requirements 15 | python3 -m pip install -e ./modules/dlas/ # install DLAS 16 | python3 -m pip install -r ./requirements.txt # install local requirements 17 | 18 | rm *.bat 19 | 20 | ./setup-rocm-bnb.sh 21 | 22 | deactivate -------------------------------------------------------------------------------- /setup-whisperx.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | call .\venv\Scripts\activate.bat 3 | 4 | :: Install whisperx 5 | python -m pip install git+https://github.com/m-bain/whisperx.git 6 | 7 | 8 | :: Fix incompatibilites caused from packages in whisperx 9 | python -m pip install -r requirements.txt 10 | 11 | echo Installation finished 12 | pause -------------------------------------------------------------------------------- /src/api/websocket_server.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | from threading import Thread 4 | 5 | from websockets.server import serve 6 | 7 | from utils import generate, get_autoregressive_models, get_voice_list, args, update_autoregressive_model, update_diffusion_model, update_tokenizer 8 | 9 | # this is a not so nice workaround to set values to None if their string value is "None" 10 | def replaceNoneStringWithNone(message): 11 | ignore_fields = ['text'] # list of fields which CAN have "None" as literal String value 12 | 13 | for member in message: 14 | if message[member] == 'None' and member not in ignore_fields: 15 | message[member] = None 16 | 17 | return message 18 | 19 | 20 | async def _handle_generate(websocket, message): 21 | # update args parameters which control the model settings 22 | if message.get('autoregressive_model'): 23 | update_autoregressive_model(message['autoregressive_model']) 24 | 25 | if message.get('diffusion_model'): 26 | update_diffusion_model(message['diffusion_model']) 27 | 28 | if message.get('tokenizer_json'): 29 | update_tokenizer(message['tokenizer_json']) 30 | 31 | if message.get('sample_batch_size'): 32 | global args 33 | args.sample_batch_size = message['sample_batch_size'] 34 | 35 | message['result'] = generate(**message) 36 | await websocket.send(json.dumps(replaceNoneStringWithNone(message))) 37 | 38 | 39 | async def _handle_get_autoregressive_models(websocket, message): 40 | message['result'] = get_autoregressive_models() 41 | await websocket.send(json.dumps(replaceNoneStringWithNone(message))) 42 | 43 | 44 | async def _handle_get_voice_list(websocket, message): 45 | message['result'] = get_voice_list() 46 | await websocket.send(json.dumps(replaceNoneStringWithNone(message))) 47 | 48 | 49 | async def _handle_message(websocket, message): 50 | message = replaceNoneStringWithNone(message) 51 | 52 | if message.get('action') and message['action'] == 'generate': 53 | await _handle_generate(websocket, message) 54 | elif message.get('action') and message['action'] == 'get_voices': 55 | await _handle_get_voice_list(websocket, message) 56 | elif message.get('action') and message['action'] == 'get_autoregressive_models': 57 | await _handle_get_autoregressive_models(websocket, message) 58 | else: 59 | print("websocket: undhandled message: " + message) 60 | 61 | 62 | async def _handle_connection(websocket, path): 63 | print("websocket: client connected") 64 | 65 | async for message in websocket: 66 | try: 67 | await _handle_message(websocket, json.loads(message)) 68 | except ValueError: 69 | print("websocket: malformed json received") 70 | 71 | 72 | async def _run(host: str, port: int): 73 | print(f"websocket: server started on ws://{host}:{port}") 74 | 75 | async with serve(_handle_connection, host, port, ping_interval=None): 76 | await asyncio.Future() # run forever 77 | 78 | 79 | def _run_server(listen_address: str, port: int): 80 | asyncio.run(_run(host=listen_address, port=port)) 81 | 82 | 83 | def start_websocket_server(listen_address: str, port: int): 84 | Thread(target=_run_server, args=[listen_address, port], daemon=True).start() 85 | -------------------------------------------------------------------------------- /src/cli.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | if 'TORTOISE_MODELS_DIR' not in os.environ: 5 | os.environ['TORTOISE_MODELS_DIR'] = os.path.realpath(os.path.join(os.getcwd(), './models/tortoise/')) 6 | 7 | if 'TRANSFORMERS_CACHE' not in os.environ: 8 | os.environ['TRANSFORMERS_CACHE'] = os.path.realpath(os.path.join(os.getcwd(), './models/transformers/')) 9 | 10 | os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' 11 | 12 | from utils import * 13 | 14 | if __name__ == "__main__": 15 | args = setup_args(cli=True) 16 | 17 | default_arguments = import_generate_settings() 18 | parser = argparse.ArgumentParser(allow_abbrev=False) 19 | parser.add_argument("--text", default=default_arguments['text']) 20 | parser.add_argument("--delimiter", default=default_arguments['delimiter']) 21 | parser.add_argument("--emotion", default=default_arguments['emotion']) 22 | parser.add_argument("--prompt", default=default_arguments['prompt']) 23 | parser.add_argument("--voice", default=default_arguments['voice']) 24 | parser.add_argument("--mic_audio", default=default_arguments['mic_audio']) 25 | parser.add_argument("--voice_latents_chunks", default=default_arguments['voice_latents_chunks']) 26 | parser.add_argument("--candidates", default=default_arguments['candidates']) 27 | parser.add_argument("--seed", default=default_arguments['seed']) 28 | parser.add_argument("--num_autoregressive_samples", default=default_arguments['num_autoregressive_samples']) 29 | parser.add_argument("--diffusion_iterations", default=default_arguments['diffusion_iterations']) 30 | parser.add_argument("--temperature", default=default_arguments['temperature']) 31 | parser.add_argument("--diffusion_sampler", default=default_arguments['diffusion_sampler']) 32 | parser.add_argument("--breathing_room", default=default_arguments['breathing_room']) 33 | parser.add_argument("--cvvp_weight", default=default_arguments['cvvp_weight']) 34 | parser.add_argument("--top_p", default=default_arguments['top_p']) 35 | parser.add_argument("--diffusion_temperature", default=default_arguments['diffusion_temperature']) 36 | parser.add_argument("--length_penalty", default=default_arguments['length_penalty']) 37 | parser.add_argument("--repetition_penalty", default=default_arguments['repetition_penalty']) 38 | parser.add_argument("--cond_free_k", default=default_arguments['cond_free_k']) 39 | 40 | args, unknown = parser.parse_known_args() 41 | kwargs = { 42 | 'text': args.text, 43 | 'delimiter': args.delimiter, 44 | 'emotion': args.emotion, 45 | 'prompt': args.prompt, 46 | 'voice': args.voice, 47 | 'mic_audio': args.mic_audio, 48 | 'voice_latents_chunks': args.voice_latents_chunks, 49 | 'candidates': args.candidates, 50 | 'seed': args.seed, 51 | 'num_autoregressive_samples': args.num_autoregressive_samples, 52 | 'diffusion_iterations': args.diffusion_iterations, 53 | 'temperature': args.temperature, 54 | 'diffusion_sampler': args.diffusion_sampler, 55 | 'breathing_room': args.breathing_room, 56 | 'cvvp_weight': args.cvvp_weight, 57 | 'top_p': args.top_p, 58 | 'diffusion_temperature': args.diffusion_temperature, 59 | 'length_penalty': args.length_penalty, 60 | 'repetition_penalty': args.repetition_penalty, 61 | 'cond_free_k': args.cond_free_k, 62 | 'experimentals': default_arguments['experimentals'], 63 | } 64 | 65 | tts = load_tts() 66 | generate(**kwargs) -------------------------------------------------------------------------------- /src/list_devices.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | devices = [f"cuda:{i} => {torch.cuda.get_device_name(i)}" for i in range(torch.cuda.device_count())] 4 | 5 | print(devices) -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | # Moved all of the imports into __name__ == "__main__" due to how multiprocessing spawns instances, makes multiprocessing faster as it reduces import overhead 2 | 3 | if __name__ == "__main__": 4 | import os 5 | import sys 6 | 7 | if os.path.exists("runtime"): 8 | # Get the directory where the script is located 9 | script_dir = os.path.dirname(os.path.abspath(__file__)) 10 | 11 | # Add this directory to sys.path 12 | if script_dir not in sys.path: 13 | sys.path.insert(0, script_dir) 14 | 15 | if 'TORTOISE_MODELS_DIR' not in os.environ: 16 | os.environ['TORTOISE_MODELS_DIR'] = os.path.realpath(os.path.join(os.getcwd(), './models/tortoise/')) 17 | 18 | if 'TRANSFORMERS_CACHE' not in os.environ: 19 | os.environ['TRANSFORMERS_CACHE'] = os.path.realpath(os.path.join(os.getcwd(), './models/transformers/')) 20 | 21 | os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' 22 | 23 | from utils import * 24 | from webui import * 25 | 26 | from api.websocket_server import start_websocket_server 27 | args = setup_args() 28 | 29 | if args.listen_path is not None and args.listen_path != "/": 30 | import uvicorn 31 | uvicorn.run("main:app", host=args.listen_host, port=args.listen_port if not None else 8000) 32 | else: 33 | webui = setup_gradio() 34 | webui.launch(share=args.share, prevent_thread_lock=True, show_error=True, server_name=args.listen_host, server_port=args.listen_port) 35 | if not args.defer_tts_load: 36 | tts = load_tts() 37 | 38 | if args.websocket_enabled: 39 | start_websocket_server(args.websocket_listen_address, args.websocket_listen_port) 40 | 41 | webui.block_thread() 42 | elif __name__ == "main": 43 | from fastapi import FastAPI 44 | import gradio as gr 45 | 46 | import sys 47 | sys.argv = [sys.argv[0]] 48 | 49 | app = FastAPI() 50 | args = setup_args() 51 | webui = setup_gradio() 52 | app = gr.mount_gradio_app(app, webui, path=args.listen_path) 53 | 54 | if not args.defer_tts_load: 55 | tts = load_tts() 56 | 57 | -------------------------------------------------------------------------------- /src/train.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import yaml 5 | import datetime 6 | 7 | if os.path.exists("runtime"): 8 | # Get the directory where the script is located 9 | script_dir = os.path.dirname(os.path.abspath(__file__)) 10 | 11 | # Add this directory to sys.path 12 | if script_dir not in sys.path: 13 | sys.path.insert(0, script_dir) 14 | 15 | from torch.distributed.run import main as torchrun 16 | 17 | # this is effectively just copy pasted and cleaned up from the __main__ section of training.py 18 | def train(config_path, launcher='none'): 19 | opt = option.parse(config_path, is_train=True) 20 | 21 | if launcher == 'none' and opt['gpus'] > 1: 22 | return torchrun([f"--nproc_per_node={opt['gpus']}", "./src/train.py", "--yaml", config_path, "--launcher=pytorch"]) 23 | 24 | trainer = tr.Trainer() 25 | if launcher == 'none': 26 | opt['dist'] = False 27 | trainer.rank = -1 28 | if len(opt['gpu_ids']) == 1: 29 | torch.cuda.set_device(opt['gpu_ids'][0]) 30 | print('Disabled distributed training.') 31 | else: 32 | opt['dist'] = True 33 | tr.init_dist('nccl', timeout=datetime.timedelta(seconds=5*60)) 34 | trainer.world_size = torch.distributed.get_world_size() 35 | trainer.rank = torch.distributed.get_rank() 36 | torch.cuda.set_device(torch.distributed.get_rank()) 37 | 38 | trainer.init(config_path, opt, launcher, '') 39 | trainer.do_training() 40 | 41 | if __name__ == "__main__": 42 | parser = argparse.ArgumentParser() 43 | parser.add_argument('--yaml', type=str, help='Path to training configuration file.', default='./training/voice/train.yml', nargs='+') # ugh 44 | parser.add_argument('--launcher', choices=['none', 'pytorch'], default='none', help='Job launcher') 45 | args = parser.parse_args() 46 | args.yaml = " ".join(args.yaml) # absolutely disgusting 47 | config_path = args.yaml 48 | 49 | with open(config_path, 'r') as file: 50 | opt_config = yaml.safe_load(file) 51 | 52 | # yucky override 53 | if "bitsandbytes" in opt_config and not opt_config["bitsandbytes"]: 54 | os.environ['BITSANDBYTES_OVERRIDE_LINEAR'] = '0' 55 | os.environ['BITSANDBYTES_OVERRIDE_EMBEDDING'] = '0' 56 | os.environ['BITSANDBYTES_OVERRIDE_ADAM'] = '0' 57 | os.environ['BITSANDBYTES_OVERRIDE_ADAMW'] = '0' 58 | 59 | try: 60 | import torch_intermediary 61 | if torch_intermediary.OVERRIDE_ADAM: 62 | print("Using BitsAndBytes optimizations") 63 | else: 64 | print("NOT using BitsAndBytes optimizations") 65 | except Exception as e: 66 | pass 67 | 68 | import torch 69 | from dlas import train as tr 70 | from dlas.utils import util, options as option 71 | 72 | train(config_path, args.launcher) -------------------------------------------------------------------------------- /src/train_jard.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import yaml 5 | import datetime 6 | 7 | ''' 8 | Note: 9 | This is a specific file for testing, nothing more than that for Jarod. 10 | ''' 11 | 12 | if os.path.exists("runtime"): 13 | # Get the directory where the script is located 14 | script_dir = os.path.dirname(os.path.abspath(__file__)) 15 | 16 | # Add this directory to sys.path 17 | if script_dir not in sys.path: 18 | sys.path.insert(0, script_dir) 19 | 20 | from torch.distributed.run import main as torchrun 21 | 22 | # this is effectively just copy pasted and cleaned up from the __main__ section of training.py 23 | def train(config_path, launcher='none'): 24 | opt = option.parse(config_path, is_train=True) 25 | 26 | if launcher == 'none' and opt['gpus'] > 1: 27 | return torchrun([f"--nproc_per_node={opt['gpus']}", "./src/train.py", "--yaml", config_path, "--launcher=pytorch"]) 28 | 29 | trainer = tr.Trainer() 30 | if launcher == 'none': 31 | opt['dist'] = False 32 | trainer.rank = -1 33 | if len(opt['gpu_ids']) == 1: 34 | torch.cuda.set_device(opt['gpu_ids'][0]) 35 | print('Disabled distributed training.') 36 | else: 37 | opt['dist'] = True 38 | tr.init_dist('nccl', timeout=datetime.timedelta(seconds=5*60)) 39 | trainer.world_size = torch.distributed.get_world_size() 40 | trainer.rank = torch.distributed.get_rank() 41 | torch.cuda.set_device(torch.distributed.get_rank()) 42 | 43 | trainer.init(config_path, opt, launcher, '') 44 | trainer.do_training() 45 | 46 | if __name__ == "__main__": 47 | parser = argparse.ArgumentParser() 48 | parser.add_argument('--yaml', type=str, help='Path to training configuration file.', default='./training/voice/train.yml', nargs='+') # ugh 49 | 50 | parser.add_argument('--launcher', choices=['none', 'pytorch'], default='none', help='Job launcher') 51 | args = parser.parse_args() 52 | args.yaml = " ".join(args.yaml) # absolutely disgusting 53 | config_path = args.yaml 54 | # config_path = "./training/vietnamese/train.yaml" 55 | 56 | with open(config_path, 'r') as file: 57 | opt_config = yaml.safe_load(file) 58 | 59 | # yucky override 60 | if "bitsandbytes" in opt_config and not opt_config["bitsandbytes"]: 61 | os.environ['BITSANDBYTES_OVERRIDE_LINEAR'] = '0' 62 | os.environ['BITSANDBYTES_OVERRIDE_EMBEDDING'] = '0' 63 | os.environ['BITSANDBYTES_OVERRIDE_ADAM'] = '0' 64 | os.environ['BITSANDBYTES_OVERRIDE_ADAMW'] = '0' 65 | 66 | try: 67 | import torch_intermediary 68 | if torch_intermediary.OVERRIDE_ADAM: 69 | print("Using BitsAndBytes optimizations") 70 | else: 71 | print("NOT using BitsAndBytes optimizations") 72 | except Exception as e: 73 | pass 74 | 75 | import torch 76 | from dlas import train as tr 77 | from dlas.utils import util, options as option 78 | 79 | train(config_path, args.launcher) -------------------------------------------------------------------------------- /start-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run \ 4 | -ti \ 5 | --rm \ 6 | --gpus all \ 7 | --name ai-voice-cloning \ 8 | -v "${PWD}/models:/home/user/ai-voice-cloning/models" \ 9 | -v "${PWD}/training:/home/user/ai-voice-cloning/training" \ 10 | -v "${PWD}/voices:/home/user/ai-voice-cloning/voices" \ 11 | -v "${PWD}/bin:/home/user/ai-voice-cloning/bin" \ 12 | -v "${PWD}/config:/home/user/ai-voice-cloning/config" \ 13 | --user "$(id -u):$(id -g)" \ 14 | -p "7860:7860" \ 15 | ai-voice-cloning $@ 16 | 17 | # For dev: 18 | # -v "${PWD}/src:/home/user/ai-voice-cloning/src" \ 19 | # -v "${PWD}/modules/tortoise_dataset_tools/dataset_whisper_tools:/home/user/ai-voice-cloning/modules/tortoise_dataset_tools/dataset_whisper_tools" \ 20 | # -v "${PWD}/modules/dlas/dlas:/home/user/ai-voice-cloning/modules/dlas/dlas" \ 21 | # -v "/home/user/ai-voice-cloning/src/__pycache__" \ 22 | 23 | # For testing: 24 | # -e "PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True" \ 25 | -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | call .\venv\Scripts\activate.bat 2 | set PATH=.\bin\;%PATH% 3 | set PYTHONUTF8=1 4 | python .\src\main.py %* 5 | pause -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ulimit -Sn `ulimit -Hn` # ROCm is a bitch 3 | while [ true ]; do 4 | python3 ./src/main.py "$@" 5 | echo "Press Cntrl-C to quit or application will restart... (5s)" 6 | sleep 5 7 | done 8 | -------------------------------------------------------------------------------- /train-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CMD="python3 ./src/train.py --yaml $1" 3 | # ipc host is one way to increase the shared memory for the container 4 | # more info here https://github.com/pytorch/pytorch#docker-image 5 | CPATH="/home/user/ai-voice-cloning" 6 | docker run --rm --gpus all \ 7 | --mount "type=bind,src=$PWD/models,dst=$CPATH/models" \ 8 | --mount "type=bind,src=$PWD/training,dst=$CPATH/training" \ 9 | --mount "type=bind,src=$PWD/voices,dst=$CPATH/voices" \ 10 | --mount "type=bind,src=$PWD/bin,dst=$CPATH/bin" \ 11 | --mount "type=bind,src=$PWD/src,dst=$CPATH/src" \ 12 | --workdir $CPATH \ 13 | --ipc host \ 14 | --user "$(id -u):$(id -g)" \ 15 | -it ai-voice-cloning $CMD 16 | -------------------------------------------------------------------------------- /train.bat: -------------------------------------------------------------------------------- 1 | call .\venv\Scripts\activate.bat 2 | set PYTHONUTF8=1 3 | python ./src/train.py --yaml "%1" 4 | pause 5 | deactivate -------------------------------------------------------------------------------- /train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ./venv/bin/activate 3 | python3 ./src/train.py --yaml "$1" 4 | deactivate 5 | -------------------------------------------------------------------------------- /training/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /update-force.bat: -------------------------------------------------------------------------------- 1 | git fetch --all 2 | git reset --hard origin/master 3 | call .\update.bat 4 | 5 | python -m venv venv 6 | call .\venv\Scripts\activate.bat 7 | 8 | python -m pip install --upgrade pip 9 | python -m pip install -U -r .\modules\tortoise-tts\requirements.txt 10 | python -m pip install -U -e .\modules\tortoise-tts 11 | python -m pip install -U -r .\modules\dlas\requirements.txt 12 | python -m pip install -U -r .\requirements.txt 13 | 14 | pause 15 | deactivate -------------------------------------------------------------------------------- /update-force.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git fetch --all 3 | git reset --hard origin/master 4 | 5 | ./update.sh 6 | 7 | # force install requirements 8 | python3 -m venv venv 9 | source ./venv/bin/activate 10 | 11 | python3 -m pip install --upgrade pip 12 | python3 -m pip install -r ./modules/tortoise-tts/requirements.txt 13 | python3 -m pip install -e ./modules/tortoise-tts 14 | python3 -m pip install -r ./modules/dlas/requirements.txt 15 | python3 -m pip install -e ./modules/dlas 16 | python3 -m pip install -r ./requirements.txt 17 | 18 | deactivate -------------------------------------------------------------------------------- /update.bat: -------------------------------------------------------------------------------- 1 | git pull 2 | git submodule update --remote -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git pull 3 | git submodule update --remote 4 | 5 | source ./venv/bin/activate 6 | if python -m pip show whispercpp &>/dev/null; then python -m pip install -U git+https://git.ecker.tech/lightmare/whispercpp.py; fi 7 | deactivate -------------------------------------------------------------------------------- /update_package.bat: -------------------------------------------------------------------------------- 1 | portable_git\bin\git.exe clone https://github.com/JarodMica/ai-voice-cloning.git 2 | cd ai-voice-cloning 3 | git submodule init 4 | git submodule update --remote 5 | cd .. 6 | 7 | xcopy ai-voice-cloning\update_package.bat /E /I /H /Y 8 | 9 | xcopy ai-voice-cloning\src src /E /I /H /Y 10 | xcopy ai-voice-cloning\modules\dlas modules\dlas /E /I /H /Y 11 | xcopy ai-voice-cloning\modules\tortoise-tts modules\tortoise-tts /E /I /H /Y 12 | 13 | @echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | @echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | @echo Finished updating! 16 | @echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | @echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | 19 | pause -------------------------------------------------------------------------------- /voices/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.random/ -------------------------------------------------------------------------------- /voices/random/cond_latents_d1f79232.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarodMica/ai-voice-cloning/61e46bcbc2676e21623724e66269f48d015b2ccb/voices/random/cond_latents_d1f79232.pth -------------------------------------------------------------------------------- /voices/random/cond_latents_f540259e.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarodMica/ai-voice-cloning/61e46bcbc2676e21623724e66269f48d015b2ccb/voices/random/cond_latents_f540259e.pth --------------------------------------------------------------------------------