CoolFace
Apppublic

pony123/ChatGLM2-Voice-Cloning

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
preprocess.py286 linesDownload Raw Back to speaker_encoder
1from multiprocess.pool import ThreadPool2from speaker_encoder.params_data import *3from speaker_encoder.config import librispeech_datasets, anglophone_nationalites4from datetime import datetime5from speaker_encoder import audio6from pathlib import Path7from tqdm import tqdm8import numpy as np9 10 11class DatasetLog:12    """13    Registers metadata about the dataset in a text file.14    """15    def __init__(self, root, name):16        self.text_file = open(Path(root, "Log_%s.txt" % name.replace("/", "_")), "w")17        self.sample_data = dict()18        19        start_time = str(datetime.now().strftime("%A %d %B %Y at %H:%M"))20        self.write_line("Creating dataset %s on %s" % (name, start_time))21        self.write_line("-----")22        self._log_params()23        24    def _log_params(self):25        from speaker_encoder import params_data26        self.write_line("Parameter values:")27        for param_name in (p for p in dir(params_data) if not p.startswith("__")):28            value = getattr(params_data, param_name)29            self.write_line("\t%s: %s" % (param_name, value))30        self.write_line("-----")31    32    def write_line(self, line):33        self.text_file.write("%s\n" % line)34        35    def add_sample(self, **kwargs):36        for param_name, value in kwargs.items():37            if not param_name in self.sample_data:38                self.sample_data[param_name] = []39            self.sample_data[param_name].append(value)40            41    def finalize(self):42        self.write_line("Statistics:")43        for param_name, values in self.sample_data.items():44            self.write_line("\t%s:" % param_name)45            self.write_line("\t\tmin %.3f, max %.3f" % (np.min(values), np.max(values)))46            self.write_line("\t\tmean %.3f, median %.3f" % (np.mean(values), np.median(values)))47        self.write_line("-----")48        end_time = str(datetime.now().strftime("%A %d %B %Y at %H:%M"))49        self.write_line("Finished on %s" % end_time)50        self.text_file.close()51       52        53def _init_preprocess_dataset(dataset_name, datasets_root, out_dir) -> (Path, DatasetLog):54    dataset_root = datasets_root.joinpath(dataset_name)55    if not dataset_root.exists():56        print("Couldn\'t find %s, skipping this dataset." % dataset_root)57        return None, None58    return dataset_root, DatasetLog(out_dir, dataset_name)59 60 61def _preprocess_speaker_dirs(speaker_dirs, dataset_name, datasets_root, out_dir, extension,62                             skip_existing, logger):63    print("%s: Preprocessing data for %d speakers." % (dataset_name, len(speaker_dirs)))64    65    # Function to preprocess utterances for one speaker66    def preprocess_speaker(speaker_dir: Path):67        # Give a name to the speaker that includes its dataset68        speaker_name = "_".join(speaker_dir.relative_to(datasets_root).parts)69        70        # Create an output directory with that name, as well as a txt file containing a 71        # reference to each source file.72        speaker_out_dir = out_dir.joinpath(speaker_name)73        speaker_out_dir.mkdir(exist_ok=True)74        sources_fpath = speaker_out_dir.joinpath("_sources.txt")75        76        # There's a possibility that the preprocessing was interrupted earlier, check if 77        # there already is a sources file.78        if sources_fpath.exists():79            try:80                with sources_fpath.open("r") as sources_file:81                    existing_fnames = {line.split(",")[0] for line in sources_file}82            except:83                existing_fnames = {}84        else:85            existing_fnames = {}86        87        # Gather all audio files for that speaker recursively88        sources_file = sources_fpath.open("a" if skip_existing else "w")89        for in_fpath in speaker_dir.glob("**/*.%s" % extension):90            # Check if the target output file already exists91            out_fname = "_".join(in_fpath.relative_to(speaker_dir).parts)92            out_fname = out_fname.replace(".%s" % extension, ".npy")93            if skip_existing and out_fname in existing_fnames:94                continue95                96            # Load and preprocess the waveform97            wav = audio.preprocess_wav(in_fpath)98            if len(wav) == 0:99                continue100            101            # Create the mel spectrogram, discard those that are too short102            frames = audio.wav_to_mel_spectrogram(wav)103            if len(frames) < partials_n_frames:104                continue105            106            out_fpath = speaker_out_dir.joinpath(out_fname)107            np.save(out_fpath, frames)108            logger.add_sample(duration=len(wav) / sampling_rate)109            sources_file.write("%s,%s\n" % (out_fname, in_fpath))110        111        sources_file.close()112    113    # Process the utterances for each speaker114    with ThreadPool(8) as pool:115        list(tqdm(pool.imap(preprocess_speaker, speaker_dirs), dataset_name, len(speaker_dirs),116                  unit="speakers"))117    logger.finalize()118    print("Done preprocessing %s.\n" % dataset_name)119 120 121# Function to preprocess utterances for one speaker122def __preprocess_speaker(speaker_dir: Path, datasets_root: Path, out_dir: Path, extension: str, skip_existing: bool):123        # Give a name to the speaker that includes its dataset124        speaker_name = "_".join(speaker_dir.relative_to(datasets_root).parts)125        126        # Create an output directory with that name, as well as a txt file containing a 127        # reference to each source file.128        speaker_out_dir = out_dir.joinpath(speaker_name)129        speaker_out_dir.mkdir(exist_ok=True)130        sources_fpath = speaker_out_dir.joinpath("_sources.txt")131        132        # There's a possibility that the preprocessing was interrupted earlier, check if 133        # there already is a sources file.134        # if sources_fpath.exists():135        #     try:136        #         with sources_fpath.open("r") as sources_file:137        #             existing_fnames = {line.split(",")[0] for line in sources_file}138        #     except:139        #         existing_fnames = {}140        # else:141        #     existing_fnames = {}142        existing_fnames = {}143        # Gather all audio files for that speaker recursively144        sources_file = sources_fpath.open("a" if skip_existing else "w")145 146        for in_fpath in speaker_dir.glob("**/*.%s" % extension):147            # Check if the target output file already exists148            out_fname = "_".join(in_fpath.relative_to(speaker_dir).parts)149            out_fname = out_fname.replace(".%s" % extension, ".npy")150            if skip_existing and out_fname in existing_fnames:151                continue152                153            # Load and preprocess the waveform154            wav = audio.preprocess_wav(in_fpath)155            if len(wav) == 0:156                continue157            158            # Create the mel spectrogram, discard those that are too short159            frames = audio.wav_to_mel_spectrogram(wav)160            if len(frames) < partials_n_frames:161                continue162            163            out_fpath = speaker_out_dir.joinpath(out_fname)164            np.save(out_fpath, frames)165            # logger.add_sample(duration=len(wav) / sampling_rate)166            sources_file.write("%s,%s\n" % (out_fname, in_fpath))167        168        sources_file.close()169        return len(wav)170 171def _preprocess_speaker_dirs_vox2(speaker_dirs, dataset_name, datasets_root, out_dir, extension,172                             skip_existing, logger):173    # from multiprocessing import Pool, cpu_count174    from pathos.multiprocessing import ProcessingPool as Pool175    # Function to preprocess utterances for one speaker176    def __preprocess_speaker(speaker_dir: Path):177        # Give a name to the speaker that includes its dataset178        speaker_name = "_".join(speaker_dir.relative_to(datasets_root).parts)179        180        # Create an output directory with that name, as well as a txt file containing a 181        # reference to each source file.182        speaker_out_dir = out_dir.joinpath(speaker_name)183        speaker_out_dir.mkdir(exist_ok=True)184        sources_fpath = speaker_out_dir.joinpath("_sources.txt")185        186        existing_fnames = {}187        # Gather all audio files for that speaker recursively188        sources_file = sources_fpath.open("a" if skip_existing else "w")189        wav_lens = []190        for in_fpath in speaker_dir.glob("**/*.%s" % extension):191            # Check if the target output file already exists192            out_fname = "_".join(in_fpath.relative_to(speaker_dir).parts)193            out_fname = out_fname.replace(".%s" % extension, ".npy")194            if skip_existing and out_fname in existing_fnames:195                continue196                197            # Load and preprocess the waveform198            wav = audio.preprocess_wav(in_fpath)199            if len(wav) == 0:200                continue201            202            # Create the mel spectrogram, discard those that are too short203            frames = audio.wav_to_mel_spectrogram(wav)204            if len(frames) < partials_n_frames:205                continue206            207            out_fpath = speaker_out_dir.joinpath(out_fname)208            np.save(out_fpath, frames)209            # logger.add_sample(duration=len(wav) / sampling_rate)210            sources_file.write("%s,%s\n" % (out_fname, in_fpath))211            wav_lens.append(len(wav))212        sources_file.close()213        return wav_lens214 215    print("%s: Preprocessing data for %d speakers." % (dataset_name, len(speaker_dirs)))216    # Process the utterances for each speaker217    # with ThreadPool(8) as pool:218    #     list(tqdm(pool.imap(preprocess_speaker, speaker_dirs), dataset_name, len(speaker_dirs),219    #               unit="speakers"))220    pool = Pool(processes=20)221    for i, wav_lens in enumerate(pool.map(__preprocess_speaker, speaker_dirs), 1):222        for wav_len in wav_lens:223            logger.add_sample(duration=wav_len / sampling_rate)224        print(f'{i}/{len(speaker_dirs)} \r')225 226    logger.finalize()227    print("Done preprocessing %s.\n" % dataset_name)228 229 230def preprocess_librispeech(datasets_root: Path, out_dir: Path, skip_existing=False):231    for dataset_name in librispeech_datasets["train"]["other"]:232        # Initialize the preprocessing233        dataset_root, logger = _init_preprocess_dataset(dataset_name, datasets_root, out_dir)234        if not dataset_root:235            return 236        237        # Preprocess all speakers238        speaker_dirs = list(dataset_root.glob("*"))239        _preprocess_speaker_dirs(speaker_dirs, dataset_name, datasets_root, out_dir, "flac",240                                 skip_existing, logger)241 242 243def preprocess_voxceleb1(datasets_root: Path, out_dir: Path, skip_existing=False):244    # Initialize the preprocessing245    dataset_name = "VoxCeleb1"246    dataset_root, logger = _init_preprocess_dataset(dataset_name, datasets_root, out_dir)247    if not dataset_root:248        return249 250    # Get the contents of the meta file251    with dataset_root.joinpath("vox1_meta.csv").open("r") as metafile:252        metadata = [line.split("\t") for line in metafile][1:]253    254    # Select the ID and the nationality, filter out non-anglophone speakers255    nationalities = {line[0]: line[3] for line in metadata}256    # keep_speaker_ids = [speaker_id for speaker_id, nationality in nationalities.items() if 257    #                     nationality.lower() in anglophone_nationalites]258    keep_speaker_ids = [speaker_id for speaker_id, nationality in nationalities.items()]                        259    print("VoxCeleb1: using samples from %d (presumed anglophone) speakers out of %d." % 260          (len(keep_speaker_ids), len(nationalities)))261    262    # Get the speaker directories for anglophone speakers only263    speaker_dirs = dataset_root.joinpath("wav").glob("*")264    speaker_dirs = [speaker_dir for speaker_dir in speaker_dirs if265                    speaker_dir.name in keep_speaker_ids]266    print("VoxCeleb1: found %d anglophone speakers on the disk, %d missing (this is normal)." % 267          (len(speaker_dirs), len(keep_speaker_ids) - len(speaker_dirs)))268 269    # Preprocess all speakers270    _preprocess_speaker_dirs(speaker_dirs, dataset_name, datasets_root, out_dir, "wav",271                             skip_existing, logger)272 273 274def preprocess_voxceleb2(datasets_root: Path, out_dir: Path, skip_existing=False):275    # Initialize the preprocessing276    dataset_name = "VoxCeleb2"277    dataset_root, logger = _init_preprocess_dataset(dataset_name, datasets_root, out_dir)278    if not dataset_root:279        return280    281    # Get the speaker directories282    # Preprocess all speakers283    speaker_dirs = list(dataset_root.joinpath("dev", "aac").glob("*"))284    _preprocess_speaker_dirs_vox2(speaker_dirs, dataset_name, datasets_root, out_dir, "m4a",285                             skip_existing, logger)286