Spaces:
Running
Running
Update download_model.py
Browse files- download_model.py +100 -103
download_model.py
CHANGED
|
@@ -1,147 +1,135 @@
|
|
| 1 |
from huggingface_hub import list_repo_files, hf_hub_download
|
| 2 |
import os
|
| 3 |
import shutil
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
# Repository ID
|
| 6 |
repo_id = "hexgrad/Kokoro-82M"
|
| 7 |
|
| 8 |
# Set up the cache directory
|
| 9 |
-
cache_dir = "./cache"
|
| 10 |
os.makedirs(cache_dir, exist_ok=True)
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
def get_voice_models():
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
| 15 |
os.makedirs(VOICES_DIR, exist_ok=True)
|
| 16 |
-
# Get the list of all files
|
| 17 |
-
files = list_repo_files(repo_id)
|
| 18 |
|
| 19 |
-
#
|
|
|
|
|
|
|
|
|
|
| 20 |
voice_files = [file.replace("voices/", "") for file in files if file.startswith("voices/")]
|
| 21 |
|
| 22 |
-
# Get current files
|
| 23 |
-
current_voice = os.listdir(
|
| 24 |
|
| 25 |
-
#
|
| 26 |
download_voice = [file for file in voice_files if file not in current_voice]
|
| 27 |
if download_voice:
|
| 28 |
-
print(f"Files to download: {download_voice}")
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
for file in download_voice
|
| 32 |
-
file_path = hf_hub_download(repo_id=repo_id, filename=f"voices/{file}", cache_dir=cache_dir)
|
| 33 |
-
target_path = os.path.join(voices_dir, file)
|
| 34 |
-
shutil.copy(file_path, target_path)
|
| 35 |
-
print(f"Downloaded: {file} to {target_path}")
|
| 36 |
-
|
| 37 |
-
# Call the function to execute the code
|
| 38 |
-
get_voice_models()
|
| 39 |
-
|
| 40 |
-
# Check and download additional required files with caching
|
| 41 |
-
kokoro_file = "kokoro-v0_19.pth"
|
| 42 |
-
fp16_file = "fp16/kokoro-v0_19-half.pth"
|
| 43 |
-
|
| 44 |
-
if kokoro_file not in os.listdir("./KOKORO/"):
|
| 45 |
-
file_path = hf_hub_download(repo_id=repo_id, filename=kokoro_file, cache_dir=cache_dir)
|
| 46 |
-
shutil.copy(file_path, os.path.join("./KOKORO/", kokoro_file))
|
| 47 |
-
print(f"Downloaded: {kokoro_file} to ./KOKORO/")
|
| 48 |
-
|
| 49 |
-
if "fp16" not in os.listdir("./KOKORO/"):
|
| 50 |
-
os.makedirs("./KOKORO/fp16", exist_ok=True)
|
| 51 |
-
|
| 52 |
-
if os.path.basename(fp16_file) not in os.listdir("./KOKORO/fp16/"):
|
| 53 |
-
file_path = hf_hub_download(repo_id=repo_id, filename=fp16_file, cache_dir=cache_dir)
|
| 54 |
-
shutil.copy(file_path, os.path.join("./KOKORO/fp16/", os.path.basename(fp16_file)))
|
| 55 |
-
print(f"Downloaded: {os.path.basename(fp16_file)} to ./KOKORO/fp16/")
|
| 56 |
-
|
| 57 |
-
|
| 58 |
|
|
|
|
|
|
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
import platform
|
| 63 |
|
| 64 |
def setup_batch_file():
|
| 65 |
-
|
|
|
|
| 66 |
if platform.system() == "Windows":
|
| 67 |
-
|
| 68 |
-
if os.path.exists(
|
| 69 |
-
print("'run.bat' already exists in the current folder.")
|
| 70 |
-
else:
|
| 71 |
-
# Content for run_app.bat
|
| 72 |
bat_content_app = '''@echo off
|
| 73 |
call myenv\\Scripts\\activate
|
| 74 |
@python.exe app.py %*
|
| 75 |
@pause
|
| 76 |
'''
|
| 77 |
-
|
| 78 |
-
with open('run_app.bat', 'w') as bat_file:
|
| 79 |
bat_file.write(bat_content_app)
|
| 80 |
-
print("
|
|
|
|
|
|
|
| 81 |
else:
|
| 82 |
-
print("
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
-
def mix_all_voices(folder_path=
|
| 95 |
-
|
| 96 |
# Get the list of available voice packs
|
| 97 |
-
|
| 98 |
os.path.splitext(filename)[0]
|
| 99 |
for filename in os.listdir(folder_path)
|
| 100 |
if filename.endswith('.pt')
|
| 101 |
]
|
| 102 |
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
# # Create the mixed model using a weighted average
|
| 113 |
-
# mixed_voice = (weight_1 * voice_id_1) + (weight_2 * voice_id_2)
|
| 114 |
-
|
| 115 |
-
# # Save the mixed model
|
| 116 |
-
# torch.save(mixed_voice, f'{folder_path}/{new_name}.pt')
|
| 117 |
-
# print(f"Created new voice model: {new_name}")
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
# Function to mix two voices
|
| 122 |
-
def mix_model(voice_1, voice_2):
|
| 123 |
-
"""Mix two voice models and save the new model."""
|
| 124 |
-
new_name = f"{voice_1}_mix_{voice_2}"
|
| 125 |
-
voice_id_1 = torch.load(f'{folder_path}/{voice_1}.pt', weights_only=True)
|
| 126 |
-
voice_id_2 = torch.load(f'{folder_path}/{voice_2}.pt', weights_only=True)
|
| 127 |
|
| 128 |
-
|
| 129 |
-
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
|
| 135 |
# Create mixed voices for each pair
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
# Call the function to mix all voices
|
| 141 |
-
mix_all_voices("./KOKORO/voices")
|
| 142 |
|
| 143 |
-
|
| 144 |
-
def save_voice_names(directory="./KOKORO/voices", output_file="./voice_names.txt"):
|
| 145 |
"""
|
| 146 |
Retrieves voice names from a directory, sorts them by length, and saves to a file.
|
| 147 |
|
|
@@ -168,4 +156,13 @@ def save_voice_names(directory="./KOKORO/voices", output_file="./voice_names.txt
|
|
| 168 |
f.write(f"{voice_name}\n")
|
| 169 |
|
| 170 |
print(f"Voice names saved to {output_file}")
|
| 171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from huggingface_hub import list_repo_files, hf_hub_download
|
| 2 |
import os
|
| 3 |
import shutil
|
| 4 |
+
import torch
|
| 5 |
+
from itertools import combinations
|
| 6 |
+
import platform
|
| 7 |
|
| 8 |
# Repository ID
|
| 9 |
repo_id = "hexgrad/Kokoro-82M"
|
| 10 |
|
| 11 |
# Set up the cache directory
|
| 12 |
+
cache_dir = "./cache"
|
| 13 |
os.makedirs(cache_dir, exist_ok=True)
|
| 14 |
|
| 15 |
+
# Set up the base model paths
|
| 16 |
+
KOKORO_DIR = "./KOKORO"
|
| 17 |
+
VOICES_DIR = os.path.join(KOKORO_DIR, "voices")
|
| 18 |
+
FP16_DIR = os.path.join(KOKORO_DIR, "fp16")
|
| 19 |
+
KOKORO_FILE = "kokoro-v0_19.pth"
|
| 20 |
+
FP16_FILE = "fp16/kokoro-v0_19-half.pth"
|
| 21 |
+
|
| 22 |
+
def download_files(repo_id, filenames, destination_dir, cache_dir):
|
| 23 |
+
# Ensure directories exist
|
| 24 |
+
os.makedirs(destination_dir, exist_ok=True)
|
| 25 |
+
|
| 26 |
+
for filename in filenames:
|
| 27 |
+
destination = os.path.join(destination_dir, os.path.basename(filename))
|
| 28 |
+
if not os.path.exists(destination):
|
| 29 |
+
file_path = hf_hub_download(repo_id=repo_id, filename=filename, cache_dir=cache_dir)
|
| 30 |
+
shutil.copy(file_path, destination)
|
| 31 |
+
print(f"Downloaded and saved: {destination}")
|
| 32 |
+
else:
|
| 33 |
+
print(f"File already exist in: {destination}")
|
| 34 |
+
|
| 35 |
+
|
| 36 |
def get_voice_models():
|
| 37 |
+
"""Downloads missing voice models from the Hugging Face repository."""
|
| 38 |
+
|
| 39 |
+
# Create or empty the 'voices' directory
|
| 40 |
+
if os.path.exists(VOICES_DIR):
|
| 41 |
+
shutil.rmtree(VOICES_DIR)
|
| 42 |
os.makedirs(VOICES_DIR, exist_ok=True)
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
# Get list of files from the repository
|
| 45 |
+
files = list_repo_files(repo_id)
|
| 46 |
+
|
| 47 |
+
# Filter for voice files
|
| 48 |
voice_files = [file.replace("voices/", "") for file in files if file.startswith("voices/")]
|
| 49 |
|
| 50 |
+
# Get current voice files
|
| 51 |
+
current_voice = os.listdir(VOICES_DIR)
|
| 52 |
|
| 53 |
+
# Download new voices
|
| 54 |
download_voice = [file for file in voice_files if file not in current_voice]
|
| 55 |
if download_voice:
|
| 56 |
+
# print(f"Files to download: {download_voice}")
|
| 57 |
+
pass
|
| 58 |
+
|
| 59 |
+
download_files(repo_id, [f"voices/{file}" for file in download_voice], VOICES_DIR, cache_dir)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
+
def download_base_models():
|
| 62 |
+
"""Downloads Kokoro base model and fp16 version if missing."""
|
| 63 |
|
| 64 |
+
download_files(repo_id, [KOKORO_FILE], KOKORO_DIR, cache_dir)
|
| 65 |
+
download_files(repo_id, [FP16_FILE], FP16_DIR, cache_dir)
|
|
|
|
| 66 |
|
| 67 |
def setup_batch_file():
|
| 68 |
+
"""Creates a 'run_app.bat' file for Windows if it doesn't exist."""
|
| 69 |
+
|
| 70 |
if platform.system() == "Windows":
|
| 71 |
+
bat_file_name = 'run_app.bat'
|
| 72 |
+
if not os.path.exists(bat_file_name):
|
|
|
|
|
|
|
|
|
|
| 73 |
bat_content_app = '''@echo off
|
| 74 |
call myenv\\Scripts\\activate
|
| 75 |
@python.exe app.py %*
|
| 76 |
@pause
|
| 77 |
'''
|
| 78 |
+
with open(bat_file_name, 'w') as bat_file:
|
|
|
|
| 79 |
bat_file.write(bat_content_app)
|
| 80 |
+
print(f"Created '{bat_file_name}'.")
|
| 81 |
+
else:
|
| 82 |
+
print(f"'{bat_file_name}' already exists.")
|
| 83 |
else:
|
| 84 |
+
print("Not a Windows system, skipping batch file creation.")
|
| 85 |
+
|
| 86 |
+
def download_ffmpeg():
|
| 87 |
+
"""Downloads ffmpeg and ffprobe executables from Hugging Face."""
|
| 88 |
+
print("For Kokoro TTS we don't need ffmpeg, But for Subtitle Dubbing we need ffmpeg")
|
| 89 |
+
os_name=platform.system()
|
| 90 |
+
if os_name == "Windows":
|
| 91 |
+
repo_id = "fishaudio/fish-speech-1"
|
| 92 |
+
filenames = ["ffmpeg.exe", "ffprobe.exe"]
|
| 93 |
+
ffmpeg_dir = "./ffmpeg"
|
| 94 |
+
download_files(repo_id, filenames, ffmpeg_dir, cache_dir)
|
| 95 |
+
elif os_name == "Linux":
|
| 96 |
+
print("Please install ffmpeg using the package manager for your system.")
|
| 97 |
+
print("'sudo apt install ffmpeg' on Debian/Ubuntu")
|
| 98 |
+
else:
|
| 99 |
+
print(f"Manually install ffmpeg for {os_name} from https://ffmpeg.org/download.html")
|
| 100 |
|
| 101 |
+
def mix_all_voices(folder_path=VOICES_DIR):
|
| 102 |
+
"""Mix all pairs of voice models and save the new models."""
|
| 103 |
# Get the list of available voice packs
|
| 104 |
+
available_voice_pack = [
|
| 105 |
os.path.splitext(filename)[0]
|
| 106 |
for filename in os.listdir(folder_path)
|
| 107 |
if filename.endswith('.pt')
|
| 108 |
]
|
| 109 |
|
| 110 |
+
# Generate all unique pairs of voices
|
| 111 |
+
voice_combinations = combinations(available_voice_pack, 2)
|
| 112 |
+
|
| 113 |
+
# Function to mix two voices
|
| 114 |
+
def mix_model(voice_1, voice_2):
|
| 115 |
+
"""Mix two voice models and save the new model."""
|
| 116 |
+
new_name = f"{voice_1}_mix_{voice_2}"
|
| 117 |
+
voice_id_1 = torch.load(f'{folder_path}/{voice_1}.pt', weights_only=True)
|
| 118 |
+
voice_id_2 = torch.load(f'{folder_path}/{voice_2}.pt', weights_only=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
+
# Create the mixed model by averaging the weights
|
| 121 |
+
mixed_voice = torch.mean(torch.stack([voice_id_1, voice_id_2]), dim=0)
|
| 122 |
|
| 123 |
+
# Save the mixed model
|
| 124 |
+
torch.save(mixed_voice, f'{folder_path}/{new_name}.pt')
|
| 125 |
+
print(f"Created new voice model: {new_name}")
|
| 126 |
|
| 127 |
# Create mixed voices for each pair
|
| 128 |
+
for voice_1, voice_2 in voice_combinations:
|
| 129 |
+
print(f"Mixing {voice_1} ❤️ {voice_2}")
|
| 130 |
+
mix_model(voice_1, voice_2)
|
|
|
|
|
|
|
|
|
|
| 131 |
|
| 132 |
+
def save_voice_names(directory=VOICES_DIR, output_file="./voice_names.txt"):
|
|
|
|
| 133 |
"""
|
| 134 |
Retrieves voice names from a directory, sorts them by length, and saves to a file.
|
| 135 |
|
|
|
|
| 156 |
f.write(f"{voice_name}\n")
|
| 157 |
|
| 158 |
print(f"Voice names saved to {output_file}")
|
| 159 |
+
|
| 160 |
+
# --- Main Execution ---
|
| 161 |
+
if __name__ == "__main__":
|
| 162 |
+
get_voice_models()
|
| 163 |
+
download_base_models()
|
| 164 |
+
setup_batch_file()
|
| 165 |
+
# mix_all_voices()
|
| 166 |
+
save_voice_names()
|
| 167 |
+
download_ffmpeg()
|
| 168 |
+
print("Setup complete!")
|