本帮助文档为项目 so-vits-svc 的详细中文安装、调试、推理教程,您也可以直接选择官方README文档
撰写:Sucial 点击跳转B站主页
任何组织或者个人不得以丑化、污损,或者利用信息技术手段伪造等方式侵害他人的肖像权。未经肖像权人同意,不得制作、使用、公开肖像权人的肖像,但是法律另有规定的除外。未经肖像权人同意,肖像作品权利人不得以发表、复制、发行、出租、展览等方式使用或者公开肖像权人的肖像。对自然人声音的保护,参照适用肖像权保护的有关规定。
对自然人声音的保护,参照适用肖像权保护的有关规定
【名誉权】民事主体享有名誉权。任何组织或者个人不得以侮辱、诽谤等方式侵害他人的名誉权。
【作品侵害名誉权】行为人发表的文学、艺术作品以真人真事或者特定人为描述对象,含有侮辱、诽谤内容,侵害他人名誉权的,受害人有权依法请求该行为人承担民事责任。行为人发表的文学、艺术作品不以特定人为描述对象,仅其中的情节与该特定人的情况相似的,不承担民事责任。
本教程内容仅代表个人,均不代表so-vits-svc团队及原作者观点
本教程涉及到的开源代码请自行遵守其开源协议
本教程默认使用由so-vits-svc团队维护的仓库
若制作视频发布,推荐注明使用项目的Github链接,tag推荐使用so-vits-svc以便和其他基于技术进行区分
云端训练和推理部分可能涉及资金使用,如果你是未成年人,请在获得监护人的许可与理解后进行,未经许可引起的后续问题,本教程概不负责
本地训练(尤其是在硬件较差的情况下)可能需要设备长时间高负荷运行,请做好设备养护和散热措施
请确保你制作数据集的数据来源合法合规,且数据提供者明确你在制作什么以及可能造成的后果
出于设备原因,本教程仅在Windows系统下进行过测试,Mac和Linux请确保自己有一定解决问题能力
该项目为歌声合成项目,无法进行其他用途,请知悉
在有底模的前提下,选取200条音频作为训练集,经多次测试(RTX3060, batch_size = 3
)得到以下结论:
- 本项目需要的环境:
NVIDIA-CUDA
Python <= 3.10
Pytorch
FFmpeg
在cmd控制台里输入nvidia-smi.exe
以查看显卡驱动版本和对应的cuda版本
前往 NVIDIA-Developer 官网下载与系统对应的Cuda版本
以Cuda-11.7
版本为例(注:本文下述所有配置均在Cuda-11.7
下演示)Cuda11.7下载地址 根据自己的系统和需求选择安装(一般本地Windows用户请依次选择Windows
, x86_64
, 系统版本
, exe(local)
)
安装成功之后在cmd控制台中输入nvcc -V
, 出现类似以下内容则安装成功:
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Tue_May__3_19:00:59_Pacific_Daylight_Time_2022
Cuda compilation tools, release 11.7, V11.7.64
Build cuda_11.7.r11.7/compiler.31294372_0
cuda11.7
nvidia-smi.exe
并不会出现cuda版本变化,即任然显示的是>11,7的版本NVIDIA CUDA
的程序全部卸载即可(一共5个)python
出现类似以下内容则安装成功: Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
# 设置清华大学下载镜像
pip config set global.index-url http://pypi.tuna.tsinghua.edu.cn/simple
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
torch
, torchaudio
, torchvision
这三个库,下面提供两种方法直接前往 Pytorch官网 选择所需版本然后复制Run this Command栏显示的命令至cmd安装(不建议)
前往该地址使用Ctrl+F
搜索直接下载whl包 点击前往
- 这个项目需要的是
torch==1.10.0+cu113
torchaudio==0.10.0+cu113
1.10.0
和0.10.0
表示是pytorch
版本,cu113
表示cuda
版本11.3
以此类推,请选择适合自己的版本安装
下面我将以Cuda11.7
版本为例
–示例开始–
- 我们需要安装以下三个库
- torch-1.13.0+cu117-cp310-cp310-win_amd64.whl 其中cp310指
python3.10
,win-amd64
表示windows 64位操作系统- torchaudio-0.13.0+cu117-cp310-cp310-win_amd64.whl
- torchvision-0.14.0+cu117-cp310-cp310-win_amd64.whl
下载完成后进入进入下载的whl文件的目录,在所处文件夹内右击空白处选择 在终端中打开 并执行下面命令以安装库
pip install .\torch-1.13.0+cu117-cp310-cp310-win_amd64.whl
# 回车运行(安装时间较长)
pip install .\torchaudio-0.13.0+cu117-cp310-cp310-win_amd64.whl
# 回车运行
pip install .\torchvision-0.14.0+cu117-cp310-cp310-win_amd64.whl
# 回车运行
Successfully installed ...
之后再执行下一条命令,第一个torch包安装时间较长安装完torch
, torchaudio
, torchvision
这三个库之后,在cmd控制台运用以下命令检测cuda与torch版本是否匹配
python
# 回车运行
import torch
# 回车运行
print(torch.__version__)
# 回车运行
print(torch.cuda.is_available())
# 回车运行
True
则成功,出现False
则失败,需要重新安装requirements.txt
的文本文件,输入以下内容保存 Flask==2.1.2
Flask_Cors==3.0.10
gradio==3.4.1
numpy==1.23.5
playsound==1.3.0
PyAudio==0.2.12
pydub==0.25.1
pyworld==0.3.2
requests==2.28.1
scipy==1.10.0
sounddevice==0.4.5
SoundFile==0.10.3.post1
starlette==0.19.1
tqdm==4.63.0
scikit-maad
praat-parselmouth
tensorboard
librosa
fairseq
pip install [库名称]
重新单独安装直至成功) pip install -r requirements.txt
.\ffmpeg\bin
(详细安装方法以及添加Path此处省略,网上随便一查都有)ffmpeg -version
出现类似以下内容则安装成功ffmpeg version git-2020-08-12-bb59bdb Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 10.2.1 (GCC) 20200805
configuration: [此处省略一大堆内容]
libavutil 56. 58.100 / 56. 58.100
libavcodec 58.100.100 / 58.100.100
...
前往 so-vits-svc4.0 下载源代码。
你也可以根据需要下载以下两个:
改善了交互的一个分支推荐:34j/so-vits-svc-fork
支持实时转换的一个客户端:w-okada/voice-changer
解压到任意文件夹
hubert
目录下# contentvec
http://obs.cstcloud.cn/share/obs/sankagenkeshi/checkpoint_best_legacy_500.pt
# 也可手动下载放在hubert目录
G_0.pth
D_0.pth
logs/44k
目录下虽然底模一般不会引起什么版权问题,但还是请注意一下,比如事先询问作者,又或者作者在模型描述中明确写明了可行的用途
准备的训练数据,建议60-100条语音(格式务必为wav,不同的说话人建立不同的文件夹),每条语音控制在4-8秒!(确保语音不要有噪音或尽量降低噪音,一个文件夹内语音必须是一个人说的),可以训练出效果不错的模型。
长音频可以使用辅助音频自动切片软件进行大量切片 audio-slicer
.\dataset_raw
文件夹里,文件结构类似如下:dataset_raw
├───speaker0
│ ├───xxx1-xxx1.wav
│ ├───...
│ └───Lxx-0xx8.wav
└───speaker1
├───xx2-0xxx2.wav
├───...
└───xxx7-xxx007.wav
.\dataset_raw
文件夹内新建并编辑config.json
,代码如下:"n_speakers": 10 //修改数字为说话人的人数
"spk":{
"speaker0": 0, //修改speaker0为第一个说话人的名字,需要和文件夹名字一样,后面的: 0, 不需要改
"speaker1": 1, //以此类推
"speaker2": 2,
//以此类推
}
so-vits-svc
文件夹内运行终端,直接执行: python resample.py
.\dataset\32k
文件夹中会有说话人的wav语音。so-vits-svc
文件夹内运行终端,直接执行: python preprocess_flist_config.py
PS E:\vs\so-vits-svc> python preprocess_flist_config.py
100%|████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1993.49it/s]
Writing ./filelists/train.txt
100%|████████████████████████████████████████████████████████████████████████████████████████████| 16/16 [00:00<?, ?it/s]
Writing ./filelists/val.txt
100%|████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<?, ?it/s]
Writing ./filelists/test.txt
100%|████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<?, ?it/s]
Writing configs/config.json
so-vits-svc
文件夹内运行终端,直接执行: python preprocess_hubert_f0.py
PS E:\vs\so-vits-svc-32k> python preprocess_hubert_f0.py
Loading hubert for content...
Loaded hubert.
100%|██████████████████████████████████████████████████████████████████████████████████| 20/20 [00:06<00:00, 3.03it/s]
打开上面第二步过程中生成的配置文件.\configs\config.json
修改第13
行代码"batch_size"
的数值。这边解释一下"batch_size": 12,
数值12要根据自己电脑的显存(任务管理器-GPU- 专用GPU内存)来调整
- 修改建议
6G显存 建议修改成2-3
8G显存 建议修改成4-6
"batch_size"参数调小可以解决显存不够的问题
so-vits-svc
文件夹内运行终端,直接执行下面命令开始训练 python train.py -c configs/config.json -m 44k
torch.cuda.OutOfMemoryError: CUDA out of menory. Tried to allocate 16.80 MiB (GPU 0; 8.0 GiB total capacity; 7.11 Gi8 already allocated; 0 bytes free; 7.30 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation. See documentation for Memory Management and PYTORCH_cUDA_ALLOC_CONF
# 注意:一定是 0 bytes free < Tried to allocate 16.80 MiB 才是显存不足,不然就是别的问题
python train.py -c configs/config.json -m 32k
,多重试几遍,或者关机重启,一般是会成功的。如果报错一直是同一个报错,那就是对应的那里出问题了(要靠报错找问题所在)2023-04-01 17:02:21,633 44k INFO {
'train': {
'log_interval': 200, 'eval_interval': 800, 'seed': 1234, 'epochs': 10000, 'learning_rate': 0.0001, 'betas': [0.8, 0.99], 'eps': 1e-09, 'batch_size': 2, 'fp16_run': False, 'lr_decay': 0.999875, 'segment_size': 10240, 'init_lr_ratio': 1, 'warmup_epochs': 0, 'c_mel': 45, 'c_kl': 1.0, 'use_sr': True, 'max_speclen': 512, 'port': '8001', 'keep_ckpts': 3}, 'data': {
'training_files': 'filelists/train.txt', 'validation_files': 'filelists/val.txt', 'max_wav_value': 32768.0, 'sampling_rate': 44100, 'filter_length': 2048, 'hop_length': 512, 'win_length': 2048, 'n_mel_channels': 80, 'mel_fmin': 0.0, 'mel_fmax': 22050}, 'model': {
'inter_channels': 192, 'hidden_channels': 192, 'filter_channels': 768, 'n_heads': 2, 'n_layers': 6, 'kernel_size': 3, 'p_dropout': 0.1, 'resblock': '1', 'resblock_kernel_sizes': [3, 7, 11], 'resblock_dilation_sizes': [[1, 3, 5], [1, 3, 5], [1, 3, 5]], 'upsample_rates': [8, 8, 2, 2, 2], 'upsample_initial_channel': 512, 'upsample_kernel_sizes': [16, 16, 4, 4, 4], 'n_layers_q': 3, 'use_spectral_norm': False, 'gin_channels': 256, 'ssl_dim': 256, 'n_speakers': 1}, 'spk': {
'sanwu': 0}, 'model_dir': './logs\\44k'}
2023-04-01 17:02:21,634 44k WARNING E:\vs\so-vits-svc\so-vits-svc-4.0-sanwu is not a git repository, therefore hash value comparison will be ignored.
2023-04-01 17:02:24,816 44k INFO Loaded checkpoint './logs\44k\G_2400.pth' (iteration 7)
2023-04-01 17:02:25,289 44k INFO Loaded checkpoint './logs\44k\D_2400.pth' (iteration 7)
2023-04-01 17:04:07,531 44k INFO Train Epoch: 7 [27%]
2023-04-01 17:04:07,531 44k INFO Losses: [1.178899884223938, 5.447257995605469, 13.873568534851074, 45.92221450805664, 1.7247810363769531], step: 2400, lr: 9.991253280566489e-05
2023-04-01 17:04:12,999 44k INFO Saving model and optimizer state at iteration 7 to ./logs\44k\G_2400.pth
2023-04-01 17:04:13,783 44k INFO Saving model and optimizer state at iteration 7 to ./logs\44k\D_2400.pth
2023-04-01 17:06:45,604 44k INFO Train Epoch: 7 [79%]
2023-04-01 17:06:45,604 44k INFO Losses: [1.1601612567901611, 4.299866199493408, 13.368327140808105, 34.780784606933594, 1.5297999382019043], step: 2600, lr: 9.991253280566489e-05
2023-04-01 17:07:39,541 44k INFO ====> Epoch: 7, cost 317.91 s
2023-04-01 17:09:00,870 44k INFO Train Epoch: 8 [31%]
2023-04-01 17:09:00,871 44k INFO Losses: [0.7684269547462463, 4.85490608215332, 17.213212966918945, 42.981754302978516, 1.2239456176757812], step: 2800, lr: 9.990004373906418e-05
2023-04-01 17:10:57,125 44k INFO Train Epoch: 8 [83%]
2023-04-01 17:10:57,126 44k INFO Losses: [1.4237611293792725, 3.9369957447052, 13.494928359985352, 34.12102127075195, 1.412590503692627], step: 3000, lr: 9.990004373906418e-05
2023-04-01 17:11:34,132 44k INFO ====> Epoch: 8, cost 234.59 s
2023-04-01 17:13:16,350 44k INFO Train Epoch: 9 [36%]
2023-04-01 17:13:16,350 44k INFO Losses: [0.9615359306335449, 5.3759379386901855, 11.088563919067383, 34.991233825683594, 1.9573057889938354], step: 3200, lr: 9.98875562335968e-05
2023-04-01 17:13:20,401 44k INFO Saving model and optimizer state at iteration 9 to ./logs\44k\G_3200.pth
2023-04-01 17:13:21,223 44k INFO Saving model and optimizer state at iteration 9 to ./logs\44k\D_3200.pth
2023-04-01 17:13:21,813 44k INFO .. Free up space by deleting ckpt ./logs\44k\G_800.pth
2023-04-01 17:13:21,814 44k INFO .. Free up space by deleting ckpt ./logs\44k\D_800.pth
2023-04-01 17:15:17,549 44k INFO Train Epoch: 9 [88%]
2023-04-01 17:15:17,550 44k INFO Losses: [1.2361057996749878, 4.204023838043213, 13.108729362487793, 37.149662017822266, 1.6868081092834473], step: 3400, lr: 9.98875562335968e-05
2023-04-01 17:15:45,216 44k INFO ====> Epoch: 9, cost 251.08 s
出现类似以上的内容就说明是在开始训练了(显存会直接爆满)。停止训练有下面两种方法:
- 按
Ctrl+C
- 直接右上角叉掉
在控制台中运行python train.py -c configs/config.json -m 44k
即可继续训练
注意:上述训练过程第一次运行时可能会出现如下报错,不用理会即可(如果你懂pth文件结构可以尝试修复)
2023-04-01 09:58:55,507 44k INFO emb_g.weight is not in the checkpoint
2023-04-01 09:58:55,507 44k INFO pre.weight is not in the checkpoint
2023-04-01 09:58:55,508 44k INFO pre.bias is not in the checkpoint
2023-04-01 09:58:55,508 44k INFO enc_p.proj.weight is not in the checkpoint
2023-04-01 09:58:55,508 44k INFO enc_p.proj.bias is not in the checkpoint
2023-04-01 09:58:55,508 44k INFO enc_p.f0_emb.weight is not in the checkpoint
2023-04-01 09:58:55,508 44k INFO enc_p.enc_.attn_layers.0.emb_rel_k is not in the checkpoint
2023-04-01 09:58:55,509 44k INFO enc_p.enc_.attn_layers.0.emb_rel_v is not in the checkpoint
2023-04-01 09:58:55,509 44k INFO enc_p.enc_.attn_layers.0.conv_q.weight is not in the checkpoint
2023-04-01 09:58:55,509 44k INFO enc_p.enc_.attn_layers.0.conv_q.bias is not in the checkpoint
2023-04-01 09:58:55,509 44k INFO enc_p.enc_.attn_layers.0.conv_k.weight is not in the checkpoint
2023-04-01 09:58:55,509 44k INFO enc_p.enc_.attn_layers.0.conv_k.bias is not in the checkpoint
2023-04-01 09:58:55,509 44k INFO enc_p.enc_.attn_layers.0.conv_v.weight is not in the checkpoint
2023-04-01 09:58:55,510 44k INFO enc_p.enc_.attn_layers.0.conv_v.bias is not in the checkpoint
2023-04-01 09:58:55,510 44k INFO enc_p.enc_.attn_layers.0.conv_o.weight is not in the checkpoint
2023-04-01 09:58:55,510 44k INFO enc_p.enc_.attn_layers.0.conv_o.bias is not in the checkpoint
#此处省略更多
#…………
.\logs\44k\train.log
# 示例3
2023-02-08 18:32:24,942 44k INFO [2.252035617828369, 2.5846095085144043, 8.220404624938965, 5 17.75478744506836, 0.9781494140625, 2000, 9.911637167309565e-05]
2023-02-08 18:32:28,889 44k INFO Saving model and optimizer state at iteration 72 to ./logs\44k\G_2000.pth
2023-02-08 18:32:29,661 44k INFO Saving model and optimizer state at iteration 72 to ./logs\44k\D_2000.pth
# 示例1
2023-02-08 18:32:39,907 44k INFO ====> Epoch: 72, cost xxx s
2023-02-08 18:33:00,099 44k INFO ====> Epoch: 73, cost xxx s
2023-02-08 18:33:20,682 44k INFO ====> Epoch: 74, cost xxx s
2023-02-08 18:33:40,887 44k INFO ====> Epoch: 75, cost xxx s
2023-02-08 18:34:01,460 44k INFO ====> Epoch: 76, cost xxx s
2023-02-08 18:34:21,798 44k INFO ====> Epoch: 77, cost xxx s
2023-02-08 18:34:41,866 44k INFO ====> Epoch: 78, cost xxx s
2023-02-08 18:34:54,712 44k INFO Train Epoch: 79 [57%]
# 示例2
2023-02-08 18:34:54,712 44k INFO [2.282658100128174, 2.5492446422576904, 10.027194023132324, 15.401838302612305, 1.598284363746643, 2200, 9.902967736366644e-05]
以下的解释我引用了B站up主inifnite_loop的解释,相关视频 相关专栏
- 需要关注两个参数:Epoch和global_step
Epoch表示迭代批次,每一批次可以看作一个迭代分组
Global_step表示总体迭代次数- 两者的关系是global_step = 最多语音说话人的语音数 / batch_size * epoch
batch_size是配置文件中的参数- 示例1: 每一次迭代输出内
====> Epoch: 74
表示第74迭代批次完成- 示例2:
Global_step
每200次输出一次 (配置文件中的参数log_interval
)- 示例3:
Global_step
每1000次(未改配置文件应该默认是800次)输出一次(配置文件中的参数eval_interval
),会保存模型到新的文件
以上,我们谈论到了每1000次(未改配置文件应该默认是800次)迭代才会保存一次模型样本,那么,这些样本保存在哪里呢?如何处理这些样本呢?下面我将详细讲述。
.\logs\44k
D_0.pth
D_1000.pth
D_2000.pth
D_3000.pth
D_4000.pth
...
G_0.pth
G_1000.pth
G_2000.pth
G_3000.pth
G_4000.pth
...
按上述方法训练得到最后一次的G和D后,该如何使用这些模型呢?下面我将讲述具体的使用操作方法
.\raw
文件夹inference_main.py
,修改第25-46
行,具体修改内容如下(其实注释很清楚,我照搬了)# 一定要设置的部分
parser.add_argument('-m', '--model_path', type=str, default="logs/44k/G_4800.pth", help='模型路径')
parser.add_argument('-c', '--config_path', type=str, default="configs/config.json", help='配置文件路径')
parser.add_argument('-cl', '--clip', type=float, default=0, help='音频自动切片,0为不切片,单位为秒/s')
parser.add_argument('-n', '--clean_names', type=str, nargs='+', default=["vocals (1)","vocals (2)","vocals (3)","vocals (4)","vocals (5)","vocals (6)","vocals (7)","vocals (8)"], help='wav文件名列表,放在raw文件夹下')
parser.add_argument('-t', '--trans', type=int, nargs='+', default=[0], help='音高调整,支持正负(半音)')
parser.add_argument('-s', '--spk_list', type=str, nargs='+', default=['Hanser'], help='合成目标说话人名称')
# 可选项部分
parser.add_argument('-a', '--auto_predict_f0', action='store_true', default=False,
help='语音转换自动预测音高,转换歌声时不要打开这个会严重跑调')
parser.add_argument('-cm', '--cluster_model_path', type=str, default="logs/44k/kmeans_10000.pt", help='聚类模型路径,如果没有训练聚类则随便填')
parser.add_argument('-cr', '--cluster_infer_ratio', type=float, default=0, help='聚类方案占比,范围0-1,若没有训练聚类模型则填0即可')
parser.add_argument('-lg', '--linear_gradient', type=float, default=0, help='两段音频切片的交叉淡入长度,如果自动切片后出现人声不连贯可调整该数值,如果连贯建议采用默认值0,单位为秒/s')
# 不用动的部分
parser.add_argument('-sd', '--slice_db', type=int, default=-40, help='默认-40,嘈杂的音频可以-30,干声保留呼吸可以-50')
parser.add_argument('-d', '--device', type=str, default=None, help='推理设备,None则为自动选择cpu和gpu')
parser.add_argument('-ns', '--noice_scale', type=float, default=0.4, help='噪音级别,会影响咬字和音质,较为玄学')
parser.add_argument('-p', '--pad_seconds', type=float, default=0.5, help='推理音频pad秒数,由于未知原因开头结尾会有异响,pad一小段静音段后就不会出现')
parser.add_argument('-wf', '--wav_format', type=str, default='wav', help='音频输出格式')
parser.add_argument('-lgr', '--linear_gradient_retain', type=float, default=0.75, help='自动音频切片后,需要舍弃每段切片的头尾。该参数设置交叉长度保留的比例,范围0-1,左开右闭')
# 例
python inference_main.py -m "logs/44k/G_30400.pth" -c "configs/config.json" -n "君の知らない物語-src.wav" -t 0 -s "nen"
必填项部分
-m
| --model_path
:模型路径-c
| --config_path
:配置文件路径-n
| --clean_names
:wav 文件名列表,放在 raw 文件夹下-t
| --trans
:音高调整,支持正负(半音)-s
| --spk_list
:合成目标说话人名称-cl
| --clip
:音频强制切片,默认0为自动切片,单位为秒/s可选项部分:部分具体见下一节
-lg
| --linear_gradient
:两段音频切片的交叉淡入长度,如果强制切片后出现人声不连贯可调整该数值,如果连贯建议采用默认值0,单位为秒-fmp
| --f0_mean_pooling
:是否对F0使用均值滤波器(池化),对部分哑音有改善。注意,启动该选项会导致推理速度下降,默认关闭-a
| --auto_predict_f0
:语音转换自动预测音高,转换歌声时不要打开这个会严重跑调-cm
| --cluster_model_path
:聚类模型路径,如果没有训练聚类则随便填-cr
| --cluster_infer_ratio
:聚类方案占比,范围0-1,若没有训练聚类模型则默认0即可so-vits-svc
文件夹内运行终端,执行下面命令开始推理生成 python .\inference_main.py
.\results
文件夹下
- 以下是对本文档的撰写有帮助的感谢名单:
so-vits-svc 官方源代码和帮助文档
B站up主inifnite_loop 3.0版本相关视频 以及 3.0版本相关专栏
所有提供训练音频样本的人员
本帮助文档为项目 so-vits-svc3.0 的详细中文安装、调试、推理教程,您也可以直接选择官方README文档
撰写:Sucial 点击跳转B站主页
- 本项目需要的环境:
NVIDIA-CUDA
Python <= 3.10
Pytorch
FFmpeg
在cmd控制台里输入nvidia-smi.exe
以查看显卡驱动版本和对应的cuda版本
前往 NVIDIA-Developer 官网下载与系统对应的Cuda版本
以Cuda-11.7
版本为例(注:本文下述所有配置均在Cuda-11.7
下演示)Cuda11.7下载地址 根据自己的系统和需求选择安装(一般本地Windows用户请依次选择Windows
, x86_64
, 系统版本
, exe(local)
)
安装成功之后在cmd控制台中输入nvcc -V
, 出现类似以下内容则安装成功:
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Tue_May__3_19:00:59_Pacific_Daylight_Time_2022
Cuda compilation tools, release 11.7, V11.7.64
Build cuda_11.7.r11.7/compiler.31294372_0
cuda11.7
nvidia-smi.exe
并不会出现cuda版本变化,即任然显示的是>11,7的版本NVIDIA CUDA
的程序全部卸载即可(一共5个)python
出现类似以下内容则安装成功: Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
# 设置清华大学下载镜像
pip config set global.index-url http://pypi.tuna.tsinghua.edu.cn/simple
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
requirements.txt
的文本文件,输入以下内容保存 Flask==2.1.2
Flask_Cors==3.0.10
gradio==3.4.1
numpy==1.23.5
playsound==1.3.0
PyAudio==0.2.12
pydub==0.25.1
pyworld==0.3.2
requests==2.28.1
scipy==1.10.0
sounddevice==0.4.5
SoundFile==0.10.3.post1
starlette==0.19.1
tqdm==4.63.0
scikit-maad
praat-parselmouth
tensorboard
librosa
pip install [库名称]
重新单独安装直至成功) pip install -r requirements.txt
torch
, torchaudio
, torchvision
这三个库,下面提供两种方法直接前往 Pytorch官网 选择所需版本然后复制Run this Command栏显示的命令至cmd安装(不建议)
Ctrl+F
搜索直接下载whl包 点击前往
- 这个项目需要的是
torch==1.10.0+cu113
torchaudio==0.10.0+cu113
1.10.0 和0.10.0表示是pytorch版本,cu113表示cuda版本11.3
以此类推,请选择适合自己的版本安装
Cuda11.7
版本为例
- 我们需要安装以下三个库
torch-1.13.0+cu117
点击下载:torch-1.13.0+cu117-cp310-cp310-win_amd64.whl
其中cp310指python3.10
,win-amd64
表示windows 64位操作系统torchaudio-0.13.0+cu117
点击下载:torchaudio-0.13.0+cu117-cp310-cp310-win_amd64.whltorchvision-0.14.0+cu117
点击下载:torchvision-0.14.0+cu117-cp310-cp310-win_amd64.whl
pip install .\torch-1.13.0+cu117-cp310-cp310-win_amd64.whl
# 回车运行(安装时间较长)
pip install .\torchaudio-0.13.0+cu117-cp310-cp310-win_amd64.whl
# 回车运行
pip install .\torchvision-0.14.0+cu117-cp310-cp310-win_amd64.whl
# 回车运行
Successfully installed ...
之后再执行下一条命令,第一个torch包安装时间较长安装完torch
, torchaudio
, torchvision
这三个库之后,在cmd控制台运用以下命令检测cuda与torch版本是否匹配
python
# 回车运行
import torch
# 回车运行
print(torch.__version__)
# 回车运行
print(torch.cuda.is_available())
# 回车运行
True
则成功,出现False
则失败,需要重新安装.\ffmpeg\bin
(详细安装方法以及添加Path此处省略,网上随便一查都有)ffmpeg -version
出现类似以下内容则安装成功ffmpeg version git-2020-08-12-bb59bdb Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 10.2.1 (GCC) 20200805
configuration: [此处省略一大堆内容]
libavutil 56. 58.100 / 56. 58.100
libavcodec 58.100.100 / 58.100.100
...
前往 so-vits-svc 选择32k
分支(本教程针对32k
)下载源代码。安装了git的可直接git以下地址
解压到任意文件夹
hubert
https://github.com/bshall/hubert/releases/download/v0.1/hubert-soft-0d54a1f4.pt
G与D预训练模型
https://huggingface.co/innnky/sovits_pretrained/resolve/main/G_0.pth
https://huggingface.co/innnky/sovits_pretrained/resolve/main/D_0.pth
上述三个底模如果原链接下载不了请点击下方的链接
https://pan.baidu.com/s/1uw6W3gOBvMbVey1qt_AzhA?pwd=80eo 提取码:80eo
hubert-soft-0d54a1f4.pt
放入.\hubert
文件夹D_0.pth和G_0.pth
文件放入.\logs\32k
文件夹准备的训练数据,建议60-100条语音(格式务必为wav,不同的说话人建立不同的文件夹),每条语音控制在4-8秒!(确保语音不要有噪音或尽量降低噪音,一个文件夹内语音必须是一个人说的),可以训练出效果不错的模型
.\dataset_raw
文件夹里,文件结构类似如下:dataset_raw
├───speaker0
│ ├───xxx1-xxx1.wav
│ ├───...
│ └───Lxx-0xx8.wav
└───speaker1
├───xx2-0xxx2.wav
├───...
└───xxx7-xxx007.wav
.\dataset_raw
文件夹内新建并编辑config.json
,代码如下:"n_speakers": 10 //修改数字为说话人的人数
"spk":{
"speaker0": 0, //修改speaker0为第一个说话人的名字,需要和文件夹名字一样,后面的: 0, 不需要改
"speaker1": 1, //以此类推
"speaker2": 2,
//以此类推
}
so-vits-svc
文件夹内运行终端,直接执行: python resample.py
注意:如果遇到如下报错:
...
E:\vs\so-vits-svc-32k\resample.py:17: FutureWarning: Pass sr=None as keyword args. From version 0.10 passing these as positional arguments will result in an error
wav, sr = librosa.load(wav_path, None)
E:\vs\so-vits-svc-32k\resample.py:17: FutureWarning: Pass sr=None as keyword args. From version 0.10 passing these as positional arguments will result in an error
wav, sr = librosa.load(wav_path, None)
...
请打开resample.py
,修改第17
行内容
# 第17行修改前如下
wav, sr = librosa.load(wav_path, None)
# 第17行修改后如下
wav, sr = librosa.load(wav_path, sr = None)
保存,重新执行python resample.py
命令
.\dataset\32k
文件夹中会有说话人的wav语音,之后dataset_raw
文件夹就可以删除了so-vits-svc
文件夹内运行终端,直接执行: python preprocess_flist_config.py
PS E:\vs\so-vits-svc-32k> python preprocess_flist_config.py
100%|██████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1993.49it/s]
Writing ./filelists/train.txt
100%|██████████████████████████████████████████████████████████████████████████████████████████| 16/16 [00:00<?, ?it/s]
Writing ./filelists/val.txt
100%|████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<?, ?it/s]
Writing ./filelists/test.txt
100%|████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<?, ?it/s]
Writing configs/config.json
so-vits-svc
文件夹内运行终端,直接执行: python preprocess_hubert_f0.py
PS E:\vs\so-vits-svc-32k> python preprocess_hubert_f0.py
Loading hubert for content...
Loaded hubert.
0%| | 0/20 [00:00<?, ?it/s]dataset/32k\speaker\1_01.wav
5%|████ | 1/20 [00:03<01:00, 3.20s/it]dataset/32k\speaker\1_02.wav
10%|████████ | 2/20 [00:03<00:25, 1.40s/it]dataset/32k\speaker\1_03.wav
15%|████████████ | 3/20 [00:03<00:14, 1.19it/s]dataset/32k\speaker\1_04.wav
20%|████████████████▌ | 4/20 [00:03<00:09, 1.69it/s]dataset/32k\speaker\1_05.wav
25%|████████████████████ | 5/20 [00:03<00:06, 2.39it/s]dataset/32k\speaker\1_06.wav
30%|████████████████████████ | 6/20 [00:04<00:04, 2.98it/s]dataset/32k\speaker\1_07.wav
35%|█████████████████████████████ | 7/20 [00:04<00:03, 3.48it/s]dataset/32k\speaker\1_08.wav
40%|█████████████████████████████████ | 8/20 [00:04<00:03, 3.78it/s]dataset/32k\speaker\1_09.wav
45%|█████████████████████████████████████ | 9/20 [00:04<00:02, 4.13it/s]dataset/32k\speaker\1_10.wav
50%|█████████████████████████████████████████ | 10/20 [00:04<00:02, 4.41it/s]dataset/32k\speaker\1_11.wav
55%|█████████████████████████████████████████████ | 11/20 [00:04<00:01, 4.71it/s]dataset/32k\speaker\1_12.wav
60%|█████████████████████████████████████████████████ | 12/20 [00:05<00:01, 4.93it/s]dataset/32k\speaker\1_13.wav
65%|█████████████████████████████████████████████████████ | 13/20 [00:05<00:01, 5.25it/s]dataset/32k\speaker\1_14.wav
70%|█████████████████████████████████████████████████████████ | 14/20 [00:05<00:01, 5.46it/s]dataset/32k\speaker\1_15.wav
75%|█████████████████████████████████████████████████████████████▌ | 15/20 [00:05<00:00, 6.19it/s]dataset/32k\speaker\1_16.wav
80%|█████████████████████████████████████████████████████████████████▌ | 16/20 [00:05<00:00, 5.84it/s]dataset/32k\speaker\1_17.wav
85%|█████████████████████████████████████████████████████████████████████ | 17/20 [00:06<00:00, 5.43it/s]dataset/32k\speaker\1_18.wav
90%|█████████████████████████████████████████████████████████████████████████ | 18/20 [00:06<00:00, 5.27it/s]dataset/32k\speaker\1_19.wav
95%|█████████████████████████████████████████████████████████████████████████████ | 19/20 [00:06<00:00, 5.26it/s]dataset/32k\speaker\1_20.wav
100%|██████████████████████████████████████████████████████████████████████████████████| 20/20 [00:06<00:00, 3.03it/s]
.\configs\config.json
修改第13
行代码"batch_size"
的数值。这边解释一下"batch_size": 12,
数值12要根据自己电脑的显存(任务管理器-GPU-专用GPU内存)来调整
- 修改建议
6G显存 建议修改成2或3
8G显存 建议修改成4
"batch_size"参数调小可以解决显存不够的问题
train.py
# 第60行将nccl改成gloo(如果后续开始训练时gloo报错就改回nccl,一般不会报错)
# 修改前如下
dist.init_process_group(backend='nccl', init_method='env://', world_size=n_gpus, rank=rank)
# 修改后如下
dist.init_process_group(backend='gloo', init_method='env://', world_size=n_gpus, rank=rank)
# 第44行开始
# 修改前如下
n_gpus = torch.cuda.device_count()
os.environ['MASTER_ADDR'] = 'localhost'
os.environ['MASTER_PORT'] = hps.train.port
#修改后增加代码后如下
n_gpus = torch.cuda.device_count()
os.environ['MASTER_ADDR'] = 'localhost'
os.environ['MASTER_PORT'] = hps.train.port
os.environ["CUDA_VISIBLE_DEVICES"] = "0" # 这里的0代表GPU0是用来训练的显卡,不知道是0还是1的可以在任务管理器查看,如果是双显卡的话一定要选择适合的显卡
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:32" # 这里的32如果懂的话也可以修改,不懂别改
so-vits-svc
文件夹内运行终端,直接执行下面命令开始训练 python train.py -c configs/config.json -m 32k
torch.cuda.OutOfMemoryError: CUDA out of menory. Tried to allocate 16.80 MiB (GPU 0; 8.0 GiB total capacity; 7.11 Gi8 already allocated; 0 bytes free; 7.30 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation. See documentation for Memory Management and PYTORCH_cUDA_ALLOC_CONF
# 注意:一定是 0 bytes free < Tried to allocate 16.80 MiB 才是显存不足,不然就是别的问题
python train.py -c configs/config.json -m 32k
,多重试几遍,或者关机重启,一般是会成功的。如果报错一直是同一个报错,那就是对应的那里出问题了(要靠报错找问题所在)2023-02-08 18:07:42,439 32k INFO {
'train': {
'log_interval': 200, 'eval_interval': 1000, 'seed': 1234, 'epochs': 10000, 'learning_rate': 0.0001, 'betas': [0.8, 0.99], 'eps': 1e-09, 'batch_size': 2, 'fp16_run': False, 'lr_decay': 0.999875, 'segment_size': 17920, 'init_lr_ratio': 1, 'warmup_epochs': 0, 'c_mel': 45, 'c_kl': 1.0, 'use_sr': True, 'max_speclen': 384, 'port': '8001'}, 'data': {
'training_files': 'filelists/train.txt', 'validation_files': 'filelists/val.txt', 'max_wav_value': 32768.0, 'sampling_rate': 32000, 'filter_length': 1280, 'hop_length': 320, 'win_length': 1280, 'n_mel_channels': 80, 'mel_fmin': 0.0, 'mel_fmax': None}, 'model': {
'inter_channels': 192, 'hidden_channels': 192, 'filter_channels': 768, 'n_heads': 2, 'n_layers': 6, 'kernel_size': 3, 'p_dropout': 0.1, 'resblock': '1', 'resblock_kernel_sizes': [3, 7, 11], 'resblock_dilation_sizes': [[1, 3, 5], [1, 3, 5], [1, 3, 5]], 'upsample_rates': [10, 8, 2, 2], 'upsample_initial_channel': 512, 'upsample_kernel_sizes': [16, 16, 4, 4], 'n_layers_q': 3, 'use_spectral_norm': False, 'gin_channels': 256, 'ssl_dim': 256, 'n_speakers': 2}, 'spk': {
'Sucial': 0}, 'model_dir': './logs\\32k'}
2023-02-08 18:07:42,440 32k WARNING E:\vs\so-vits-svc-32k is not a git repository, therefore hash value comparison will be ignored.
2023-02-08 18:07:45,451 32k INFO Loaded checkpoint './logs\32k\G_0.pth' (iteration 1)
2023-02-08 18:07:45,998 32k INFO Loaded checkpoint './logs\32k\D_0.pth' (iteration 1)
2023-02-08 18:07:55,722 32k INFO Train Epoch: 1 [0%]
2023-02-08 18:07:55,723 32k INFO [1.376741886138916, 3.908522129058838, 12.127800941467285, 35.539894104003906, 4.270486354827881, 0, 0.0001]
2023-02-08 18:08:01,381 32k INFO Saving model and optimizer state at iteration 1 to ./logs\32k\G_0.pth
2023-02-08 18:08:02,344 32k INFO Saving model and optimizer state at iteration 1 to ./logs\32k\D_0.pth
2023-02-08 18:08:19,482 32k INFO ====> Epoch: 1
2023-02-08 18:08:40,093 32k INFO ====> Epoch: 2
2023-02-08 18:09:01,010 32k INFO ====> Epoch: 3
2023-02-08 18:09:21,715 32k INFO ====> Epoch: 4
2023-02-08 18:09:42,242 32k INFO ====> Epoch: 5
2023-02-08 18:10:02,528 32k INFO ====> Epoch: 6
2023-02-08 18:10:22,965 32k INFO ====> Epoch: 7
2023-02-08 18:10:29,149 32k INFO Train Epoch: 8 [14%]
2023-02-08 18:10:29,150 32k INFO [2.378505229949951, 2.3670239448547363, 10.534687042236328, 19.235595703125, 1.8958038091659546, 200, 9.991253280566489e-05]
2023-02-08 18:10:43,388 32k INFO ====> Epoch: 8
2023-02-08 18:11:03,722 32k INFO ====> Epoch: 9
2023-02-08 18:11:23,859 32k INFO ====> Epoch: 10
...
- 按
Ctrl+C
- 直接右上角叉掉
在控制台中运行python train.py -c config/config.json -m 32k
即可继续训练
.\logs\32k\train.log
# 示例3
2023-02-08 18:32:24,942 32k INFO [2.252035617828369, 2.5846095085144043, 8.220404624938965, 5 17.75478744506836, 0.9781494140625, 2000, 9.911637167309565e-05]
2023-02-08 18:32:28,889 32k INFO Saving model and optimizer state at iteration 72 to ./logs\32k\G_2000.pth
2023-02-08 18:32:29,661 32k INFO Saving model and optimizer state at iteration 72 to ./logs\32k\D_2000.pth
# 示例1
2023-02-08 18:32:39,907 32k INFO ====> Epoch: 72
2023-02-08 18:33:00,099 32k INFO ====> Epoch: 73
2023-02-08 18:33:20,682 32k INFO ====> Epoch: 74
2023-02-08 18:33:40,887 32k INFO ====> Epoch: 75
2023-02-08 18:34:01,460 32k INFO ====> Epoch: 76
2023-02-08 18:34:21,798 32k INFO ====> Epoch: 77
2023-02-08 18:34:41,866 32k INFO ====> Epoch: 78
2023-02-08 18:34:54,712 32k INFO Train Epoch: 79 [57%]
# 示例2
2023-02-08 18:34:54,712 32k INFO [2.282658100128174, 2.5492446422576904, 10.027194023132324, 15.401838302612305, 1.598284363746643, 2200, 9.902967736366644e-05]
以下的解释我引用了B站up主inifnite_loop的解释,相关视频 相关专栏
- 需要关注两个参数:Epoch和global_step
Epoch表示迭代批次,每一批次可以看作一个迭代分组
Global_step表示总体迭代次数- 两者的关系是global_step = 最多语音说话人的语音数 / batch_size * epoch
batch_size是配置文件中的参数- 示例1: 每一次迭代输出内
====> Epoch: 74
表示第74迭代批次完成- 示例2:
Global_step
每200次输出一次 (配置文件中的参数log_interval
)- 示例3:
Global_step
每1000次输出一次(配置文件中的参数eval_interval
),会保存模型到新的文件
以上,我们谈论到了每1000次迭代才会保存一次模型样本,那么,这些样本保存在哪里呢?如何处理这些样本呢?下面我将详细讲述。
.\logs\32k
D_0.pth
D_1000.pth
D_2000.pth
D_3000.pth
D_4000.pth
...
G_0.pth
G_1000.pth
G_2000.pth
G_3000.pth
G_4000.pth
...
按上述方法训练得到最后一次的G和D后,该如何使用这些模型呢?下面我将讲述具体的使用操作方法
.\raw
文件夹inference_main.py
,修改第17-27
行,具体修改内容如下:model_path = "logs/32k/G_10000.pth" # 这里改成你最新训练出来的G模型路径
config_path = "configs/config.json"
svc_model = Svc(model_path, config_path)
infer_tool.mkdir(["raw", "results"])
# 支持多个wav文件,放在raw文件夹下
clean_names = ["vocals_01", "vocals_02","vocals_03"] # 这里修改成你要处理的干声片段的文件名,支持多个文件
trans = [0] # 音高调整,支持正负(半音)
spk_list = ['Sucial'] # 这里是说话人的名字,之前准备训练样本的文件夹名字
slice_db = -40 # 默认-40,嘈杂的音频可以-30,干声保留呼吸可以-50
wav_format = 'wav' # 音频输出格式
#inference_main.py line35 第35行,
wav_path = Path(raw_audio_path).with_suffix('.wav')
#改为
wav_path = str(Path(raw_audio_path).with_suffix('.wav'))
so-vits-svc
文件夹内运行终端,执行下面命令开始推理生成 python .\inference_main.py
.\results
文件夹下
- 以下是对本文档的撰写有帮助的感谢名单:
so-vits-svc 官方源代码和帮助文档
B站up主inifnite_loop 相关视频 相关专栏
所有提供训练音频样本的人员
文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大
文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码
文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版
文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗
文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程
文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0
文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader
文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型
文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写
文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录
文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点
文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文