Adam3 commited on
Commit
d7ef198
·
verified ·
1 Parent(s): 310ee88

Upload 8 files

Browse files
Files changed (7) hide show
  1. analyzer.py +76 -0
  2. gdown.py +354 -0
  3. launch_tensorboard.py +21 -0
  4. model_download.py +385 -0
  5. prerequisites.py +114 -0
  6. pretrained_selector.py +63 -0
  7. split_audio.py +56 -0
analyzer.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import librosa.display
4
+ import librosa
5
+
6
+
7
+ def calculate_features(y, sr):
8
+ stft = np.abs(librosa.stft(y))
9
+ duration = librosa.get_duration(y=y, sr=sr)
10
+ cent = librosa.feature.spectral_centroid(S=stft, sr=sr)[0]
11
+ bw = librosa.feature.spectral_bandwidth(S=stft, sr=sr)[0]
12
+ rolloff = librosa.feature.spectral_rolloff(S=stft, sr=sr)[0]
13
+ return stft, duration, cent, bw, rolloff
14
+
15
+
16
+ def plot_title(title):
17
+ plt.suptitle(title, fontsize=16, fontweight="bold")
18
+
19
+
20
+ def plot_spectrogram(y, sr, stft, duration, cmap="inferno"):
21
+ plt.subplot(3, 1, 1)
22
+ plt.imshow(
23
+ librosa.amplitude_to_db(stft, ref=np.max),
24
+ origin="lower",
25
+ extent=[0, duration, 0, sr / 1000],
26
+ aspect="auto",
27
+ cmap=cmap, # Change the colormap here
28
+ )
29
+ plt.colorbar(format="%+2.0f dB")
30
+ plt.xlabel("Time (s)")
31
+ plt.ylabel("Frequency (kHz)")
32
+ plt.title("Spectrogram")
33
+
34
+
35
+ def plot_waveform(y, sr, duration):
36
+ plt.subplot(3, 1, 2)
37
+ librosa.display.waveshow(y, sr=sr)
38
+ plt.xlabel("Time (s)")
39
+ plt.ylabel("Amplitude")
40
+ plt.title("Waveform")
41
+
42
+
43
+ def plot_features(times, cent, bw, rolloff, duration):
44
+ plt.subplot(3, 1, 3)
45
+ plt.plot(times, cent, label="Spectral Centroid (kHz)", color="b")
46
+ plt.plot(times, bw, label="Spectral Bandwidth (kHz)", color="g")
47
+ plt.plot(times, rolloff, label="Spectral Rolloff (kHz)", color="r")
48
+ plt.xlabel("Time (s)")
49
+ plt.title("Spectral Features")
50
+ plt.legend()
51
+
52
+
53
+ def analyze_audio(audio_file, save_plot_path="logs/audio_analysis.png"):
54
+ y, sr = librosa.load(audio_file)
55
+ stft, duration, cent, bw, rolloff = calculate_features(y, sr)
56
+
57
+ plt.figure(figsize=(12, 10))
58
+
59
+ plot_title("Audio Analysis" + " - " + audio_file.split("/")[-1])
60
+ plot_spectrogram(y, sr, stft, duration)
61
+ plot_waveform(y, sr, duration)
62
+ plot_features(librosa.times_like(cent), cent, bw, rolloff, duration)
63
+
64
+ plt.tight_layout()
65
+
66
+ if save_plot_path:
67
+ plt.savefig(save_plot_path, bbox_inches="tight", dpi=300)
68
+ plt.close()
69
+
70
+ audio_info = f"""Sample Rate: {sr}\nDuration: {(
71
+ str(round(duration, 2)) + " seconds"
72
+ if duration < 60
73
+ else str(round(duration / 60, 2)) + " minutes"
74
+ )}\nNumber of Samples: {len(y)}\nBits per Sample: {librosa.get_samplerate(audio_file)}\nChannels: {"Mono (1)" if y.ndim == 1 else "Stereo (2)"}"""
75
+
76
+ return audio_info, save_plot_path
gdown.py ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import six
4
+ import sys
5
+ import json
6
+ import tqdm
7
+ import time
8
+ import shutil
9
+ import warnings
10
+ import tempfile
11
+ import textwrap
12
+ import requests
13
+ from six.moves import urllib_parse
14
+
15
+
16
+ def indent(text, prefix):
17
+ """Indent each non-empty line of text with the given prefix."""
18
+ return "".join(
19
+ (prefix + line if line.strip() else line) for line in text.splitlines(True)
20
+ )
21
+
22
+
23
+ class FileURLRetrievalError(Exception):
24
+ pass
25
+
26
+
27
+ class FolderContentsMaximumLimitError(Exception):
28
+ pass
29
+
30
+
31
+ def parse_url(url, warning=True):
32
+ """Parse URLs especially for Google Drive links.
33
+
34
+ Args:
35
+ url: URL to parse.
36
+ warning: Whether to warn if the URL is not a download link.
37
+
38
+ Returns:
39
+ A tuple (file_id, is_download_link), where file_id is the ID of the
40
+ file on Google Drive, and is_download_link is a flag indicating
41
+ whether the URL is a download link.
42
+ """
43
+ parsed = urllib_parse.urlparse(url)
44
+ query = urllib_parse.parse_qs(parsed.query)
45
+ is_gdrive = parsed.hostname in ("drive.google.com", "docs.google.com")
46
+ is_download_link = parsed.path.endswith("/uc")
47
+
48
+ if not is_gdrive:
49
+ return None, is_download_link
50
+
51
+ file_id = query.get("id", [None])[0]
52
+ if file_id is None:
53
+ for pattern in (
54
+ r"^/file/d/(.*?)/(edit|view)$",
55
+ r"^/file/u/[0-9]+/d/(.*?)/(edit|view)$",
56
+ r"^/document/d/(.*?)/(edit|htmlview|view)$",
57
+ r"^/document/u/[0-9]+/d/(.*?)/(edit|htmlview|view)$",
58
+ r"^/presentation/d/(.*?)/(edit|htmlview|view)$",
59
+ r"^/presentation/u/[0-9]+/d/(.*?)/(edit|htmlview|view)$",
60
+ r"^/spreadsheets/d/(.*?)/(edit|htmlview|view)$",
61
+ r"^/spreadsheets/u/[0-9]+/d/(.*?)/(edit|htmlview|view)$",
62
+ ):
63
+ match = re.match(pattern, parsed.path)
64
+ if match:
65
+ file_id = match.group(1)
66
+ break
67
+
68
+ if warning and not is_download_link:
69
+ warnings.warn(
70
+ "You specified a Google Drive link that is not the correct link "
71
+ "to download a file. You might want to try `--fuzzy` option "
72
+ f"or the following url: https://drive.google.com/uc?id={file_id}"
73
+ )
74
+
75
+ return file_id, is_download_link
76
+
77
+
78
+ CHUNK_SIZE = 512 * 1024 # 512KB
79
+ HOME = os.path.expanduser("~")
80
+
81
+
82
+ def get_url_from_gdrive_confirmation(contents):
83
+ """Extract the download URL from a Google Drive confirmation page."""
84
+ for pattern in (
85
+ r'href="(\/uc\?export=download[^"]+)',
86
+ r'href="/open\?id=([^"]+)"',
87
+ r'"downloadUrl":"([^"]+)',
88
+ ):
89
+ match = re.search(pattern, contents)
90
+ if match:
91
+ url = match.group(1)
92
+ if pattern == r'href="/open\?id=([^"]+)"':
93
+ uuid = re.search(
94
+ r'<input\s+type="hidden"\s+name="uuid"\s+value="([^"]+)"',
95
+ contents,
96
+ ).group(1)
97
+ url = (
98
+ "https://drive.usercontent.google.com/download?id="
99
+ + url
100
+ + "&confirm=t&uuid="
101
+ + uuid
102
+ )
103
+ elif pattern == r'"downloadUrl":"([^"]+)':
104
+ url = url.replace("\\u003d", "=").replace("\\u0026", "&")
105
+ else:
106
+ url = "https://docs.google.com" + url.replace("&", "&")
107
+ return url
108
+
109
+ match = re.search(r'<p class="uc-error-subcaption">(.*)</p>', contents)
110
+ if match:
111
+ error = match.group(1)
112
+ raise FileURLRetrievalError(error)
113
+
114
+ raise FileURLRetrievalError(
115
+ "Cannot retrieve the public link of the file. "
116
+ "You may need to change the permission to "
117
+ "'Anyone with the link', or have had many accesses."
118
+ )
119
+
120
+
121
+ def _get_session(proxy, use_cookies, return_cookies_file=False):
122
+ """Create a requests session with optional proxy and cookie handling."""
123
+ sess = requests.session()
124
+ sess.headers.update(
125
+ {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)"}
126
+ )
127
+
128
+ if proxy is not None:
129
+ sess.proxies = {"http": proxy, "https": proxy}
130
+ print("Using proxy:", proxy, file=sys.stderr)
131
+
132
+ cookies_file = os.path.join(HOME, ".cache/gdown/cookies.json")
133
+ if os.path.exists(cookies_file) and use_cookies:
134
+ with open(cookies_file) as f:
135
+ cookies = json.load(f)
136
+ for k, v in cookies:
137
+ sess.cookies[k] = v
138
+
139
+ return (sess, cookies_file) if return_cookies_file else sess
140
+
141
+
142
+ def download(
143
+ url=None,
144
+ output=None,
145
+ quiet=False,
146
+ proxy=None,
147
+ speed=None,
148
+ use_cookies=True,
149
+ verify=True,
150
+ id=None,
151
+ fuzzy=True,
152
+ resume=False,
153
+ format=None,
154
+ ):
155
+ """Download file from URL.
156
+
157
+ Parameters
158
+ ----------
159
+ url: str
160
+ URL. Google Drive URL is also supported.
161
+ output: str
162
+ Output filename. Default is basename of URL.
163
+ quiet: bool
164
+ Suppress terminal output. Default is False.
165
+ proxy: str
166
+ Proxy.
167
+ speed: float
168
+ Download byte size per second (e.g., 256KB/s = 256 * 1024).
169
+ use_cookies: bool
170
+ Flag to use cookies. Default is True.
171
+ verify: bool or string
172
+ Either a bool, in which case it controls whether the server's TLS
173
+ certificate is verified, or a string, in which case it must be a path
174
+ to a CA bundle to use. Default is True.
175
+ id: str
176
+ Google Drive's file ID.
177
+ fuzzy: bool
178
+ Fuzzy extraction of Google Drive's file Id. Default is False.
179
+ resume: bool
180
+ Resume the download from existing tmp file if possible.
181
+ Default is False.
182
+ format: str, optional
183
+ Format of Google Docs, Spreadsheets and Slides. Default is:
184
+ - Google Docs: 'docx'
185
+ - Google Spreadsheet: 'xlsx'
186
+ - Google Slides: 'pptx'
187
+
188
+ Returns
189
+ -------
190
+ output: str
191
+ Output filename.
192
+ """
193
+ if not (id is None) ^ (url is None):
194
+ raise ValueError("Either url or id has to be specified")
195
+ if id is not None:
196
+ url = f"https://drive.google.com/uc?id={id}"
197
+
198
+ url_origin = url
199
+
200
+ sess, cookies_file = _get_session(
201
+ proxy=proxy, use_cookies=use_cookies, return_cookies_file=True
202
+ )
203
+
204
+ gdrive_file_id, is_gdrive_download_link = parse_url(url, warning=not fuzzy)
205
+
206
+ if fuzzy and gdrive_file_id:
207
+ # overwrite the url with fuzzy match of a file id
208
+ url = f"https://drive.google.com/uc?id={gdrive_file_id}"
209
+ url_origin = url
210
+ is_gdrive_download_link = True
211
+
212
+ while True:
213
+ res = sess.get(url, stream=True, verify=verify)
214
+
215
+ if url == url_origin and res.status_code == 500:
216
+ # The file could be Google Docs or Spreadsheets.
217
+ url = f"https://drive.google.com/open?id={gdrive_file_id}"
218
+ continue
219
+
220
+ if res.headers["Content-Type"].startswith("text/html"):
221
+ title = re.search("<title>(.+)</title>", res.text)
222
+ if title:
223
+ title = title.group(1)
224
+ if title.endswith(" - Google Docs"):
225
+ url = f"https://docs.google.com/document/d/{gdrive_file_id}/export?format={'docx' if format is None else format}"
226
+ continue
227
+ if title.endswith(" - Google Sheets"):
228
+ url = f"https://docs.google.com/spreadsheets/d/{gdrive_file_id}/export?format={'xlsx' if format is None else format}"
229
+ continue
230
+ if title.endswith(" - Google Slides"):
231
+ url = f"https://docs.google.com/presentation/d/{gdrive_file_id}/export?format={'pptx' if format is None else format}"
232
+ continue
233
+ elif (
234
+ "Content-Disposition" in res.headers
235
+ and res.headers["Content-Disposition"].endswith("pptx")
236
+ and format not in (None, "pptx")
237
+ ):
238
+ url = f"https://docs.google.com/presentation/d/{gdrive_file_id}/export?format={'pptx' if format is None else format}"
239
+ continue
240
+
241
+ if use_cookies:
242
+ os.makedirs(os.path.dirname(cookies_file), exist_ok=True)
243
+ with open(cookies_file, "w") as f:
244
+ cookies = [
245
+ (k, v)
246
+ for k, v in sess.cookies.items()
247
+ if not k.startswith("download_warning_")
248
+ ]
249
+ json.dump(cookies, f, indent=2)
250
+
251
+ if "Content-Disposition" in res.headers:
252
+ # This is the file
253
+ break
254
+ if not (gdrive_file_id and is_gdrive_download_link):
255
+ break
256
+
257
+ # Need to redirect with confirmation
258
+ try:
259
+ url = get_url_from_gdrive_confirmation(res.text)
260
+ except FileURLRetrievalError as e:
261
+ message = (
262
+ "Failed to retrieve file url:\n\n"
263
+ "{}\n\n"
264
+ "You may still be able to access the file from the browser:"
265
+ f"\n\n\t{url_origin}\n\n"
266
+ "but Gdown can't. Please check connections and permissions."
267
+ ).format(indent("\n".join(textwrap.wrap(str(e))), prefix="\t"))
268
+ raise FileURLRetrievalError(message)
269
+
270
+ if gdrive_file_id and is_gdrive_download_link:
271
+ content_disposition = urllib_parse.unquote(res.headers["Content-Disposition"])
272
+ filename_from_url = (
273
+ re.search(r"filename\*=UTF-8''(.*)", content_disposition)
274
+ or re.search(r'filename=["\']?(.*?)["\']?$', content_disposition)
275
+ ).group(1)
276
+ filename_from_url = filename_from_url.replace(os.path.sep, "_")
277
+ else:
278
+ filename_from_url = os.path.basename(url)
279
+
280
+ output = output or filename_from_url
281
+
282
+ output_is_path = isinstance(output, six.string_types)
283
+ if output_is_path and output.endswith(os.path.sep):
284
+ os.makedirs(output, exist_ok=True)
285
+ output = os.path.join(output, filename_from_url)
286
+
287
+ if output_is_path:
288
+ temp_dir = os.path.dirname(output) or "."
289
+ prefix = os.path.basename(output)
290
+ existing_tmp_files = [
291
+ os.path.join(temp_dir, file)
292
+ for file in os.listdir(temp_dir)
293
+ if file.startswith(prefix)
294
+ ]
295
+ if resume and existing_tmp_files:
296
+ if len(existing_tmp_files) > 1:
297
+ print(
298
+ "There are multiple temporary files to resume:",
299
+ file=sys.stderr,
300
+ )
301
+ for file in existing_tmp_files:
302
+ print(f"\t{file}", file=sys.stderr)
303
+ print(
304
+ "Please remove them except one to resume downloading.",
305
+ file=sys.stderr,
306
+ )
307
+ return
308
+ tmp_file = existing_tmp_files[0]
309
+ else:
310
+ resume = False
311
+ tmp_file = tempfile.mktemp(
312
+ suffix=tempfile.template, prefix=prefix, dir=temp_dir
313
+ )
314
+ f = open(tmp_file, "ab")
315
+ else:
316
+ tmp_file = None
317
+ f = output
318
+
319
+ if tmp_file is not None and f.tell() != 0:
320
+ headers = {"Range": f"bytes={f.tell()}-"}
321
+ res = sess.get(url, headers=headers, stream=True, verify=verify)
322
+
323
+ if not quiet:
324
+ if resume:
325
+ print("Resume:", tmp_file, file=sys.stderr)
326
+ print(
327
+ "To:",
328
+ os.path.abspath(output) if output_is_path else output,
329
+ file=sys.stderr,
330
+ )
331
+
332
+ try:
333
+ total = int(res.headers.get("Content-Length", 0))
334
+ if not quiet:
335
+ pbar = tqdm.tqdm(total=total, unit="B", unit_scale=True)
336
+ t_start = time.time()
337
+ for chunk in res.iter_content(chunk_size=CHUNK_SIZE):
338
+ f.write(chunk)
339
+ if not quiet:
340
+ pbar.update(len(chunk))
341
+ if speed is not None:
342
+ elapsed_time_expected = 1.0 * pbar.n / speed
343
+ elapsed_time = time.time() - t_start
344
+ if elapsed_time < elapsed_time_expected:
345
+ time.sleep(elapsed_time_expected - elapsed_time)
346
+ if not quiet:
347
+ pbar.close()
348
+ if tmp_file:
349
+ f.close()
350
+ shutil.move(tmp_file, output)
351
+ finally:
352
+ sess.close()
353
+
354
+ return output
launch_tensorboard.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import logging
3
+ from tensorboard import program
4
+
5
+ log_path = "logs"
6
+
7
+
8
+ def launch_tensorboard_pipeline():
9
+ logging.getLogger("root").setLevel(logging.WARNING)
10
+ logging.getLogger("tensorboard").setLevel(logging.WARNING)
11
+
12
+ tb = program.TensorBoard()
13
+ tb.configure(argv=[None, "--logdir", log_path])
14
+ url = tb.launch()
15
+
16
+ print(
17
+ f"Access the tensorboard using the following link:\n{url}?pinnedCards=%5B%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fg%2Ftotal%22%7D%2C%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fd%2Ftotal%22%7D%2C%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fg%2Fkl%22%7D%2C%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fg%2Fmel%22%7D%5D"
18
+ )
19
+
20
+ while True:
21
+ time.sleep(600)
model_download.py ADDED
@@ -0,0 +1,385 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import six
4
+ import sys
5
+ import wget
6
+ import shutil
7
+ import zipfile
8
+ import requests
9
+ from bs4 import BeautifulSoup
10
+ from urllib.parse import unquote, urlencode, parse_qs, urlparse
11
+
12
+ now_dir = os.getcwd()
13
+ sys.path.append(now_dir)
14
+
15
+ from rvc_cli.rvc.lib.utils import format_title
16
+ from rvc_cli.rvc.lib.tools import gdown
17
+
18
+
19
+ def find_folder_parent(search_dir, folder_name):
20
+ for dirpath, dirnames, _ in os.walk(search_dir):
21
+ if folder_name in dirnames:
22
+ return os.path.abspath(dirpath)
23
+ return None
24
+
25
+
26
+ file_path = find_folder_parent(now_dir, "logs")
27
+ zips_path = os.path.join(file_path, "zips")
28
+
29
+
30
+ def search_pth_index(folder):
31
+ pth_paths = [
32
+ os.path.join(folder, file)
33
+ for file in os.listdir(folder)
34
+ if os.path.isfile(os.path.join(folder, file)) and file.endswith(".pth")
35
+ ]
36
+ index_paths = [
37
+ os.path.join(folder, file)
38
+ for file in os.listdir(folder)
39
+ if os.path.isfile(os.path.join(folder, file)) and file.endswith(".index")
40
+ ]
41
+
42
+ return pth_paths, index_paths
43
+
44
+
45
+ def get_mediafire_download_link(url):
46
+ response = requests.get(url)
47
+ response.raise_for_status()
48
+ soup = BeautifulSoup(response.text, "html.parser")
49
+ download_button = soup.find(
50
+ "a", {"class": "input popsok", "aria-label": "Download file"}
51
+ )
52
+ if download_button:
53
+ download_link = download_button.get("href")
54
+ return download_link
55
+ else:
56
+ return None
57
+
58
+
59
+ def download_from_url(url):
60
+ os.makedirs(zips_path, exist_ok=True)
61
+ if url != "":
62
+ if "drive.google.com" in url:
63
+ if "file/d/" in url:
64
+ file_id = url.split("file/d/")[1].split("/")[0]
65
+ elif "id=" in url:
66
+ file_id = url.split("id=")[1].split("&")[0]
67
+ else:
68
+ return None
69
+
70
+ if file_id:
71
+ os.chdir(zips_path)
72
+ try:
73
+ gdown.download(
74
+ f"https://drive.google.com/uc?id={file_id}",
75
+ quiet=True,
76
+ fuzzy=True,
77
+ )
78
+ except Exception as error:
79
+ error_message = str(
80
+ f"An error occurred downloading the file: {error}"
81
+ )
82
+ if (
83
+ "Too many users have viewed or downloaded this file recently"
84
+ in error_message
85
+ ):
86
+ os.chdir(now_dir)
87
+ return "too much use"
88
+ elif (
89
+ "Cannot retrieve the public link of the file." in error_message
90
+ ):
91
+ os.chdir(now_dir)
92
+ return "private link"
93
+ else:
94
+ print(error_message)
95
+ os.chdir(now_dir)
96
+ return None
97
+ elif "disk.yandex.ru" in url:
98
+ base_url = "https://cloud-api.yandex.net/v1/disk/public/resources/download?"
99
+ public_key = url
100
+ final_url = base_url + urlencode(dict(public_key=public_key))
101
+ response = requests.get(final_url)
102
+ download_url = response.json()["href"]
103
+ download_response = requests.get(download_url)
104
+
105
+ if download_response.status_code == 200:
106
+ filename = parse_qs(urlparse(unquote(download_url)).query).get(
107
+ "filename", [""]
108
+ )[0]
109
+ if filename:
110
+ os.chdir(zips_path)
111
+ with open(filename, "wb") as f:
112
+ f.write(download_response.content)
113
+ else:
114
+ print("Failed to get filename from URL.")
115
+ return None
116
+
117
+ elif "pixeldrain.com" in url:
118
+ try:
119
+ file_id = url.split("pixeldrain.com/u/")[1]
120
+ os.chdir(zips_path)
121
+ print(file_id)
122
+ response = requests.get(f"https://pixeldrain.com/api/file/{file_id}")
123
+ if response.status_code == 200:
124
+ file_name = (
125
+ response.headers.get("Content-Disposition")
126
+ .split("filename=")[-1]
127
+ .strip('";')
128
+ )
129
+ os.makedirs(zips_path, exist_ok=True)
130
+ with open(os.path.join(zips_path, file_name), "wb") as newfile:
131
+ newfile.write(response.content)
132
+ os.chdir(file_path)
133
+ return "downloaded"
134
+ else:
135
+ os.chdir(file_path)
136
+ return None
137
+ except Exception as error:
138
+ print(f"An error occurred downloading the file: {error}")
139
+ os.chdir(file_path)
140
+ return None
141
+
142
+ elif "cdn.discordapp.com" in url:
143
+ file = requests.get(url)
144
+ os.chdir(zips_path)
145
+ if file.status_code == 200:
146
+ name = url.split("/")
147
+ with open(os.path.join(name[-1]), "wb") as newfile:
148
+ newfile.write(file.content)
149
+ else:
150
+ return None
151
+ elif "/blob/" in url or "/resolve/" in url:
152
+ os.chdir(zips_path)
153
+ if "/blob/" in url:
154
+ url = url.replace("/blob/", "/resolve/")
155
+
156
+ response = requests.get(url, stream=True)
157
+ if response.status_code == 200:
158
+ content_disposition = six.moves.urllib_parse.unquote(
159
+ response.headers["Content-Disposition"]
160
+ )
161
+ m = re.search(r'filename="([^"]+)"', content_disposition)
162
+ file_name = m.groups()[0]
163
+ file_name = file_name.replace(os.path.sep, "_")
164
+ total_size_in_bytes = int(response.headers.get("content-length", 0))
165
+ block_size = 1024
166
+ progress_bar_length = 50
167
+ progress = 0
168
+
169
+ with open(os.path.join(zips_path, file_name), "wb") as file:
170
+ for data in response.iter_content(block_size):
171
+ file.write(data)
172
+ progress += len(data)
173
+ progress_percent = int((progress / total_size_in_bytes) * 100)
174
+ num_dots = int(
175
+ (progress / total_size_in_bytes) * progress_bar_length
176
+ )
177
+ progress_bar = (
178
+ "["
179
+ + "." * num_dots
180
+ + " " * (progress_bar_length - num_dots)
181
+ + "]"
182
+ )
183
+ print(
184
+ f"{progress_percent}% {progress_bar} {progress}/{total_size_in_bytes} ",
185
+ end="\r",
186
+ )
187
+ if progress_percent == 100:
188
+ print("\n")
189
+
190
+ else:
191
+ os.chdir(now_dir)
192
+ return None
193
+ elif "/tree/main" in url:
194
+ os.chdir(zips_path)
195
+ response = requests.get(url)
196
+ soup = BeautifulSoup(response.content, "html.parser")
197
+ temp_url = ""
198
+ for link in soup.find_all("a", href=True):
199
+ if link["href"].endswith(".zip"):
200
+ temp_url = link["href"]
201
+ break
202
+ if temp_url:
203
+ url = temp_url
204
+ url = url.replace("blob", "resolve")
205
+ if "huggingface.co" not in url:
206
+ url = "https://huggingface.co" + url
207
+
208
+ wget.download(url)
209
+ else:
210
+ os.chdir(now_dir)
211
+ return None
212
+ elif "applio.org" in url:
213
+ parts = url.split("/")
214
+ id_with_query = parts[-1]
215
+ id_parts = id_with_query.split("?")
216
+ id_number = id_parts[0]
217
+
218
+ url = "https://cjtfqzjfdimgpvpwhzlv.supabase.co/rest/v1/models"
219
+ headers = {
220
+ "apikey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNqdGZxempmZGltZ3B2cHdoemx2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTUxNjczODgsImV4cCI6MjAxMDc0MzM4OH0.7z5WMIbjR99c2Ooc0ma7B_FyGq10G8X-alkCYTkKR10"
221
+ }
222
+
223
+ params = {"id": f"eq.{id_number}"}
224
+ response = requests.get(url, headers=headers, params=params)
225
+ if response.status_code == 200:
226
+ json_response = response.json()
227
+ print(json_response)
228
+ if json_response:
229
+ link = json_response[0]["link"]
230
+ verify = download_from_url(link)
231
+ if verify == "downloaded":
232
+ return "downloaded"
233
+ else:
234
+ return None
235
+ else:
236
+ return None
237
+ else:
238
+ try:
239
+ os.chdir(zips_path)
240
+ wget.download(url)
241
+ except Exception as error:
242
+ os.chdir(now_dir)
243
+ print(f"An error occurred downloading the file: {error}")
244
+ return None
245
+
246
+ for currentPath, _, zipFiles in os.walk(zips_path):
247
+ for Files in zipFiles:
248
+ filePart = Files.split(".")
249
+ extensionFile = filePart[len(filePart) - 1]
250
+ filePart.pop()
251
+ nameFile = "_".join(filePart)
252
+ realPath = os.path.join(currentPath, Files)
253
+ os.rename(realPath, nameFile + "." + extensionFile)
254
+
255
+ os.chdir(now_dir)
256
+ return "downloaded"
257
+
258
+ os.chdir(now_dir)
259
+ return None
260
+
261
+
262
+ def extract_and_show_progress(zipfile_path, unzips_path):
263
+ try:
264
+ with zipfile.ZipFile(zipfile_path, "r") as zip_ref:
265
+ for file_info in zip_ref.infolist():
266
+ zip_ref.extract(file_info, unzips_path)
267
+ os.remove(zipfile_path)
268
+ return True
269
+ except Exception as error:
270
+ print(f"An error occurred extracting the zip file: {error}")
271
+ return False
272
+
273
+
274
+ def unzip_file(zip_path, zip_file_name):
275
+ zip_file_path = os.path.join(zip_path, zip_file_name + ".zip")
276
+ extract_path = os.path.join(file_path, zip_file_name)
277
+ with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
278
+ zip_ref.extractall(extract_path)
279
+ os.remove(zip_file_path)
280
+
281
+
282
+ def model_download_pipeline(url: str):
283
+ try:
284
+ verify = download_from_url(url)
285
+ if verify == "downloaded":
286
+ extract_folder_path = ""
287
+ for filename in os.listdir(zips_path):
288
+ if filename.endswith(".zip"):
289
+ zipfile_path = os.path.join(zips_path, filename)
290
+ print("Proceeding with the extraction...")
291
+
292
+ model_zip = os.path.basename(zipfile_path)
293
+ model_name = format_title(model_zip.split(".zip")[0])
294
+ extract_folder_path = os.path.join(
295
+ "logs",
296
+ os.path.normpath(model_name),
297
+ )
298
+ success = extract_and_show_progress(
299
+ zipfile_path, extract_folder_path
300
+ )
301
+
302
+ macosx_path = os.path.join(extract_folder_path, "__MACOSX")
303
+ if os.path.exists(macosx_path):
304
+ shutil.rmtree(macosx_path)
305
+
306
+ subfolders = [
307
+ f
308
+ for f in os.listdir(extract_folder_path)
309
+ if os.path.isdir(os.path.join(extract_folder_path, f))
310
+ ]
311
+ if len(subfolders) == 1:
312
+ subfolder_path = os.path.join(
313
+ extract_folder_path, subfolders[0]
314
+ )
315
+ for item in os.listdir(subfolder_path):
316
+ s = os.path.join(subfolder_path, item)
317
+ d = os.path.join(extract_folder_path, item)
318
+ shutil.move(s, d)
319
+ os.rmdir(subfolder_path)
320
+
321
+ for item in os.listdir(extract_folder_path):
322
+ if ".pth" in item:
323
+ file_name = item.split(".pth")[0]
324
+ if file_name != model_name:
325
+ os.rename(
326
+ os.path.join(extract_folder_path, item),
327
+ os.path.join(
328
+ extract_folder_path, model_name + ".pth"
329
+ ),
330
+ )
331
+ else:
332
+ if "v2" not in item:
333
+ if "_nprobe_1_" in item and "_v1" in item:
334
+ file_name = item.split("_nprobe_1_")[1].split(
335
+ "_v1"
336
+ )[0]
337
+ if file_name != model_name:
338
+ new_file_name = (
339
+ item.split("_nprobe_1_")[0]
340
+ + "_nprobe_1_"
341
+ + model_name
342
+ + "_v1"
343
+ )
344
+ os.rename(
345
+ os.path.join(extract_folder_path, item),
346
+ os.path.join(
347
+ extract_folder_path,
348
+ new_file_name + ".index",
349
+ ),
350
+ )
351
+ else:
352
+ if "_nprobe_1_" in item and "_v2" in item:
353
+ file_name = item.split("_nprobe_1_")[1].split(
354
+ "_v2"
355
+ )[0]
356
+ if file_name != model_name:
357
+ new_file_name = (
358
+ item.split("_nprobe_1_")[0]
359
+ + "_nprobe_1_"
360
+ + model_name
361
+ + "_v2"
362
+ )
363
+ os.rename(
364
+ os.path.join(extract_folder_path, item),
365
+ os.path.join(
366
+ extract_folder_path,
367
+ new_file_name + ".index",
368
+ ),
369
+ )
370
+
371
+ if success:
372
+ print(f"Model {model_name} downloaded!")
373
+ else:
374
+ print(f"Error downloading {model_name}")
375
+ return "Error"
376
+ if extract_folder_path == "":
377
+ print("Zip file was not found.")
378
+ return "Error"
379
+ result = search_pth_index(extract_folder_path)
380
+ return result
381
+ else:
382
+ return "Error"
383
+ except Exception as error:
384
+ print(f"An unexpected error occurred: {error}")
385
+ return "Error"
prerequisites.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from concurrent.futures import ThreadPoolExecutor
3
+ from tqdm import tqdm
4
+ import requests
5
+ import sys
6
+ import pdb
7
+ import traceback
8
+
9
+ # Automatically invoke the debugger on an unhandled exception.
10
+ def debug_excepthook(exc_type, exc_value, exc_traceback):
11
+ traceback.print_exception(exc_type, exc_value, exc_traceback)
12
+ pdb.post_mortem(exc_traceback)
13
+
14
+ sys.excepthook = debug_excepthook
15
+
16
+ url_base = "https://huggingface.co/IAHispano/Applio/resolve/main/Resources"
17
+
18
+ # Define the file lists
19
+ models_list = [("predictors/", ["rmvpe.pt", "fcpe.pt"])]
20
+ embedders_list = [("embedders/contentvec/", ["pytorch_model.bin", "config.json"])]
21
+ executables_list = [
22
+ ("", ["ffmpeg.exe", "ffprobe.exe"]),
23
+ ]
24
+
25
+ folder_mapping_list = {
26
+ "embedders/contentvec/": ".rvc_cli/rvc/models/embedders/contentvec/",
27
+ "predictors/": ".rvc_cli/rvc/models/predictors/",
28
+ "formant/": ".rvc_cli/rvc/models/formant/",
29
+ }
30
+
31
+
32
+ def get_file_size_all(file_list):
33
+ """
34
+ Calculate the total size of files to be downloaded, regardless of local existence.
35
+ """
36
+ total_size = 0
37
+ for remote_folder, files in file_list:
38
+ # Use the mapping if available; otherwise, use an empty local folder
39
+ local_folder = folder_mapping_list.get(remote_folder, "")
40
+ for file in files:
41
+ url = f"{url_base}/{remote_folder}{file}"
42
+ response = requests.head(url)
43
+ total_size += int(response.headers.get("content-length", 0))
44
+ return total_size
45
+
46
+
47
+ def download_file(url, destination_path, global_bar):
48
+ """
49
+ Download a file from the given URL to the specified destination path,
50
+ updating the global progress bar as data is downloaded.
51
+ """
52
+ dir_name = os.path.dirname(destination_path)
53
+ if dir_name:
54
+ os.makedirs(dir_name, exist_ok=True)
55
+ response = requests.get(url, stream=True)
56
+ block_size = 1024
57
+ with open(destination_path, "wb") as file:
58
+ for data in response.iter_content(block_size):
59
+ file.write(data)
60
+ global_bar.update(len(data))
61
+
62
+
63
+ def download_mapping_files(file_mapping_list, global_bar):
64
+ """
65
+ Download all files in the provided file mapping list using a thread pool executor,
66
+ and update the global progress bar as downloads progress.
67
+ This version downloads all files regardless of whether they already exist.
68
+ """
69
+ with ThreadPoolExecutor() as executor:
70
+ futures = []
71
+ for remote_folder, file_list in file_mapping_list:
72
+ local_folder = folder_mapping_list.get(remote_folder, "")
73
+ for file in file_list:
74
+ destination_path = os.path.join(local_folder, file)
75
+ url = f"{url_base}/{remote_folder}{file}"
76
+ futures.append(
77
+ executor.submit(download_file, url, destination_path, global_bar)
78
+ )
79
+ for future in futures:
80
+ future.result()
81
+
82
+
83
+ def calculate_total_size(models, exe):
84
+ """
85
+ Calculate the total size of all files to be downloaded based on selected categories.
86
+ """
87
+ total_size = 0
88
+ if models:
89
+ total_size += get_file_size_all(models_list)
90
+ total_size += get_file_size_all(embedders_list)
91
+ if exe and os.name == "nt":
92
+ total_size += get_file_size_all(executables_list)
93
+ return total_size
94
+
95
+
96
+ def prerequisites_download_pipeline(models, exe):
97
+ """
98
+ Manage the download pipeline for different categories of files.
99
+ """
100
+ total_size = calculate_total_size(models, exe)
101
+ if total_size > 0:
102
+ with tqdm(
103
+ total=total_size, unit="iB", unit_scale=True, desc="Downloading all files"
104
+ ) as global_bar:
105
+ if models:
106
+ download_mapping_files(models_list, global_bar)
107
+ download_mapping_files(embedders_list, global_bar)
108
+ if exe:
109
+ if os.name == "nt":
110
+ download_mapping_files(executables_list, global_bar)
111
+ else:
112
+ print("No executables needed for non-Windows systems.")
113
+ else:
114
+ print("No files to download.")
pretrained_selector.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def pretrained_selector(pitch_guidance):
2
+ if pitch_guidance == True:
3
+ return {
4
+ "v1": {
5
+ 32000: (
6
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/f0G32k.pth",
7
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/f0D32k.pth",
8
+ ),
9
+ 40000: (
10
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/f0G40k.pth",
11
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/f0D40k.pth",
12
+ ),
13
+ 48000: (
14
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/f0G48k.pth",
15
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/f0D48k.pth",
16
+ ),
17
+ },
18
+ "v2": {
19
+ 32000: (
20
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/f0G32k.pth",
21
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/f0D32k.pth",
22
+ ),
23
+ 40000: (
24
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/f0G40k.pth",
25
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/f0D40k.pth",
26
+ ),
27
+ 48000: (
28
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/f0G48k.pth",
29
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/f0D48k.pth",
30
+ ),
31
+ },
32
+ }
33
+ elif pitch_guidance == False:
34
+ return {
35
+ "v1": {
36
+ 32000: (
37
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/G32k.pth",
38
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/D32k.pth",
39
+ ),
40
+ 40000: (
41
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/G40k.pth",
42
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/D40k.pth",
43
+ ),
44
+ 48000: (
45
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/G48k.pth",
46
+ "rvc_cli/rvc/models/pretraineds/pretrained_v1/D48k.pth",
47
+ ),
48
+ },
49
+ "v2": {
50
+ 32000: (
51
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/G32k.pth",
52
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/D32k.pth",
53
+ ),
54
+ 40000: (
55
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/G40k.pth",
56
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/D40k.pth",
57
+ ),
58
+ 48000: (
59
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/G48k.pth",
60
+ "rvc_cli/rvc/models/pretraineds/pretrained_v2/D48k.pth",
61
+ ),
62
+ },
63
+ }
split_audio.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import librosa
3
+
4
+
5
+ def process_audio(audio, sr=16000, silence_thresh=-60, min_silence_len=250):
6
+ """
7
+ Splits an audio signal into segments using a fixed frame size and hop size.
8
+
9
+ Parameters:
10
+ - audio (np.ndarray): The audio signal to split.
11
+ - sr (int): The sample rate of the input audio (default is 16000).
12
+ - silence_thresh (int): Silence threshold (default =-60dB)
13
+ - min_silence_len (int): Minimum silence duration (default 250ms).
14
+
15
+ Returns:
16
+ - list of np.ndarray: A list of audio segments.
17
+ - np.ndarray: The intervals where the audio was split.
18
+ """
19
+ frame_length = int(min_silence_len / 1000 * sr)
20
+ hop_length = frame_length // 2
21
+ intervals = librosa.effects.split(
22
+ audio, top_db=-silence_thresh, frame_length=frame_length, hop_length=hop_length
23
+ )
24
+ audio_segments = [audio[start:end] for start, end in intervals]
25
+
26
+ return audio_segments, intervals
27
+
28
+
29
+ def merge_audio(audio_segments, intervals, sr_orig, sr_new):
30
+ """
31
+ Merges audio segments back into a single audio signal, filling gaps with silence.
32
+
33
+ Parameters:
34
+ - audio_segments (list of np.ndarray): The non-silent audio segments.
35
+ - intervals (np.ndarray): The intervals used for splitting the original audio.
36
+ - sr_orig (int): The sample rate of the original audio
37
+ - sr_new (int): The sample rate of the model
38
+
39
+ Returns:
40
+ - np.ndarray: The merged audio signal with silent gaps restored.
41
+ """
42
+ sr_ratio = sr_new / sr_orig if sr_new > sr_orig else 1.0
43
+
44
+ merged_audio = np.zeros(
45
+ int(intervals[0][0] * sr_ratio if intervals[0][0] > 0 else 0),
46
+ dtype=audio_segments[0].dtype,
47
+ )
48
+
49
+ merged_audio = np.concatenate((merged_audio, audio_segments[0]))
50
+
51
+ for i in range(1, len(intervals)):
52
+ silence_duration = int((intervals[i][0] - intervals[i - 1][1]) * sr_ratio)
53
+ silence = np.zeros(silence_duration, dtype=audio_segments[0].dtype)
54
+ merged_audio = np.concatenate((merged_audio, silence, audio_segments[i]))
55
+
56
+ return merged_audio