before changes
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
|
||||
import torch
|
||||
|
||||
# load coqui-ai/trainer libraries
|
||||
from trainer import Trainer, TrainerArgs
|
||||
|
||||
# load coqui-ai/TTS libraries
|
||||
from TTS.tts.configs.shared_configs import BaseDatasetConfig
|
||||
from TTS.tts.configs.vits_config import VitsConfig
|
||||
from TTS.tts.datasets import load_tts_samples
|
||||
from TTS.tts.models.vits import Vits, VitsArgs, VitsAudioConfig
|
||||
|
||||
|
||||
#
|
||||
# parse command line arguments
|
||||
#
|
||||
def parse_cmdline_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description = "Code to clone a voice from a given set of voice samples and a multi-speaker baseline model")
|
||||
parser.add_argument("--baseline_model_path", type = str, required = True,
|
||||
help = "Path to multi-speaker baseline model (VITS model)")
|
||||
parser.add_argument("--speaker_dataset_path", type = str, required = True,
|
||||
help = "Path to voice cloning dataset")
|
||||
parser.add_argument("--speaker_embeddings_path", type = str, required = True,
|
||||
help = "Path to speaker's embeddings file")
|
||||
parser.add_argument("--output_path", type = str, default = "results/cloned-voices",
|
||||
help = "Path to store trained / generated assets")
|
||||
parser.add_argument("--batch_size", type = int, default = 96, # 96 is suitable for AWS g5 instances
|
||||
help = "Batch size for training run")
|
||||
parser.add_argument("--max_epochs", type = int, default = 200, # 200 for batch_size 96 (with the 22.050 sampling rate multi-speaker model
|
||||
help = "Maximum number of epochs for training run") # 2000 for batch_size 64 and 1500 for batch_size 96 (with the initial 16k sampling rate VCTK 0.80 model)
|
||||
parser.add_argument("--use_cpu", default = False, action = "store_true", # untested!!!
|
||||
help = "Signal that CPU should be used even if a CUDA-device is available")
|
||||
parser.add_argument("--output_format", type = str, choices = ["txt", "json"], default = "txt",
|
||||
help = "Output format; available choices include 'txt' for human readible text and 'json' for JSON formatting")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
#
|
||||
# main training method (voice cloning)
|
||||
#
|
||||
def main(args):
|
||||
if args.output_format == "txt":
|
||||
print("Commencing training of a new multi-speaker potion-voice baseline model:")
|
||||
print("")
|
||||
print(" + Baseline multi-speaker model path: {}" . format(args.baseline_model_path))
|
||||
print(" + Voice training dataset path : {}" . format(args.speaker_dataset_path))
|
||||
print(" + Speaker embeddings path : {}" . format(args.speaker_embeddings_path))
|
||||
print(" + Output path : {}" . format(args.output_path))
|
||||
print(" + Batch size : {}" . format(args.batch_size))
|
||||
print(" + Training runs (max epochs) : {}" . format(args.max_epochs))
|
||||
print("")
|
||||
|
||||
# determine whether CUDA support is available and set device parameters accordingly
|
||||
use_cuda = torch.cuda.is_available()
|
||||
if args.output_format == "txt":
|
||||
print(" + CUDA availability : {}" . format(use_cuda))
|
||||
|
||||
if args.use_cpu:
|
||||
device = "cpu"
|
||||
device_torch = False
|
||||
elif use_cuda:
|
||||
device = "cuda"
|
||||
device_torch = torch.device("cuda")
|
||||
else:
|
||||
device = "cpu"
|
||||
device_torch = False
|
||||
if args.output_format == "txt":
|
||||
print(" + Compute device used : {}" . format(device))
|
||||
print("")
|
||||
|
||||
# define training data set
|
||||
dataset_config = BaseDatasetConfig(formatter = "vctk_old", language = "en-us", path = args.speaker_dataset_path)
|
||||
|
||||
# set VITS training parameters
|
||||
audio_config = VitsAudioConfig(
|
||||
sample_rate = 22050,
|
||||
win_length = 1024,
|
||||
hop_length = 256,
|
||||
num_mels = 80,
|
||||
mel_fmin = 0,
|
||||
mel_fmax = None,
|
||||
)
|
||||
|
||||
vitsArgs = VitsArgs(
|
||||
use_speaker_embedding = False,
|
||||
use_d_vector_file = True,
|
||||
d_vector_file = [args.speaker_embeddings_path],
|
||||
d_vector_dim = 512,
|
||||
num_layers_text_encoder = 10
|
||||
)
|
||||
|
||||
config = VitsConfig(
|
||||
model_args = vitsArgs,
|
||||
audio = audio_config,
|
||||
run_name = "vits_potion_clone",
|
||||
use_speaker_embedding = False,
|
||||
use_d_vector_file = True,
|
||||
d_vector_file = [args.speaker_embeddings_path],
|
||||
d_vector_dim = 512,
|
||||
batch_size = args.batch_size,
|
||||
eval_batch_size = 8,
|
||||
batch_group_size = 0, # changing this to 5 (VITS training default) slows training down, but doesn't have any positive training effects
|
||||
num_loader_workers = 4,
|
||||
num_eval_loader_workers = 4,
|
||||
run_eval = True,
|
||||
eval_split_size = 2, # fix size of eval dataset (default 1% approach requires at least 100 voice samples!)
|
||||
test_delay_epochs = -1,
|
||||
epochs = args.max_epochs,
|
||||
text_cleaner = "english_cleaners",
|
||||
use_phonemes = False,
|
||||
phoneme_language = "en-us",
|
||||
phoneme_cache_path = os.path.join(args.output_path, "phoneme_cache"),
|
||||
compute_input_seq_cache = True,
|
||||
print_step = 50,
|
||||
print_eval = True,
|
||||
mixed_precision = True,
|
||||
max_text_len = 325,
|
||||
output_path = args.output_path,
|
||||
|
||||
save_checkpoints = True,
|
||||
save_step = 200,
|
||||
|
||||
datasets = [dataset_config],
|
||||
cudnn_benchmark = False,
|
||||
#characters = {
|
||||
# "pad": "_",
|
||||
# "eos": "&",
|
||||
# "bos": "*",
|
||||
# "characters": "!¡'(),-.:;¿?abcdefghijklmnopqrstuvwxyz «°±µ»$%&‘’‚“`”„",
|
||||
# "punctuations": "!¡'(),-.:;¿? ",
|
||||
# "phonemes": None,
|
||||
# "unique": True
|
||||
#},
|
||||
test_sentences = [
|
||||
["It took me quite a long time to develop a voice, and now that I have it I'm not going to be silent."],
|
||||
["Be a voice, not an echo."],
|
||||
["I'm sorry Dave. I'm afraid I can't do that."],
|
||||
["This cake is great. It's so delicious and moist."],
|
||||
["Prior to November 22, 1963."],
|
||||
["Hey! Sandra."],
|
||||
["Hey! Andrew."],
|
||||
["Hey, Michelle."],
|
||||
["Hey! George."],
|
||||
["Hey there, Rachel."]
|
||||
]
|
||||
)
|
||||
|
||||
# load training samples
|
||||
train_samples, eval_samples = load_tts_samples(config.datasets, eval_split = True, eval_split_max_size = config.eval_split_max_size, eval_split_size = config.eval_split_size)
|
||||
|
||||
# init VITS model
|
||||
model = Vits.init_from_config(config)
|
||||
|
||||
# init voice cloning
|
||||
trainer = Trainer(
|
||||
TrainerArgs(restore_path = args.baseline_model_path, use_ddp = False),
|
||||
config,
|
||||
args.output_path,
|
||||
model = model,
|
||||
train_samples = train_samples,
|
||||
eval_samples = eval_samples
|
||||
)
|
||||
|
||||
# trigger voice cloning (aka single speaker training)
|
||||
try:
|
||||
trainer.fit()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
print("Training stopped manually (via keyboard interrupt)! Bye.")
|
||||
exit(0)
|
||||
|
||||
# determine required adjustment for speech synthesizing (i.e., the scaling factor for the duration predictor)
|
||||
# take the duration of the test sentence and calculate the difference to corresponding reference samples
|
||||
# set config.model_args["length_scale"] accordingly and save the updated config asset
|
||||
|
||||
# exit gracefully
|
||||
if args.output_format == "txt":
|
||||
print("")
|
||||
print("Completed voice cloning. The resulting model(s) can be found at:")
|
||||
print(" --> {}" . format(args.output_path))
|
||||
print("")
|
||||
print("Done; bye.")
|
||||
print("")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# parse command line arguments
|
||||
args = parse_cmdline_args()
|
||||
|
||||
# clear command line arguments to avoid triggering argparse features part of Trainer / coqpit imports
|
||||
# Traceback (most recent call last):
|
||||
# File "train_multispeaker_baseline_model.py", line 208, in <module>
|
||||
# main(args)
|
||||
# File "train_multispeaker_baseline_model.py", line 177, in main
|
||||
# trainer = Trainer(
|
||||
# File "/home/ubuntu/dev/potion-voice_venv/lib/python3.8/site-packages/trainer/trainer.py", line 360, in __init__
|
||||
# config, new_fields = self.init_training(args, coqpit_overrides, config)
|
||||
# File "/home/ubuntu/dev/potion-voice_venv/lib/python3.8/site-packages/trainer/trainer.py", line 594, in init_training
|
||||
# config.parse_known_args(coqpit_overrides, relaxed_parser=True)
|
||||
# File "/home/ubuntu/dev/potion-voice_venv/lib/python3.8/site-packages/coqpit/coqpit.py", line 843, in parse_known_args
|
||||
# parser = self.init_argparse(arg_prefix=arg_prefix, relaxed_parser=relaxed_parser)
|
||||
# File "/home/ubuntu/dev/potion-voice_venv/lib/python3.8/site-packages/coqpit/coqpit.py", line 881, in init_argparse
|
||||
# _init_argparse(
|
||||
# File "/home/ubuntu/dev/potion-voice_venv/lib/python3.8/site-packages/coqpit/coqpit.py", line 529, in _init_argparse
|
||||
# parser = _init_argparse(
|
||||
# File "/home/ubuntu/dev/potion-voice_venv/lib/python3.8/site-packages/coqpit/coqpit.py", line 550, in _init_argparse
|
||||
# return default.init_argparse(
|
||||
# AttributeError: 'str' object has no attribute 'init_argparse'
|
||||
sys.argv = [sys.argv[0]]
|
||||
|
||||
# ensure the output path exists
|
||||
os.makedirs(args.output_path, exist_ok = True)
|
||||
|
||||
main(args)
|
||||
|
||||
|
||||
### USAGE:
|
||||
### $ python3 TTS/TTS/bin/resample.py --input_dir voice_dataset_path/person_82/wav48/1 --output_sr 16000
|
||||
### $ python3 clone_voice.py [with argument]
|
||||
Reference in New Issue
Block a user