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!")
|