Files
soprano-factory/generate_dataset.py
T
2026-01-13 07:47:17 -08:00

91 lines
2.6 KiB
Python

"""
Converts a dataset in LJSpeech format into audio tokens that can be used to train/fine-tune Soprano.
This script creates two JSON files for train and test splits in the provided directory.
Usage:
python generate_dataset.py --input-dir path/to/files
Args:
--input-dir: Path to directory of LJSpeech-style dataset. If none is provided this defaults to the provided example dataset.
"""
import argparse
import pathlib
import random
import json
from scipy.io import wavfile
import torchaudio
import torch
from tqdm import tqdm
from huggingface_hub import hf_hub_download
from encoder.codec import Encoder
SAMPLE_RATE = 32000
SEED = 42
VAL_PROP = 0.1
VAL_MAX = 512
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("--input-dir",
required=False,
default="./example_dataset",
type=pathlib.Path
)
return parser.parse_args()
def main():
args = get_args()
input_dir = args.input_dir
print("Loading model.")
encoder = Encoder()
encoder_path = hf_hub_download(repo_id='ekwek/Soprano-Encoder', filename='encoder.pth')
encoder.load_state_dict(torch.load(encoder_path))
print("Model loaded.")
print("Reading metadata.")
files = []
with open(f'{input_dir}/metadata.txt', encoding='utf-8') as f:
data = f.read().split('\n')
for line in data:
filename, transcript = line.split('|', maxsplit=1)
files.append((filename, transcript))
print(f'{len(files)} samples located in directory.')
print("Encoding audio.")
dataset = []
for sample in tqdm(files):
filename, transcript = sample
sr, audio = wavfile.read(f'{input_dir}/wavs/{filename}.wav')
audio = torch.from_numpy(audio)
if sr != SAMPLE_RATE:
audio = torchaudio.functional.resample(audio, sr, SAMPLE_RATE)
audio = audio.unsqueeze(0)
with torch.no_grad():
audio_tokens = encoder(audio)
dataset.append([transcript, audio_tokens.squeeze(0).tolist()])
print("Generating train/test splits.")
random.seed(SEED)
random.shuffle(dataset)
num_val = min(int(VAL_PROP * len(dataset)) + 1, VAL_MAX)
train_dataset = dataset[num_val:]
val_dataset = dataset[:num_val]
print(f'# train samples: {len(train_dataset)}')
print(f'# val samples: {len(val_dataset)}')
print("Saving datasets.")
with open(f'{input_dir}/train.json', 'w', encoding='utf-8') as f:
json.dump(train_dataset, f, indent=2)
with open(f'{input_dir}/val.json', 'w', encoding='utf-8') as f:
json.dump(val_dataset, f, indent=2)
print("Datasets saved.")
if __name__ == '__main__':
main()