Upload 8 files
Browse files- analyzer.py +76 -0
- gdown.py +354 -0
- launch_tensorboard.py +21 -0
- model_download.py +385 -0
- prerequisites.py +114 -0
- pretrained_selector.py +63 -0
- 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
|