Processing the voice-data is quite time consuming, and generating your voice-model from scratch takes a long time. To speed-up the process, Piper-users use a check-point file of an already recorded voice, and process their own recorded audio with that as base. And we’re going to do the same.
Installing the checkpoint file
Change back to the piper1-gpl folder and activate the virtual environment again with the command.\.venv\scripts\activate.ps1
The checkpoint files can be downloaded from the Hugging Face website. I am interested in the medium version northern english male-checkpoint file in en-GB. Open the folder and download the config.json to the dataset folder and store the epoch*.ckpt file in the ckpt-folder
Here we have a slight problem. These check-point files were created with an older version of Torch (2.5.1) and they aren’t compatible with the current version of Torch (2.8.0). With the help of Claude I found a two-step solution (“PyTorch Lightning checkpoints contain hyperparameters that conflict with CLI arguments“)
import torch
import pathlib
import tkinter as tk
from tkinter import filedialog, messagebox
import os
# Monkey-patch PosixPath to work on Windows
class PosixPathWindows(pathlib.WindowsPath):
"""A wrapper to make PosixPath loadable on Windows"""
pass
def convert_paths(obj):
"""Recursively convert Path objects to strings"""
if isinstance(obj, pathlib.Path):
return str(obj)
elif isinstance(obj, dict):
return {k: convert_paths(v) for k, v in obj.items()}
elif isinstance(obj, (list, tuple)):
return type(obj)(convert_paths(item) for item in obj)
return obj
def strip_checkpoint_params(checkpoint):
"""Remove conflicting hyperparameters from checkpoint"""
if 'hyper_parameters' not in checkpoint:
print("\n⚠ No 'hyper_parameters' key found in checkpoint")
return checkpoint
print("\nOriginal hyperparameters:")
for key, value in checkpoint['hyper_parameters'].items():
print(f" {key}: {value}")
# Keep only essential architecture parameters
keep_params = [
'num_symbols', 'num_speakers', 'resblock', 'resblock_kernel_sizes',
'resblock_dilation_sizes', 'upsample_rates', 'upsample_initial_channel',
'upsample_kernel_sizes', 'filter_length', 'hop_length', 'win_length',
'mel_channels', 'mel_fmin', 'mel_fmax', 'inter_channels', 'hidden_channels',
'filter_channels', 'n_heads', 'n_layers', 'kernel_size', 'p_dropout',
'n_layers_q', 'use_spectral_norm', 'gin_channels', 'use_sdp', 'segment_size'
]
keys_to_remove = [key for key in checkpoint['hyper_parameters'].keys()
if key not in keep_params]
removed = []
for key in keys_to_remove:
if key in checkpoint['hyper_parameters']:
del checkpoint['hyper_parameters'][key]
removed.append(key)
if removed:
print(f"\n✓ Removed conflicting parameters: {', '.join(removed)}")
else:
print("\n⚠ No conflicting parameters found to remove")
print("\nRemaining hyperparameters:")
for key, value in checkpoint['hyper_parameters'].items():
print(f" {key}: {value}")
return checkpoint
def process_checkpoint():
"""Main processing function with file/folder pickers"""
# Hide the root window
root = tk.Tk()
root.withdraw()
# Select input checkpoint file
print("Please select the checkpoint file to process...")
input_checkpoint = filedialog.askopenfilename(
title="Select Checkpoint File",
filetypes=[("Checkpoint files", "*.ckpt"), ("All files", "*.*")]
)
if not input_checkpoint:
print("No file selected. Exiting.")
return
# Select output folder
print("Please select the output folder...")
output_folder = filedialog.askdirectory(
title="Select Output Folder"
)
if not output_folder:
print("No output folder selected. Exiting.")
return
# Generate output filename
input_filename = os.path.basename(input_checkpoint)
output_filename = f"processed-{input_filename}"
output_checkpoint = os.path.join(output_folder, output_filename)
temp_checkpoint = os.path.join(output_folder, f"temp-{input_filename}")
print(f"\n{'='*60}")
print(f"Input file: {input_checkpoint}")
print(f"Output file: {output_checkpoint}")
print(f"{'='*60}\n")
# Replace PosixPath with Windows-compatible version
original_posix = pathlib.PosixPath
pathlib.PosixPath = PosixPathWindows
try:
# Step 1: Load and convert checkpoint
print("Step 1: Loading checkpoint...")
checkpoint = torch.load(input_checkpoint, weights_only=False, map_location='cpu')
print("✓ Checkpoint loaded successfully")
print("\nStep 2: Converting path objects to strings...")
checkpoint = convert_paths(checkpoint)
print("✓ Path conversion complete")
# Save temporary converted checkpoint
print(f"\nStep 3: Saving temporary converted checkpoint...")
torch.save(checkpoint, temp_checkpoint)
print("✓ Temporary file saved")
# Step 4: Strip parameters
print("\nStep 4: Stripping conflicting parameters...")
checkpoint = strip_checkpoint_params(checkpoint)
# Restore original PosixPath
pathlib.PosixPath = original_posix
# Step 5: Save final checkpoint
print(f"\nStep 5: Saving final processed checkpoint...")
torch.save(checkpoint, output_checkpoint)
print("✓ Final checkpoint saved successfully!")
# Clean up temporary file
if os.path.exists(temp_checkpoint):
os.remove(temp_checkpoint)
print("✓ Temporary file cleaned up")
print(f"\n{'='*60}")
print("✓ PROCESSING COMPLETE!")
print(f"Your processed checkpoint is ready at:")
print(f"{output_checkpoint}")
print(f"{'='*60}\n")
# Show success message
messagebox.showinfo(
"Success",
f"Checkpoint processed successfully!\n\nOutput saved to:\n{output_checkpoint}"
)
except Exception as e:
print(f"\n✗ Error: {e}")
import traceback
traceback.print_exc()
# Restore original PosixPath even on error
pathlib.PosixPath = original_posix
# Clean up temporary file if it exists
if os.path.exists(temp_checkpoint):
os.remove(temp_checkpoint)
messagebox.showerror("Error", f"An error occurred:\n\n{str(e)}")
finally:
root.destroy()
if __name__ == "__main__":
print("Checkpoint Converter & Stripper")
print("="*60)
process_checkpoint()
Download the file from my Github-page, or copy the above text in textfile-editor and save it as checkpoint_converter.py (whatever name makes sense to you) in the piper1-gpl directory. and run the script from the Powershell commandline python -m checkpoint_converter
. The processing won’t take long.
This script opens a file-picker to select the ckpt-file you downloaded from the Huggingface website, and a folder-picker where you want to store the processed ckpt-file. It will also create a temporary-file since this is a two-step process.
First it will convert the file to make it compatible for newer versions of Torch (> 2.5.1) and second it will strip some parameters from the file which also break the process.
Now let’s get the training started.