Spaces:
Running
on
Zero
Running
on
Zero
Upload 102 files
Browse files- .anvil_editor.yaml +6 -0
- .devcontainer/devcontainer.json +33 -0
- .gitignore +3 -75
- __init__.py +7 -0
- anvil.yaml +7 -0
- apollo_processing.py +216 -0
- assets/config.json +6 -0
- assets/i18n/i18n.py +54 -0
- assets/i18n/languages/ar_sa.json +280 -0
- assets/i18n/languages/de_de.json +280 -0
- assets/i18n/languages/en_us.json +279 -0
- assets/i18n/languages/es_es.json +280 -0
- assets/i18n/languages/fr_fr.json +273 -0
- assets/i18n/languages/hi_in.json +287 -0
- assets/i18n/languages/it_it.json +280 -0
- assets/i18n/languages/ja_jp.json +280 -0
- assets/i18n/languages/ru_ru.json +280 -0
- assets/i18n/languages/tr_tr.json +301 -0
- assets/i18n/languages/zn_cn.json +280 -0
- config_manager.py +128 -0
- download.py +104 -17
- ensemble.py +375 -153
- gui.py +758 -573
- helpers.py +209 -25
- inference.py +106 -221
- kaggle/clean_model.py +166 -0
- kaggle/download.py +163 -0
- kaggle/ensemble.py +314 -0
- kaggle/test +1 -0
- main.py +19 -21
- model.py +93 -21
- processing.py +675 -217
- requirements.txt +6 -2
.anvil_editor.yaml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
unique_ids:
|
2 |
+
assets: {}
|
3 |
+
forms: {}
|
4 |
+
modules: {}
|
5 |
+
scripts: {}
|
6 |
+
server_modules: {}
|
.devcontainer/devcontainer.json
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "Python 3",
|
3 |
+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
4 |
+
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
|
5 |
+
"customizations": {
|
6 |
+
"codespaces": {
|
7 |
+
"openFiles": [
|
8 |
+
"README.md",
|
9 |
+
"main.py"
|
10 |
+
]
|
11 |
+
},
|
12 |
+
"vscode": {
|
13 |
+
"settings": {},
|
14 |
+
"extensions": [
|
15 |
+
"ms-python.python",
|
16 |
+
"ms-python.vscode-pylance"
|
17 |
+
]
|
18 |
+
}
|
19 |
+
},
|
20 |
+
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo '✅ Packages installed and Requirements met'",
|
21 |
+
"postAttachCommand": {
|
22 |
+
"server": "streamlit run main.py --server.enableCORS false --server.enableXsrfProtection false"
|
23 |
+
},
|
24 |
+
"portsAttributes": {
|
25 |
+
"8501": {
|
26 |
+
"label": "Application",
|
27 |
+
"onAutoForward": "openPreview"
|
28 |
+
}
|
29 |
+
},
|
30 |
+
"forwardPorts": [
|
31 |
+
8501
|
32 |
+
]
|
33 |
+
}
|
.gitignore
CHANGED
@@ -1,76 +1,4 @@
|
|
|
|
|
|
1 |
__pycache__
|
2 |
-
.
|
3 |
-
*.py[cod]
|
4 |
-
*$py.class
|
5 |
-
|
6 |
-
# Distribution / packaging
|
7 |
-
.Python
|
8 |
-
build/
|
9 |
-
develop-eggs/
|
10 |
-
dist/
|
11 |
-
downloads/
|
12 |
-
eggs/
|
13 |
-
.eggs/
|
14 |
-
lib/
|
15 |
-
Lib/site-packages/
|
16 |
-
lib64/
|
17 |
-
parts/
|
18 |
-
sdist/
|
19 |
-
var/
|
20 |
-
wheels/
|
21 |
-
share/python-wheels/
|
22 |
-
share/man/man1/
|
23 |
-
*.egg-info/
|
24 |
-
.installed.cfg
|
25 |
-
*.egg
|
26 |
-
MANIFEST
|
27 |
-
|
28 |
-
# PyInstaller
|
29 |
-
# Usually these files are written by a python script from a template
|
30 |
-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
31 |
-
*.manifest
|
32 |
-
*.spec
|
33 |
-
|
34 |
-
# Installer logs
|
35 |
-
pip-log.txt
|
36 |
-
pip-delete-this-directory.txt
|
37 |
-
|
38 |
-
# Unit test / coverage reports
|
39 |
-
htmlcov/
|
40 |
-
.tox/
|
41 |
-
.nox/
|
42 |
-
.coverage
|
43 |
-
.coverage.*
|
44 |
-
.cache
|
45 |
-
nosetests.xml
|
46 |
-
coverage.xml
|
47 |
-
*.cover
|
48 |
-
*.py,cover
|
49 |
-
.hypothesis/
|
50 |
-
.pytest_cache/
|
51 |
-
cover/
|
52 |
-
|
53 |
-
# Jupyter Notebook
|
54 |
-
.ipynb_checkpoints
|
55 |
-
share/jupyter
|
56 |
-
etc/jupyter
|
57 |
-
|
58 |
-
# IPython
|
59 |
-
profile_default/
|
60 |
-
ipython_config.py
|
61 |
-
|
62 |
-
# Environments
|
63 |
-
.env
|
64 |
-
.venv
|
65 |
-
env/
|
66 |
-
venv/
|
67 |
-
ENV/
|
68 |
-
env.bak/
|
69 |
-
venv.bak/
|
70 |
-
pyvenv.cfg
|
71 |
-
Scripts/
|
72 |
-
|
73 |
-
*.code-workspace
|
74 |
-
|
75 |
-
results/
|
76 |
-
wandb/
|
|
|
1 |
+
*.pyc
|
2 |
+
*.pyo
|
3 |
__pycache__
|
4 |
+
.anvil-data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__init__.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#
|
2 |
+
# This repository is an Anvil app. Learn more at https://anvil.works/
|
3 |
+
# To run the server-side code on your own machine, run:
|
4 |
+
# pip install anvil-uplink
|
5 |
+
# python -m anvil.run_app_via_uplink YourAppPackageName
|
6 |
+
|
7 |
+
__path__ = [__path__[0]+"/server_code", __path__[0]+"/client_code"]
|
anvil.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
native_deps:
|
2 |
+
head_html: |2
|
3 |
+
|
4 |
+
<style>
|
5 |
+
.anvil-panel-section-container { padding: 0 15px; }
|
6 |
+
</style>
|
7 |
+
runtime_options: {client_version: '2', server_spec: null, version: 2}
|
apollo_processing.py
ADDED
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# apollo_processing.py
|
2 |
+
import os
|
3 |
+
import subprocess
|
4 |
+
import librosa
|
5 |
+
import soundfile as sf
|
6 |
+
import numpy as np
|
7 |
+
from helpers import clamp_percentage, sanitize_filename
|
8 |
+
|
9 |
+
def process_with_apollo(
|
10 |
+
output_files,
|
11 |
+
output_dir,
|
12 |
+
apollo_chunk_size,
|
13 |
+
apollo_overlap,
|
14 |
+
apollo_method,
|
15 |
+
apollo_normal_model,
|
16 |
+
apollo_midside_model,
|
17 |
+
output_format,
|
18 |
+
progress=None,
|
19 |
+
total_progress_start=80,
|
20 |
+
total_progress_end=100
|
21 |
+
):
|
22 |
+
"""
|
23 |
+
Process audio files with Apollo enhancement.
|
24 |
+
|
25 |
+
Args:
|
26 |
+
output_files: List of input audio file paths to process.
|
27 |
+
output_dir: Directory to store enhanced output files.
|
28 |
+
apollo_chunk_size: Chunk size for Apollo processing.
|
29 |
+
apollo_overlap: Overlap for Apollo processing.
|
30 |
+
apollo_method: Apollo processing method ('normal_method' or 'mid_side_method').
|
31 |
+
apollo_normal_model: Apollo model for normal method.
|
32 |
+
apollo_midside_model: Apollo model for mid-side method.
|
33 |
+
output_format: Output audio format (e.g., 'wav').
|
34 |
+
progress: Gradio progress object for UI updates.
|
35 |
+
total_progress_start: Starting progress percentage (default: 80).
|
36 |
+
total_progress_end: Ending progress percentage (default: 100).
|
37 |
+
|
38 |
+
Returns:
|
39 |
+
List of enhanced file paths or original files if processing fails.
|
40 |
+
"""
|
41 |
+
try:
|
42 |
+
apollo_script = "/content/Apollo/inference.py"
|
43 |
+
print(f"Apollo parameters - chunk_size: {apollo_chunk_size}, overlap: {apollo_overlap}, method: {apollo_method}, normal_model: {apollo_normal_model}, midside_model: {apollo_midside_model}")
|
44 |
+
|
45 |
+
# Select checkpoint and config based on method and model
|
46 |
+
if apollo_method == "mid_side_method":
|
47 |
+
if apollo_midside_model == "MP3 Enhancer":
|
48 |
+
ckpt = "/content/Apollo/model/pytorch_model.bin"
|
49 |
+
config = "/content/Apollo/configs/apollo.yaml"
|
50 |
+
elif apollo_midside_model == "Lew Vocal Enhancer":
|
51 |
+
ckpt = "/content/Apollo/model/apollo_model.ckpt"
|
52 |
+
config = "/content/Apollo/configs/apollo.yaml"
|
53 |
+
elif apollo_midside_model == "Lew Vocal Enhancer v2 (beta)":
|
54 |
+
ckpt = "/content/Apollo/model/apollo_model_v2.ckpt"
|
55 |
+
config = "/content/Apollo/configs/config_apollo_vocal.yaml"
|
56 |
+
else:
|
57 |
+
ckpt = "/content/Apollo/model/apollo_universal_model.ckpt"
|
58 |
+
config = "/content/Apollo/configs/config_apollo.yaml"
|
59 |
+
else:
|
60 |
+
if apollo_normal_model == "MP3 Enhancer":
|
61 |
+
ckpt = "/content/Apollo/model/pytorch_model.bin"
|
62 |
+
config = "/content/Apollo/configs/apollo.yaml"
|
63 |
+
elif apollo_normal_model == "Lew Vocal Enhancer":
|
64 |
+
ckpt = "/content/Apollo/model/apollo_model.ckpt"
|
65 |
+
config = "/content/Apollo/configs/apollo.yaml"
|
66 |
+
elif apollo_normal_model == "Lew Vocal Enhancer v2 (beta)":
|
67 |
+
ckpt = "/content/Apollo/model/apollo_model_v2.ckpt"
|
68 |
+
config = "/content/Apollo/configs/config_apollo_vocal.yaml"
|
69 |
+
else:
|
70 |
+
ckpt = "/content/Apollo/model/apollo_universal_model.ckpt"
|
71 |
+
config = "/content/Apollo/configs/config_apollo.yaml"
|
72 |
+
|
73 |
+
if not os.path.exists(ckpt):
|
74 |
+
raise FileNotFoundError(f"Apollo checkpoint file not found: {ckpt}")
|
75 |
+
if not os.path.exists(config):
|
76 |
+
raise FileNotFoundError(f"Apollo configuration file not found: {config}")
|
77 |
+
|
78 |
+
enhanced_files = []
|
79 |
+
total_files = len([f for f in output_files if f and os.path.exists(f)])
|
80 |
+
progress_per_file = (total_progress_end - total_progress_start) / total_files if total_files > 0 else (total_progress_end - total_progress_start)
|
81 |
+
|
82 |
+
for idx, output_file in enumerate(output_files):
|
83 |
+
if output_file and os.path.exists(output_file):
|
84 |
+
original_file_name = sanitize_filename(os.path.splitext(os.path.basename(output_file))[0])
|
85 |
+
enhancement_suffix = "_Mid_Side_Enhanced" if apollo_method == "mid_side_method" else "_Enhanced"
|
86 |
+
enhanced_output = os.path.join(output_dir, f"{original_file_name}{enhancement_suffix}.{output_format}")
|
87 |
+
|
88 |
+
try:
|
89 |
+
# Progress update
|
90 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
91 |
+
current_progress = total_progress_start + (idx * progress_per_file)
|
92 |
+
current_progress = clamp_percentage(current_progress)
|
93 |
+
progress(current_progress, desc=f"Enhancing with Apollo... ({idx+1}/{total_files})")
|
94 |
+
else:
|
95 |
+
print(f"Progress is not callable or None, skipping Apollo progress update: file {idx+1}/{total_files}")
|
96 |
+
|
97 |
+
if apollo_method == "mid_side_method":
|
98 |
+
audio, sr = librosa.load(output_file, mono=False, sr=None)
|
99 |
+
if audio.ndim == 1:
|
100 |
+
audio = np.array([audio, audio])
|
101 |
+
|
102 |
+
mid = (audio[0] + audio[1]) * 0.5
|
103 |
+
side = (audio[0] - audio[1]) * 0.5
|
104 |
+
|
105 |
+
mid_file = os.path.join(output_dir, f"{original_file_name}_mid_temp.wav")
|
106 |
+
side_file = os.path.join(output_dir, f"{original_file_name}_side_temp.wav")
|
107 |
+
sf.write(mid_file, mid, sr)
|
108 |
+
sf.write(side_file, side, sr)
|
109 |
+
|
110 |
+
mid_output = os.path.join(output_dir, f"{original_file_name}_mid_enhanced.{output_format}")
|
111 |
+
command_mid = [
|
112 |
+
"python", apollo_script,
|
113 |
+
"--in_wav", mid_file,
|
114 |
+
"--out_wav", mid_output,
|
115 |
+
"--chunk_size", str(int(apollo_chunk_size)),
|
116 |
+
"--overlap", str(int(apollo_overlap)),
|
117 |
+
"--ckpt", ckpt,
|
118 |
+
"--config", config
|
119 |
+
]
|
120 |
+
print(f"Running Apollo Mid command: {' '.join(command_mid)}")
|
121 |
+
result_mid = subprocess.run(command_mid, capture_output=True, text=True)
|
122 |
+
if result_mid.returncode != 0:
|
123 |
+
print(f"Apollo Mid processing failed: {result_mid.stderr}")
|
124 |
+
enhanced_files.append(output_file)
|
125 |
+
continue
|
126 |
+
|
127 |
+
side_output = os.path.join(output_dir, f"{original_file_name}_side_enhanced.{output_format}")
|
128 |
+
command_side = [
|
129 |
+
"python", apollo_script,
|
130 |
+
"--in_wav", side_file,
|
131 |
+
"--out_wav", side_output,
|
132 |
+
"--chunk_size", str(int(apollo_chunk_size)),
|
133 |
+
"--overlap", str(int(apollo_overlap)),
|
134 |
+
"--ckpt", ckpt,
|
135 |
+
"--config", config
|
136 |
+
]
|
137 |
+
print(f"Running Apollo Side command: {' '.join(command_side)}")
|
138 |
+
result_side = subprocess.run(command_side, capture_output=True, text=True)
|
139 |
+
if result_side.returncode != 0:
|
140 |
+
print(f"Apollo Side processing failed: {result_side.stderr}")
|
141 |
+
enhanced_files.append(output_file)
|
142 |
+
continue
|
143 |
+
|
144 |
+
if not (os.path.exists(mid_output) and os.path.exists(side_output)):
|
145 |
+
print(f"Apollo outputs missing: mid={mid_output}, side={side_output}")
|
146 |
+
enhanced_files.append(output_file)
|
147 |
+
continue
|
148 |
+
|
149 |
+
mid_audio, _ = librosa.load(mid_output, sr=sr, mono=True)
|
150 |
+
side_audio, _ = librosa.load(side_output, sr=sr, mono=True)
|
151 |
+
left = mid_audio + side_audio
|
152 |
+
right = mid_audio - side_audio
|
153 |
+
combined = np.array([left, right])
|
154 |
+
|
155 |
+
os.makedirs(os.path.dirname(enhanced_output), exist_ok=True)
|
156 |
+
sf.write(enhanced_output, combined.T, sr)
|
157 |
+
|
158 |
+
temp_files = [mid_file, side_file, mid_output, side_output]
|
159 |
+
for temp_file in temp_files:
|
160 |
+
try:
|
161 |
+
if os.path.exists(temp_file):
|
162 |
+
os.remove(temp_file)
|
163 |
+
except Exception as e:
|
164 |
+
print(f"Could not delete temporary file {temp_file}: {str(e)}")
|
165 |
+
|
166 |
+
enhanced_files.append(enhanced_output)
|
167 |
+
else:
|
168 |
+
command = [
|
169 |
+
"python", apollo_script,
|
170 |
+
"--in_wav", output_file,
|
171 |
+
"--out_wav", enhanced_output,
|
172 |
+
"--chunk_size", str(int(apollo_chunk_size)),
|
173 |
+
"--overlap", str(int(apollo_overlap)),
|
174 |
+
"--ckpt", ckpt,
|
175 |
+
"--config", config
|
176 |
+
]
|
177 |
+
print(f"Running Apollo Normal command: {' '.join(command)}")
|
178 |
+
apollo_process = subprocess.run(
|
179 |
+
command,
|
180 |
+
capture_output=True,
|
181 |
+
text=True
|
182 |
+
)
|
183 |
+
if apollo_process.returncode != 0:
|
184 |
+
print(f"Apollo processing failed: {output_file}: {apollo_process.stderr}")
|
185 |
+
enhanced_files.append(output_file)
|
186 |
+
continue
|
187 |
+
|
188 |
+
if not os.path.exists(enhanced_output):
|
189 |
+
print(f"Apollo output missing: {enhanced_output}")
|
190 |
+
enhanced_files.append(output_file)
|
191 |
+
continue
|
192 |
+
|
193 |
+
enhanced_files.append(enhanced_output)
|
194 |
+
|
195 |
+
# Progress update after each file
|
196 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
197 |
+
current_progress = total_progress_start + ((idx + 1) * progress_per_file)
|
198 |
+
current_progress = clamp_percentage(current_progress)
|
199 |
+
progress(current_progress, desc=f"Enhancing with Apollo... ({idx+1}/{total_files})")
|
200 |
+
|
201 |
+
except Exception as e:
|
202 |
+
print(f"Error during Apollo processing: {output_file}: {str(e)}")
|
203 |
+
enhanced_files.append(output_file)
|
204 |
+
continue
|
205 |
+
else:
|
206 |
+
enhanced_files.append(output_file)
|
207 |
+
|
208 |
+
# Final progress update
|
209 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
210 |
+
progress(total_progress_end, desc="Apollo enhancement complete")
|
211 |
+
|
212 |
+
return enhanced_files
|
213 |
+
|
214 |
+
except Exception as e:
|
215 |
+
print(f"Apollo processing error: {str(e)}")
|
216 |
+
return [f for f in output_files]
|
assets/config.json
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"lang": {
|
3 |
+
"override": true,
|
4 |
+
"selected_lang": "en_us"
|
5 |
+
}
|
6 |
+
}
|
assets/i18n/i18n.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
from pathlib import Path
|
4 |
+
from locale import getdefaultlocale
|
5 |
+
|
6 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
7 |
+
|
8 |
+
now_dir = os.path.dirname(os.path.abspath(__file__))
|
9 |
+
|
10 |
+
class I18nAuto:
|
11 |
+
LANGUAGE_PATH = os.path.join(BASE_DIR, "assets", "i18n", "languages")
|
12 |
+
|
13 |
+
def __init__(self, language=None):
|
14 |
+
config_path = os.path.join(BASE_DIR, "assets", "config.json")
|
15 |
+
try:
|
16 |
+
with open(config_path, "r", encoding="utf8") as file:
|
17 |
+
config = json.load(file)
|
18 |
+
lang_config = config.get("lang", {"override": False, "selected_lang": "auto"})
|
19 |
+
override = lang_config.get("override", False)
|
20 |
+
lang_prefix = lang_config.get("selected_lang", "auto")
|
21 |
+
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
22 |
+
override = False
|
23 |
+
lang_prefix = "auto"
|
24 |
+
|
25 |
+
self.language = lang_prefix
|
26 |
+
|
27 |
+
if not override:
|
28 |
+
language = language or getdefaultlocale()[0]
|
29 |
+
lang_prefix = language[:2] if language is not None else "en"
|
30 |
+
available_languages = self._get_available_languages()
|
31 |
+
matching_languages = [lang for lang in available_languages if lang.startswith(lang_prefix)]
|
32 |
+
self.language = matching_languages[0] if matching_languages else "en_US"
|
33 |
+
|
34 |
+
self.language_map = self._load_language_list()
|
35 |
+
|
36 |
+
def _load_language_list(self):
|
37 |
+
try:
|
38 |
+
file_path = Path(self.LANGUAGE_PATH) / f"{self.language}.json"
|
39 |
+
with open(file_path, "r", encoding="utf-8") as file:
|
40 |
+
return json.load(file)
|
41 |
+
except FileNotFoundError:
|
42 |
+
raise FileNotFoundError(
|
43 |
+
f"Failed to load language file for {self.language}. Check if the correct .json file exists."
|
44 |
+
)
|
45 |
+
|
46 |
+
def _get_available_languages(self):
|
47 |
+
language_files = [path.stem for path in Path(self.LANGUAGE_PATH).glob("*.json")]
|
48 |
+
return language_files
|
49 |
+
|
50 |
+
def _language_exists(self, language):
|
51 |
+
return (Path(self.LANGUAGE_PATH) / f"{language}.json").exists()
|
52 |
+
|
53 |
+
def __call__(self, key):
|
54 |
+
return self.language_map.get(key, key)
|
assets/i18n/languages/ar_sa.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "اختر اللغة",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "فصل الصوت النهائي الخاص بك",
|
5 |
+
"presented_by": "مقدم من Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ فصل الصوت",
|
7 |
+
"input_model": "📥 الإدخال والنموذج",
|
8 |
+
"upload": "🖥 رفع",
|
9 |
+
"path": "📂 المسار",
|
10 |
+
"path_placeholder": "/مسار/إلى/صوت.wav",
|
11 |
+
"category": "الفئة",
|
12 |
+
"model": "النموذج",
|
13 |
+
"settings": "⚙ الإعدادات",
|
14 |
+
"format": "الصيغة",
|
15 |
+
"chunk_size": "حجم القطعة",
|
16 |
+
"chunk_size_info": "لا تغير ما لم يكن لديك متطلبات محددة",
|
17 |
+
"overlap": "التداخل",
|
18 |
+
"overlap_info": "موصى به: 2-10 (القيم الأعلى تزيد من الجودة ولكن تتطلب المزيد من VRAM)",
|
19 |
+
"tta_boost": "تعزيز TTA",
|
20 |
+
"tta_info": "يحسن الجودة ولكنه يبطئ سرعة المعالجة",
|
21 |
+
"phase_fix": "تصحيح الطور",
|
22 |
+
"phase_fix_info": "تصحيح طور متقدم للمسارات الآلية",
|
23 |
+
"instrumental": "آلي",
|
24 |
+
"instrumental_info": "عادةً يعطي مخرجين، لكن هناك أوقات يعطي فيها مخرجًا واحدًا، تحتاج إلى التجربة :)",
|
25 |
+
"process": "🚀 معالجة",
|
26 |
+
"reset": "🧹 إعادة تعيين",
|
27 |
+
"status": "الحالة",
|
28 |
+
"main_tab": "🎧 الرئيسي",
|
29 |
+
"original": "الأصلي",
|
30 |
+
"vocals": "الأصوات",
|
31 |
+
"instrumental_output": "آلي",
|
32 |
+
"other": "أخرى",
|
33 |
+
"details_tab": "🔍 التفاصيل",
|
34 |
+
"male": "ذكر",
|
35 |
+
"female": "أنثى",
|
36 |
+
"speech": "كلام",
|
37 |
+
"drums": "طبول",
|
38 |
+
"bass": "باس",
|
39 |
+
"effects": "تأثيرات",
|
40 |
+
"advanced_tab": "⚙ متقدم",
|
41 |
+
"phase_remix": "إعادة مزج الطور",
|
42 |
+
"dry": "جاف",
|
43 |
+
"music": "موسيقى",
|
44 |
+
"karaoke": "كاريوكي",
|
45 |
+
"bleed": "تسرب",
|
46 |
+
"copy_to_drive": "📂 نسخ إلى القرص",
|
47 |
+
"copy_status": "حالة النسخ",
|
48 |
+
"files_will_be_copied": "سيتم نسخ الملفات هنا...",
|
49 |
+
"processing_tip": "<b>🔈 نصيحة المعالجة:</b> للحصول على نتائج مشوشة، استخدم نماذج <code>bleed_suppressor_v1</code> أو <code>denoisedebleed</code> في فئة <i>\"إزالة الضوضاء والتأثيرات\"</i> لتنظيف المخرجات",
|
50 |
+
"waiting_for_processing": "في انتظار المعالجة...",
|
51 |
+
"auto_ensemble_tab": "🤖 التجميع التلقائي",
|
52 |
+
"upload_file": "رفع ملف",
|
53 |
+
"enter_file_path": "أو أدخل مسار الملف",
|
54 |
+
"file_path_placeholder": "أدخل المسار الكامل لملف الصوت",
|
55 |
+
"advanced_settings": "⚙️ إعدادات متقدمة",
|
56 |
+
"use_tta": "استخدام TTA",
|
57 |
+
"instrumental_only": "آلي فقط",
|
58 |
+
"auto_overlap": "التداخل",
|
59 |
+
"auto_chunk_size": "حجم القطعة",
|
60 |
+
"output_format": "صيغة الإخراج",
|
61 |
+
"model_selection": "🧠 اختيار النموذج",
|
62 |
+
"model_category": "فئة النموذج",
|
63 |
+
"select_models": "اختر النماذج من الفئة",
|
64 |
+
"ensemble_settings": "⚡ إعدادات التجميع",
|
65 |
+
"method": "الطريقة",
|
66 |
+
"recommendation": "**التوصية:** avg_wave و max_fft يعطيان أفضل النتائج",
|
67 |
+
"start_processing": "🚀 بدء المعالجة",
|
68 |
+
"original_audio_tab": "🔊 الصوت الأصلي",
|
69 |
+
"original_audio": "الصوت الأصلي",
|
70 |
+
"ensemble_result_tab": "🎚️ نتيجة التجميع",
|
71 |
+
"output_preview": "معاينة الإخراج",
|
72 |
+
"refresh_output": "🔄 تحديث الإخراج",
|
73 |
+
"ensemble_copy_status": "سيتم نسخ مخرجات التجميع هنا...",
|
74 |
+
"guidelines": "<h4>إرشادات اختيار النموذج</h4><ul><li><strong>تجنب الخلط بين الفئات:</strong> قد يؤدي الجمع بين نماذج الأصوات والآلات إلى خلط غير مرغوب فيه</li><li><strong>ملاحظات نموذج خاصة:</strong><ul><li>نماذج الازدواجية (v1/v2) - تخرج كلا الجذعين</li><li>MDX23C Separator - نتائج هجينة</li></ul></li><li><strong>أفضل الممارسات:</strong> استخدم 3-5 نماذج متشابهة من نفس الفئة</li></ul><div>💡 نصيحة احترافية: ابدأ بتركيبة \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\"</div>",
|
75 |
+
"download_sources_tab": "⬇️ تحميل المصادر",
|
76 |
+
"direct_links": "🌐 روابط مباشرة",
|
77 |
+
"audio_file_url": "رابط ملف الصوت",
|
78 |
+
"download_from_url": "⬇️ تحميل من الرابط",
|
79 |
+
"download_status": "حالة التحميل",
|
80 |
+
"downloaded_file": "الملف المحمل",
|
81 |
+
"cookie_management": "🍪 إدارة الكوكيز",
|
82 |
+
"upload_cookies_txt": "رفع ملف Cookies.txt",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 لماذا هو ضروري؟**<br>- الوصول إلى المحتوى المقيد بالعمر<br>- تحميل الفيديوهات الخاصة/غير المدرجة<br>- تجاوز القيود الإقليمية<br>- تجنب حدود تحميل يوتيوب<br><br>**⚠️ ملاحظات هامة**<br>- لا تشارك ملفات الكوكيز الخاصة بك أبدًا!<br>- قم بتحديث الكوكيز عندما:<br> • تظهر أخطاء \"403 ممنوع\"<br> • تتوقف التنزيلات فجأة<br> • تظهر رسائل \"انتهت الجلسة\"<br><br>**🔄 خطوات التجديد**<br>1. قم بتثبيت هذا <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">امتداد كروم</a><br>2. سجل الدخول إلى يوتيوب في كروم<br>3. انقر على أيقونة الامتداد → \"تصدير\"<br>4. ارفع الملف المحمل هنا<br><br>**⏳ عمر الكوكيز**<br>- الجلسات العادية: 24 ساعة<br>- العمليات الحساسة: ساعة واحدة<br>- تغييرات كلمة المرور: إبطال فوري</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ التجميع اليدوي",
|
85 |
+
"input_sources": "📂 مصادر الإدخال",
|
86 |
+
"refresh": "🔄 تحديث",
|
87 |
+
"ensemble_algorithm": "خوارزمية التجميع",
|
88 |
+
"select_audio_files": "اختر ملفات الصوت",
|
89 |
+
"available_files": "الملفات المتاحة",
|
90 |
+
"custom_weights": "أوزان مخصصة (مفصولة بفواصل)",
|
91 |
+
"custom_weights_placeholder": "مثال: 0.8، 1.2، 1.0، ...",
|
92 |
+
"custom_weights_info": "اتركه فارغًا لأوزان متساوية",
|
93 |
+
"result_preview_tab": "🎧 معاينة النتيجة",
|
94 |
+
"ensembled_output": "مخرج التجميع",
|
95 |
+
"processing_log_tab": "📋 سجل المعالجة",
|
96 |
+
"processing_details": "تفاصيل المعالجة",
|
97 |
+
"process_ensemble": "⚡ معالجة التجميع",
|
98 |
+
"languages_tab": "🌐 اللغات",
|
99 |
+
"Vocal Models": "نماذج الأصوات",
|
100 |
+
"Instrumental Models": "نماذج الآلات",
|
101 |
+
"4-Stem Models": "نماذج 4 جذور",
|
102 |
+
"Denoise Models": "نماذج إزالة الضوضاء",
|
103 |
+
"Dereverb Models": "نماذج إزالة الصدى",
|
104 |
+
"Other Models": "نماذج أخرى",
|
105 |
+
"ensemble_files_description": "يجمع عدة ملفات صوتية في مخرج واحد باستخدام طرق التجميع المحددة.",
|
106 |
+
"ensemble_files_help": "مسار جميع ملفات الصوت للتجميع",
|
107 |
+
"ensemble_type_help": "واحد من avg_wave، median_wave، min_wave، max_wave، avg_fft، median_fft، min_fft، max_fft",
|
108 |
+
"ensemble_weights_help": "الأوزان لإنشاء التجميع. يجب أن يتساوى عدد الأوزان مع عدد الملفات",
|
109 |
+
"ensemble_output_help": "مسار ملف WAV حيث سيتم حفظ نتيجة التجميع",
|
110 |
+
"ensemble_type_print": "نوع التجميع: {}",
|
111 |
+
"num_input_files_print": "عدد ملفات الإدخال: {}",
|
112 |
+
"weights_print": "الأوزان: {}",
|
113 |
+
"output_file_print": "ملف الإخراج: {}",
|
114 |
+
"duration_mismatch_error": "يجب أن تكون جميع الملفات بنفس المدة",
|
115 |
+
"file_not_found_error": "خطأ. لا يمكن العثور على الملف: {}. تحقق من المسارات.",
|
116 |
+
"reading_chunk_print": "قراءة قطعة من الملف: {} (البداية: {}ث، المدة: {}ث)",
|
117 |
+
"chunk_result_shape_print": "شكل نتيجة القطعة: {}",
|
118 |
+
"ensemble_completed_print": "اكتمل التجميع. تم حفظ الإخراج في: {}",
|
119 |
+
"file_deletion_error": "لا يمكن حذف {}: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ الدليل غير موجود: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ المسار ليس دليلًا: {}",
|
122 |
+
"item_deletion_error": "⚠️ خطأ في حذف {}: {}",
|
123 |
+
"old_output_not_exist": "❌ مجلد الإخراج القديم غير موجود",
|
124 |
+
"old_outputs_cleared": "✅ تم مسح المخرجات القديمة بنجاح!",
|
125 |
+
"error": "🔥 خطأ: {}",
|
126 |
+
"ffmpeg_error": "خطأ FFmpeg ({}): {}",
|
127 |
+
"file_saved_successfully": "تم حفظ الملف بنجاح: {}",
|
128 |
+
"total_files_found": "إجمالي الملفات الموجودة: {}. باستخدام معدل العينة: {}",
|
129 |
+
"total_progress": "التقدم الإجمالي",
|
130 |
+
"detailed_pbar_enabled": "تم تفعيل شريط التقدم التفصيلي: {}",
|
131 |
+
"loaded_audio": "الصوت المحمل: {}، الشكل: {}",
|
132 |
+
"cannot_read_track": "لا يمكن قراءة المسار: {}",
|
133 |
+
"error_message": "رسالة الخطأ: {}",
|
134 |
+
"demudding_track": "تنظيف المسار (إعادة مزج الطور - آلي): {}",
|
135 |
+
"elapsed_time": "الوقت المنقضي: {:.2f} ثانية.",
|
136 |
+
"proc_folder_description": "يعالج ملفات الصوت في مجلد باستخدام نموذج محدد.",
|
137 |
+
"model_type_help": "نوع النموذج (bandit، bs_roformer، mdx23c، إلخ.)",
|
138 |
+
"config_path_help": "مسار ملف التكوين",
|
139 |
+
"demud_phaseremix_help": "تفعيل إعادة مزج الطور للآلي",
|
140 |
+
"start_checkpoint_help": "نقطة التفتيش الأولية للأوزان الصالحة",
|
141 |
+
"input_folder_help": "مجلد يحتوي على الخلطات للمعالجة",
|
142 |
+
"audio_path_help": "مسار ملف صوتي واحد للمعالجة",
|
143 |
+
"store_dir_help": "مسار لتخزين النتائج",
|
144 |
+
"device_ids_help": "قائمة معرفات GPU",
|
145 |
+
"extract_instrumental_help": "قلب الأصوات للحصول على الآلي إذا تم توفيره",
|
146 |
+
"disable_detailed_pbar_help": "تعطيل شريط التقدم التفصيلي في الفصل",
|
147 |
+
"force_cpu_help": "فرض استخدام CPU حتى لو كان CUDA متاحًا",
|
148 |
+
"flac_file_help": "إخراج ملف FLAC بدلاً من WAV",
|
149 |
+
"export_format_help": "صيغة التصدير ونوع PCM",
|
150 |
+
"pcm_type_help": "نوع PCM لملفات FLAC",
|
151 |
+
"use_tta_help": "تفعيل التكبير في وقت الاختبار",
|
152 |
+
"lora_checkpoint_help": "نقطة التفتيش الأولية لأوزان LoRA",
|
153 |
+
"cuda_available": "CUDA متاح، استخدم --force_cpu لتعطيله.",
|
154 |
+
"using_device": "استخدام الجهاز: {}",
|
155 |
+
"instruments_print": "الآلات: {}",
|
156 |
+
"model_load_time": "وقت تحميل النموذج: {:.2f} ثانية",
|
157 |
+
"invalid_url": "❌ رابط غير صالح",
|
158 |
+
"cookie_file_updated": "✅ تم تحديث ملف الكوكيز!",
|
159 |
+
"cookie_installation_error": "⚠️ خطأ في تثبيت الكوكيز: {}",
|
160 |
+
"file_size_zero_error": "حجم الملف صفر أو لم يتم إنشاء الملف",
|
161 |
+
"google_drive_error": "❌ خطأ في تحميل Google Drive: {}",
|
162 |
+
"wav_conversion_failed": "فشل تحويل WAV",
|
163 |
+
"download_error": "❌ خطأ في التحميل: {}",
|
164 |
+
"download_success": "🎉 تم التحميل بنجاح!",
|
165 |
+
"download_failed": "❌ فشل التحميل",
|
166 |
+
"no_output_files_found": "❌ لم يتم العثور على ملفات إخراج.",
|
167 |
+
"output_refreshed_successfully": "✅ تم تحديث الإخراج بنجاح!",
|
168 |
+
"error_refreshing_output": "❌ خطأ في تحديث الإخراج: {}",
|
169 |
+
"starting_audio_separation": "بدء فصل الصوت...",
|
170 |
+
"processing_audio": "معالجة الصوت",
|
171 |
+
"separating_audio": "فصل الصوت... ({:.1f}%)",
|
172 |
+
"separation_complete": "اكتمل الفصل!",
|
173 |
+
"progress_parsing_error": "خطأ في تحليل التقدم: {}",
|
174 |
+
"error_occurred": "حدث خطأ: {}",
|
175 |
+
"separation_process_completed": "اكتمل عملية الفصل!",
|
176 |
+
"no_audio_file_error": "❌ لم يتم توفير ملف صوتي ولا يوجد ملف موجود في دليل الإدخال.",
|
177 |
+
"no_input_progress_label": "خطأ: لم يتم توفير إدخال -- 0.0%",
|
178 |
+
"processing_audio_print": "معالجة الصوت من: {} باستخدام النموذج: {}",
|
179 |
+
"starting_audio_separation_progress_label": "بدء فصل الصوت... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "فصل الصوت... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "اكتملت معالجة الصوت! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ اكتملت معالجة الصوت!",
|
183 |
+
"error_occurred_progress_label": "حدث خطأ -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ الحد الأدنى 2 ملف مطلوب",
|
185 |
+
"valid_files_not_found": "❌ لم يتم العثور على ملفات صالحة",
|
186 |
+
"starting_ensemble_process": "بدء عملية التجميع...",
|
187 |
+
"ensembling_progress": "التجميع... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "إنهاء إخراج التجميع...",
|
189 |
+
"success_log": "✅ نجاح!\n{}",
|
190 |
+
"error_log": "❌ خطأ!\n{}",
|
191 |
+
"critical_error": "⛔ خطأ حرج: {}",
|
192 |
+
"ensemble_process_completed": "اكتملت عملية التجميع!",
|
193 |
+
"no_models_selected": "❌ لم يتم اختيار نماذج",
|
194 |
+
"no_input_audio_provided": "❌ لم يتم توفير صوت إدخال",
|
195 |
+
"loading_model": "تحميل النموذج {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "تحميل النموذج {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "اكتمل النموذج {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "اكتمل النموذج {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "تشغيل الأمر: {}",
|
200 |
+
"model_failed": "فشل النموذج {}: {}",
|
201 |
+
"critical_error_with_model": "خطأ حرج مع {}: {}",
|
202 |
+
"model_output_failed": "فشل {} في إنتاج مخرج",
|
203 |
+
"waiting_for_files": "في انتظار جاهزية جميع الملفات...",
|
204 |
+
"waiting_for_files_progress_label": "في انتظار جاهزية جميع الملفات... -- 90.0%",
|
205 |
+
"performing_ensemble": "تنفيذ التجميع...",
|
206 |
+
"performing_ensemble_progress_label": "تنفيذ التجميع... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "استخدام الذاكرة قبل التجميع: {}%",
|
208 |
+
"memory_usage_after_ensemble": "استخدام الذاكرة بعد التجميع: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "إنهاء إخراج التجميع... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "لم يتم إنشاء ملف التجميع: {}",
|
211 |
+
"ensemble_completed_progress_label": "اكتمل التجميع بنجاح! -- 100.0%",
|
212 |
+
"success_output_created": "✅ نجاح! تم إنشاء ملف الإخراج.",
|
213 |
+
"drive_mounted_copying_ensemble": "تم ربط Google Drive. يتم نسخ مخرج التجميع...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive مربوط بالفعل. يتم نسخ مخرج التجميع...",
|
215 |
+
"no_ensemble_output_files_found": "❌ لم يتم العثور على ملفات إخراج التجميع.",
|
216 |
+
"ensemble_output_copied": "✅ تم نسخ مخرج التجميع إلى {}",
|
217 |
+
"error_copying_ensemble_output": "❌ خطأ في نسخ مخرج التجميع: {}",
|
218 |
+
"drive_mounted_copying_files": "تم ربط Google Drive. يتم نسخ الملفات...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive مربوط بالفعل. يتم نسخ الملفات...",
|
220 |
+
"files_copied_to_drive": "✅ تم نسخ الملفات إلى {}",
|
221 |
+
"error_copying_files": "❌ خطأ في نسخ الملفات: {}",
|
222 |
+
"mounting_drive": "ربط Google Drive...",
|
223 |
+
"settings_saved": "تم حفظ الإعدادات في config.json: اللغة={lang}، الطريقة={method}، المنفذ={port}",
|
224 |
+
"selected_language": "اللغة المختارة: {lang}",
|
225 |
+
"available_languages": "اللغات المتاحة: {langs}",
|
226 |
+
"select_language_prompt": "اختر لغة (الافتراضي: {default}): ",
|
227 |
+
"invalid_language": "اختيار لغة غير صالح! استخدام اللغة الافتراضية ({default}).",
|
228 |
+
"available_sharing_methods": "طرق المشاركة المتاحة: gradio، localtunnel، ngrok",
|
229 |
+
"select_sharing_method_prompt": "اختر طريقة مشاركة (الافتراضي: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "أدخل رمز Ngrok الخاص بك (الافتراضي: {default}): ",
|
231 |
+
"ngrok_token_required": "خطأ: رمز Ngrok مطلوب لطريقة ngrok!",
|
232 |
+
"enter_port_prompt": "أدخل رقم المنفذ (الافتراضي: {default}): ",
|
233 |
+
"opening_previous_url": "فتح الرابط السابق: {url}",
|
234 |
+
"open_url_manually": "افتح الرابط يدويًا في Colab: {url}",
|
235 |
+
"invalid_previous_url": "رابط سابق غير صالح: {url}، لم يتم فتحه.",
|
236 |
+
"starting_method": "بدء {method} على المنفذ {port}...",
|
237 |
+
"process_stopped": "\n🛑 تم إيقاف العملية من قبل المستخدم",
|
238 |
+
"selected_port": "المنفذ المختار: {port}",
|
239 |
+
"starting_gradio_with_sharing": "بدء Gradio مع المشاركة المدمجة...",
|
240 |
+
"starting_localtunnel": "بدء Localtunnel على المنفذ {port}...",
|
241 |
+
"share_link": "رابط المشاركة: {url}",
|
242 |
+
"password_ip": "كلمة مرور IP: {ip}",
|
243 |
+
"starting_ngrok": "بدء Ngrok على المنفذ {port}...",
|
244 |
+
"ngrok_url": "رابط Ngrok: {url}",
|
245 |
+
"ngrok_error": "خطأ في بدء Ngrok: {error}",
|
246 |
+
"apollo_chunk_size": "حجم قطعة Apollo",
|
247 |
+
"apollo_chunk_size_info": "حجم القطعة لتحسين Apollo (موصى به: 19 للنموذج العام)",
|
248 |
+
"apollo_overlap": "تداخل Apollo",
|
249 |
+
"enhancing_with_apollo": "تحسين مع Apollo ({}/{} ملفات)...",
|
250 |
+
"apollo_processing_completed": "اكتملت معالجة Apollo!",
|
251 |
+
"apollo_overlap_info": "التداخل لتحسين Apollo (موصى به: 2)",
|
252 |
+
"invalid_method": "خطأ: طريقة غير صالحة! استخدم 'gradio'، 'localtunnel'، أو 'ngrok'.",
|
253 |
+
"apollo_enhancement_settings": "إعدادات تحسين Apollo",
|
254 |
+
"enhance_with_apollo": "تحسين مع Apollo",
|
255 |
+
"enhance_with_apollo_info": "تفعيل Apollo لتحسين الصوت بعد الفصل",
|
256 |
+
"apollo_method": "طريقة Apollo",
|
257 |
+
"apollo_method_info": "اختر طريقة المعالجة لـ Apollo",
|
258 |
+
"normal_method": "الطريقة العادية",
|
259 |
+
"mid_side_method": "طريقة الوسط/الجانب",
|
260 |
+
"apollo_normal_model": "نموذج Apollo العادي",
|
261 |
+
"apollo_normal_model_info": "النموذج المستخدم لمعالجة Apollo العادية",
|
262 |
+
"apollo_midside_model": "نموذج Apollo الوسط/الجانب",
|
263 |
+
"apollo_enhancement_info": "تحسين جودة الصوت",
|
264 |
+
"selected_models": "النماذج المختارة",
|
265 |
+
"save_preset": "حفظ الإعداد المسبق",
|
266 |
+
"delete_preset": "حذف الإعداد المسبق",
|
267 |
+
"refresh_presets": "تحديث الإعدادات المسبقة",
|
268 |
+
"preset_name": "اسم الإعداد المسبق",
|
269 |
+
"select_preset": "اختيار إعداد مسبق",
|
270 |
+
"add_favorite": "إضافة إلى المفضلة",
|
271 |
+
"apollo_midside_model_info": "النموذج المستخدم لمعالجة الوسط/الجانب (اختياري)",
|
272 |
+
"language_changed_message": "تم تغيير اللغة. يرجى إعادة تشغيل الخلية.",
|
273 |
+
"apply_matchering": "تطبيق Matchering",
|
274 |
+
"matchering_info": "تطبيق Matchering لتحسين جودة الصوت وتوازنه",
|
275 |
+
"matchering_passes": "تمريرات Matchering",
|
276 |
+
"matchering_passes_info": "عدد التكرارات لـ Matchering (1-5، القيم الأعلى تحسن الجودة ولكن تستغرق وقتًا أطول)",
|
277 |
+
"matchering_processing": "جارٍ تطبيق Matchering... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ اكتمل معالجة Matchering!",
|
279 |
+
"matchering_error": "❌ حدث خطأ أثناء Matchering: {}"
|
280 |
+
}
|
assets/i18n/languages/de_de.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Sprache auswählen",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "Deine ultimative Audio-Trennung",
|
5 |
+
"presented_by": "Präsentiert von Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ Audio-Trennung",
|
7 |
+
"input_model": "📥 Eingabe & Modell",
|
8 |
+
"upload": "🖥 Hochladen",
|
9 |
+
"path": "📂 Pfad",
|
10 |
+
"path_placeholder": "/pfad/zu/audio.wav",
|
11 |
+
"category": "Kategorie",
|
12 |
+
"model": "Modell",
|
13 |
+
"settings": "⚙ Einstellungen",
|
14 |
+
"format": "Format",
|
15 |
+
"chunk_size": "Chunk-Größe",
|
16 |
+
"chunk_size_info": "Nicht ändern, es sei denn, du hast spezifische Anforderungen",
|
17 |
+
"overlap": "Überlappung",
|
18 |
+
"overlap_info": "Empfohlen: 2-10 (Höhere Werte verbessern die Qualität, benötigen aber mehr VRAM)",
|
19 |
+
"tta_boost": "TTA Boost",
|
20 |
+
"tta_info": "Verbessert die Qualität, verlangsamt aber die Verarbeitungsgeschwindigkeit",
|
21 |
+
"phase_fix": "Phasenkorrektur",
|
22 |
+
"phase_fix_info": "Fortgeschrittene Phasenkorrektur für Instrumentalspuren",
|
23 |
+
"instrumental": "Instrumental",
|
24 |
+
"instrumental_info": "Liefert normalerweise 2 Ausgaben, manchmal aber nur eine einzige Ausgabe, du musst es ausprobieren :)",
|
25 |
+
"process": "🚀 Verarbeiten",
|
26 |
+
"reset": "🧹 Zurücksetzen",
|
27 |
+
"status": "Status",
|
28 |
+
"main_tab": "🎧 Haupt",
|
29 |
+
"original": "Original",
|
30 |
+
"vocals": "Gesang",
|
31 |
+
"instrumental_output": "Instrumental",
|
32 |
+
"other": "Andere",
|
33 |
+
"details_tab": "🔍 Details",
|
34 |
+
"male": "Männlich",
|
35 |
+
"female": "Weiblich",
|
36 |
+
"speech": "Sprache",
|
37 |
+
"drums": "Schlagzeug",
|
38 |
+
"bass": "Bass",
|
39 |
+
"effects": "Effekte",
|
40 |
+
"advanced_tab": "⚙ Fortgeschritten",
|
41 |
+
"phase_remix": "Phasen-Remix",
|
42 |
+
"dry": "Trocken",
|
43 |
+
"music": "Musik",
|
44 |
+
"karaoke": "Karaoke",
|
45 |
+
"bleed": "Überlauf",
|
46 |
+
"copy_to_drive": "📂 Auf Laufwerk kopieren",
|
47 |
+
"copy_status": "Kopierstatus",
|
48 |
+
"files_will_be_copied": "Dateien werden hierher kopiert...",
|
49 |
+
"processing_tip": "<b>🔈 Verarbeitungstipp:</b> Für verrauschte Ergebnisse verwende <code>bleed_suppressor_v1</code> oder <code>denoisedebleed</code> Modelle in der Kategorie <i>\"Rauschunterdrückung & Effektentfernung\"</i>, um die Ausgabe zu bereinigen",
|
50 |
+
"waiting_for_processing": "Warten auf Verarbeitung...",
|
51 |
+
"auto_ensemble_tab": "🤖 Auto-Ensemble",
|
52 |
+
"upload_file": "Datei hochladen",
|
53 |
+
"enter_file_path": "Oder Dateipfad eingeben",
|
54 |
+
"file_path_placeholder": "Vollständigen Pfad zur Audiodatei eingeben",
|
55 |
+
"advanced_settings": "⚙️ Fortgeschrittene Einstellungen",
|
56 |
+
"use_tta": "TTA verwenden",
|
57 |
+
"instrumental_only": "Nur Instrumental",
|
58 |
+
"auto_overlap": "Überlappung",
|
59 |
+
"auto_chunk_size": "Chunk-Größe",
|
60 |
+
"output_format": "Ausgabeformat",
|
61 |
+
"model_selection": "🧠 Modellwahl",
|
62 |
+
"model_category": "Modellkategorie",
|
63 |
+
"select_models": "Modelle aus Kategorie auswählen",
|
64 |
+
"ensemble_settings": "⚡ Ensemble-Einstellungen",
|
65 |
+
"method": "Methode",
|
66 |
+
"recommendation": "**Empfehlung:** avg_wave und max_fft liefern die besten Ergebnisse",
|
67 |
+
"start_processing": "🚀 Verarbeitung starten",
|
68 |
+
"original_audio_tab": "🔊 Original-Audio",
|
69 |
+
"original_audio": "Original-Audio",
|
70 |
+
"ensemble_result_tab": "🎚️ Ensemble-Ergebnis",
|
71 |
+
"output_preview": "Ausgabe-Vorschau",
|
72 |
+
"refresh_output": "🔄 Ausgabe aktualisieren",
|
73 |
+
"ensemble_copy_status": "Ensemble-Ausgabe wird hierher kopiert...",
|
74 |
+
"guidelines": "<h4>Richtlinien zur Modellwahl</h4><ul><li><strong>Vermeide das Mischen von Kategorien:</strong> Die Kombination von Gesangs- und Instrumentalmodellen kann unerwünschte Mischungen erzeugen</li><li><strong>Besondere Modellhinweise:</strong><ul><li>Dualitätsmodelle (v1/v2) - Geben beide Stems aus</li><li>MDX23C Separator - Hybride Ergebnisse</li></ul></li><li><strong>Beste Praxis:</strong> Verwende 3-5 ähnliche Modelle aus derselben Kategorie</li></ul><div>💡 Profi-Tipp: Beginne mit der Kombination \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\"</div>",
|
75 |
+
"download_sources_tab": "⬇️ Quellen herunterladen",
|
76 |
+
"direct_links": "🌐 Direkte Links",
|
77 |
+
"audio_file_url": "Audio-Datei-URL",
|
78 |
+
"download_from_url": "⬇️ Von URL herunterladen",
|
79 |
+
"download_status": "Download-Status",
|
80 |
+
"downloaded_file": "Heruntergeladene Datei",
|
81 |
+
"cookie_management": "🍪 Cookie-Verwaltung",
|
82 |
+
"upload_cookies_txt": "Cookies.txt hochladen",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 Warum nötig?**<br>- Zugriff auf altersbeschränkte Inhalte<br>- Herunterladen privater/nicht gelisteter Videos<br>- Umgehen regionaler Einschränkungen<br>- Vermeiden von YouTube-Download-Limits<br><br>**⚠️ Wichtige Hinweise**<br>- TEILE NIEMALS deine Cookie-Dateien!<br>- Aktualisiere Cookies, wenn:<br> • \"403 Forbidden\"-Fehler auftreten<br> • Downloads plötzlich stoppen<br> • \"Sitzung abgelaufen\"-Meldungen erscheinen<br><br>**🔄 Erneuerungsschritte**<br>1. Installiere diese <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">Chrome-Erweiterung</a><br>2. Melde dich bei YouTube in Chrome an<br>3. Klicke auf das Erweiterungssymbol → \"Exportieren\"<br>4. Lade die heruntergeladene Datei hier hoch<br><br>**⏳ Cookie-Lebensdauer**<br>- Normale Sitzungen: 24 Stunden<br>- Sensible Operationen: 1 Stunde<br>- Passwortänderungen: Sofortige Ungültigkeit</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ Manuelles Ensemble",
|
85 |
+
"input_sources": "📂 Eingabequellen",
|
86 |
+
"refresh": "🔄 Aktualisieren",
|
87 |
+
"ensemble_algorithm": "Ensemble-Algorithmus",
|
88 |
+
"select_audio_files": "Audiodateien auswählen",
|
89 |
+
"available_files": "Verfügbare Dateien",
|
90 |
+
"custom_weights": "Benutzerdefinierte Gewichte (durch Kommas getrennt)",
|
91 |
+
"custom_weights_placeholder": "Beispiel: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "Leer lassen für gleiche Gewichte",
|
93 |
+
"result_preview_tab": "🎧 Ergebnisvorschau",
|
94 |
+
"ensembled_output": "Ensemble-Ausgabe",
|
95 |
+
"processing_log_tab": "📋 Verarbeitungsprotokoll",
|
96 |
+
"processing_details": "Verarbeitungsdetails",
|
97 |
+
"process_ensemble": "⚡ Ensemble verarbeiten",
|
98 |
+
"languages_tab": "🌐 Sprachen",
|
99 |
+
"Vocal Models": "Gesangsmodelle",
|
100 |
+
"Instrumental Models": "Instrumentalmodelle",
|
101 |
+
"4-Stem Models": "4-Stem-Modelle",
|
102 |
+
"Denoise Models": "Rauschunterdrückungsmodelle",
|
103 |
+
"Dereverb Models": "Hallentfernungsmodelle",
|
104 |
+
"Other Models": "Andere Modelle",
|
105 |
+
"ensemble_files_description": "Kombiniert mehrere Audiodateien zu einer einzigen Ausgabe unter Verwendung spezifizierter Ensemble-Methoden.",
|
106 |
+
"ensemble_files_help": "Pfad zu allen Audiodateien für das Ensemble",
|
107 |
+
"ensemble_type_help": "Einer von avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "Gewichte zur Erstellung des Ensembles. Die Anzahl der Gewichte muss der Anzahl der Dateien entsprechen",
|
109 |
+
"ensemble_output_help": "Pfad zur WAV-Datei, in der das Ensemble-Ergebnis gespeichert wird",
|
110 |
+
"ensemble_type_print": "Ensemble-Typ: {}",
|
111 |
+
"num_input_files_print": "Anzahl der Eingabedateien: {}",
|
112 |
+
"weights_print": "Gewichte: {}",
|
113 |
+
"output_file_print": "Ausgabedatei: {}",
|
114 |
+
"duration_mismatch_error": "Alle Dateien müssen die gleiche Dauer haben",
|
115 |
+
"file_not_found_error": "Fehler. Datei nicht gefunden: {}. Überprüfe die Pfade.",
|
116 |
+
"reading_chunk_print": "Lese Chunk aus Datei: {} (Start: {}s, Dauer: {}s)",
|
117 |
+
"chunk_result_shape_print": "Chunk-Ergebnisform: {}",
|
118 |
+
"ensemble_completed_print": "Ensemble abgeschlossen. Ausgabe gespeichert unter: {}",
|
119 |
+
"file_deletion_error": "{} konnte nicht gelöscht werden: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ Verzeichnis existiert nicht: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ Pfad ist kein Verzeichnis: {}",
|
122 |
+
"item_deletion_error": "⚠️ Fehler beim Löschen von {}: {}",
|
123 |
+
"old_output_not_exist": "❌ Alter Ausgabeordner existiert nicht",
|
124 |
+
"old_outputs_cleared": "✅ Alte Ausgaben erfolgreich gelöscht!",
|
125 |
+
"error": "🔥 Fehler: {}",
|
126 |
+
"ffmpeg_error": "FFmpeg-Fehler ({}): {}",
|
127 |
+
"file_saved_successfully": "Datei erfolgreich gespeichert: {}",
|
128 |
+
"total_files_found": "Gesamtzahl gefundener Dateien: {}. Verwende Abtastrate: {}",
|
129 |
+
"total_progress": "Gesamtfortschritt",
|
130 |
+
"detailed_pbar_enabled": "Detaillierter Fortschrittsbalken aktiviert: {}",
|
131 |
+
"loaded_audio": "Geladenes Audio: {}, Form: {}",
|
132 |
+
"cannot_read_track": "Spur kann nicht gelesen werden: {}",
|
133 |
+
"error_message": "Fehlermeldung: {}",
|
134 |
+
"demudding_track": "Spur entmischen (Phasen-Remix - Instrumental): {}",
|
135 |
+
"elapsed_time": "Verstrichene Zeit: {:.2f} Sekunden.",
|
136 |
+
"proc_folder_description": "Verarbeitet Audiodateien in einem Ordner mit einem spezifizierten Modell.",
|
137 |
+
"model_type_help": "Modelltyp (bandit, bs_roformer, mdx23c, etc.)",
|
138 |
+
"config_path_help": "Pfad zur Konfigurationsdatei",
|
139 |
+
"demud_phaseremix_help": "Phasen-Remix für Instrumental aktivieren",
|
140 |
+
"start_checkpoint_help": "Initialer Checkpoint für gültige Gewichte",
|
141 |
+
"input_folder_help": "Ordner mit Mischungen zur Verarbeitung",
|
142 |
+
"audio_path_help": "Pfad zu einer einzelnen Audiodatei zur Verarbeitung",
|
143 |
+
"store_dir_help": "Pfad zum Speichern der Ergebnisse",
|
144 |
+
"device_ids_help": "Liste der GPU-IDs",
|
145 |
+
"extract_instrumental_help": "Gesang invertieren, um Instrumental zu erhalten, falls vorhanden",
|
146 |
+
"disable_detailed_pbar_help": "Detaillierten Fortschrittsbalken in Demix deaktivieren",
|
147 |
+
"force_cpu_help": "CPU erzwingen, selbst wenn CUDA verfügbar ist",
|
148 |
+
"flac_file_help": "FLAC-Datei anstelle von WAV ausgeben",
|
149 |
+
"export_format_help": "Exportformat und PCM-Typ",
|
150 |
+
"pcm_type_help": "PCM-Typ für FLAC-Dateien",
|
151 |
+
"use_tta_help": "Testzeit-Augmentation aktivieren",
|
152 |
+
"lora_checkpoint_help": "Initialer Checkpoint für LoRA-Gewichte",
|
153 |
+
"cuda_available": "CUDA ist verfügbar, verwende --force_cpu, um es zu deaktivieren.",
|
154 |
+
"using_device": "Verwendetes Gerät: {}",
|
155 |
+
"instruments_print": "Instrumente: {}",
|
156 |
+
"model_load_time": "Modell-Ladezeit: {:.2f} Sek.",
|
157 |
+
"invalid_url": "❌ Ungültige URL",
|
158 |
+
"cookie_file_updated": "✅ Cookie-Datei aktualisiert!",
|
159 |
+
"cookie_installation_error": "⚠️ Fehler bei der Cookie-Installation: {}",
|
160 |
+
"file_size_zero_error": "Dateigröße null oder Datei nicht erstellt",
|
161 |
+
"google_drive_error": "❌ Google Drive Download-Fehler: {}",
|
162 |
+
"wav_conversion_failed": "WAV-Konvertierung fehlgeschlagen",
|
163 |
+
"download_error": "❌ Download-Fehler: {}",
|
164 |
+
"download_success": "🎉 Erfolgreich heruntergeladen!",
|
165 |
+
"download_failed": "❌ Download fehlgeschlagen",
|
166 |
+
"no_output_files_found": "❌ Keine Ausgabedateien gefunden.",
|
167 |
+
"output_refreshed_successfully": "✅ Ausgabe erfolgreich aktualisiert!",
|
168 |
+
"error_refreshing_output": "❌ Fehler beim Aktualisieren der Ausgabe: {}",
|
169 |
+
"starting_audio_separation": "Audio-Trennung wird gestartet...",
|
170 |
+
"processing_audio": "Audio wird verarbeitet",
|
171 |
+
"separating_audio": "Audio wird getrennt... ({:.1f}%)",
|
172 |
+
"separation_complete": "Trennung abgeschlossen!",
|
173 |
+
"progress_parsing_error": "Fortschrittsanalyse-Fehler: {}",
|
174 |
+
"error_occurred": "Ein Fehler ist aufgetreten: {}",
|
175 |
+
"separation_process_completed": "Trennungsprozess abgeschlossen!",
|
176 |
+
"no_audio_file_error": "❌ Keine Audiodatei bereitgestellt und keine vorhandene Datei im Eingabeordner.",
|
177 |
+
"no_input_progress_label": "Fehler: Keine Eingabe bereitgestellt -- 0.0%",
|
178 |
+
"processing_audio_print": "Verarbeite Audio von: {} mit Modell: {}",
|
179 |
+
"starting_audio_separation_progress_label": "Audio-Trennung wird gestartet... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "Audio wird getrennt... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "Audioverarbeitung abgeschlossen! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ Audioverarbeitung abgeschlossen!",
|
183 |
+
"error_occurred_progress_label": "Fehler aufgetreten -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ Mindestens 2 Dateien erforderlich",
|
185 |
+
"valid_files_not_found": "❌ Gültige Dateien nicht gefunden",
|
186 |
+
"starting_ensemble_process": "Ensemble-Prozess wird gestartet...",
|
187 |
+
"ensembling_progress": "Ensemble wird erstellt... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "Ensemble-Ausgabe wird finalisiert...",
|
189 |
+
"success_log": "✅ Erfolg!\n{}",
|
190 |
+
"error_log": "❌ Fehler!\n{}",
|
191 |
+
"critical_error": "⛔ Kritischer Fehler: {}",
|
192 |
+
"ensemble_process_completed": "Ensemble-Prozess abgeschlossen!",
|
193 |
+
"no_models_selected": "❌ Keine Modelle ausgewählt",
|
194 |
+
"no_input_audio_provided": "❌ Kein Eingabe-Audio bereitgestellt",
|
195 |
+
"loading_model": "Lade Modell {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "Lade Modell {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "Abgeschlossenes Modell {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "Abgeschlossenes Modell {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "Führe Befehl aus: {}",
|
200 |
+
"model_failed": "Modell {} fehlgeschlagen: {}",
|
201 |
+
"critical_error_with_model": "Kritischer Fehler mit {}: {}",
|
202 |
+
"model_output_failed": "{} konnte keine Ausgabe erzeugen",
|
203 |
+
"waiting_for_files": "Warten auf die Bereitschaft aller Dateien...",
|
204 |
+
"waiting_for_files_progress_label": "Warten auf die Bereitschaft aller Dateien... -- 90.0%",
|
205 |
+
"performing_ensemble": "Ensemble wird durchgeführt...",
|
206 |
+
"performing_ensemble_progress_label": "Ensemble wird durchgeführt... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "Speicherauslastung vor Ensemble: {}%",
|
208 |
+
"memory_usage_after_ensemble": "Speicherauslastung nach Ensemble: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "Ensemble-Ausgabe wird finalisiert... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "Ensemble-Datei konnte nicht erstellt werden: {}",
|
211 |
+
"ensemble_completed_progress_label": "Ensemble erfolgreich abgeschlossen! -- 100.0%",
|
212 |
+
"success_output_created": "✅ Erfolg! Ausgabedatei erstellt.",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive eingebunden. Ensemble-Ausgabe wird kopiert...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive bereits eingebunden. Ensemble-Ausgabe wird kopiert...",
|
215 |
+
"no_ensemble_output_files_found": "❌ Keine Ensemble-Ausgabedateien gefunden.",
|
216 |
+
"ensemble_output_copied": "✅ Ensemble-Ausgabe kopiert nach {}",
|
217 |
+
"error_copying_ensemble_output": "❌ Fehler beim Kopieren der Ensemble-Ausgabe: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive eingebunden. Dateien werden kopiert...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive bereits eingebunden. Dateien werden kopiert...",
|
220 |
+
"files_copied_to_drive": "✅ Dateien kopiert nach {}",
|
221 |
+
"error_copying_files": "❌ Fehler beim Kopieren der Dateien: {}",
|
222 |
+
"mounting_drive": "Google Drive wird eingebunden...",
|
223 |
+
"settings_saved": "Einstellungen in config.json gespeichert: Sprache={lang}, Methode={method}, Port={port}",
|
224 |
+
"selected_language": "Ausgewählte Sprache: {lang}",
|
225 |
+
"available_languages": "Verfügbare Sprachen: {langs}",
|
226 |
+
"select_language_prompt": "Wähle eine Sprache (Standard: {default}): ",
|
227 |
+
"invalid_language": "Ungültige Sprachauswahl! Verwende Standardsprache ({default}).",
|
228 |
+
"available_sharing_methods": "Verfügbare Freigabemethoden: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "Wähle eine Freigabemethode (Standard: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "Gib deinen Ngrok-Token ein (Standard: {default}): ",
|
231 |
+
"ngrok_token_required": "Fehler: Ngrok-Token ist für die ngrok-Methode erforderlich!",
|
232 |
+
"enter_port_prompt": "Gib die Portnummer ein (Standard: {default}): ",
|
233 |
+
"opening_previous_url": "Öffne vorherige URL: {url}",
|
234 |
+
"open_url_manually": "Öffne die URL manuell in Colab: {url}",
|
235 |
+
"invalid_previous_url": "Ungültige vorherige URL: {url}, nicht geöffnet.",
|
236 |
+
"starting_method": "Starte {method} auf Port {port}...",
|
237 |
+
"process_stopped": "\n🛑 Prozess vom Benutzer gestoppt",
|
238 |
+
"selected_port": "Ausgewählter Port: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Starte Gradio mit integrierter Freigabe...",
|
240 |
+
"starting_localtunnel": "Starte Localtunnel auf Port {port}...",
|
241 |
+
"share_link": "Freigabe-Link: {url}",
|
242 |
+
"password_ip": "Passwort-IP: {ip}",
|
243 |
+
"starting_ngrok": "Starte Ngrok auf Port {port}...",
|
244 |
+
"ngrok_url": "Ngrok-URL: {url}",
|
245 |
+
"ngrok_error": "Fehler beim Starten von Ngrok: {error}",
|
246 |
+
"apollo_chunk_size": "Apollo Chunk-Größe",
|
247 |
+
"apollo_chunk_size_info": "Chunk-Größe für Apollo-Verbesserung (empfohlen: 19 für Universalmodell)",
|
248 |
+
"apollo_overlap": "Apollo-Überlappung",
|
249 |
+
"enhancing_with_apollo": "Verbessere mit Apollo ({}/{} Dateien)...",
|
250 |
+
"apollo_processing_completed": "Apollo-Verarbeitung abgeschlossen!",
|
251 |
+
"apollo_overlap_info": "Überlappung für Apollo-Verbesserung (empfohlen: 2)",
|
252 |
+
"invalid_method": "Fehler: Ungültige Methode! Verwende 'gradio', 'localtunnel' oder 'ngrok'.",
|
253 |
+
"apollo_enhancement_settings": "Apollo-Verbesserungseinstellungen",
|
254 |
+
"enhance_with_apollo": "Mit Apollo verbessern",
|
255 |
+
"enhance_with_apollo_info": "Apollo für Audioverbesserung nach der Trennung aktivieren",
|
256 |
+
"apollo_method": "Apollo-Methode",
|
257 |
+
"apollo_method_info": "Wähle die Verarbeitungsmethode für Apollo",
|
258 |
+
"normal_method": "Normale Methode",
|
259 |
+
"mid_side_method": "Mitte/Seite-Methode",
|
260 |
+
"apollo_normal_model": "Apollo Normalmodell",
|
261 |
+
"apollo_normal_model_info": "Modell für normale Apollo-Verarbeitung",
|
262 |
+
"apollo_midside_model": "Apollo Mitte/Seite-Modell",
|
263 |
+
"apollo_enhancement_info": "Verbesserung der Klangqualität",
|
264 |
+
"selected_models": "Ausgewählte Modelle",
|
265 |
+
"save_preset": "Voreinstellung Speichern",
|
266 |
+
"delete_preset": "Voreinstellung Löschen",
|
267 |
+
"refresh_presets": "Voreinstellungen Aktualisieren",
|
268 |
+
"preset_name": "Name der Voreinstellung",
|
269 |
+
"select_preset": "Voreinstellung Auswählen",
|
270 |
+
"add_favorite": "Zu Favoriten Hinzufügen",
|
271 |
+
"apollo_midside_model_info": "Modell für Mitte/Seite-Verarbeitung (optional)",
|
272 |
+
"language_changed_message": "Sprache geändert. Bitte starte die Zelle neu.",
|
273 |
+
"apply_matchering": "Matchering anwenden",
|
274 |
+
"matchering_info": "Matchering anwenden, um Audio-Mastering und -Balance zu verbessern",
|
275 |
+
"matchering_passes": "Matchering-Durchgänge",
|
276 |
+
"matchering_passes_info": "Anzahl der Matchering-Iterationen (1-5, höhere Werte verbessern die Qualität, dauern aber länger)",
|
277 |
+
"matchering_processing": "Matchering wird angewendet... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ Matchering-Verarbeitung abgeschlossen!",
|
279 |
+
"matchering_error": "❌ Fehler während Matchering: {}"
|
280 |
+
}
|
assets/i18n/languages/en_us.json
ADDED
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Select Language",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "Your Ultimate Audio Separation",
|
5 |
+
"presented_by": "Presented by Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ Audio Separation",
|
7 |
+
"input_model": "📥 Input & Model",
|
8 |
+
"upload": "🖥 Upload",
|
9 |
+
"path": "📂 Path",
|
10 |
+
"path_placeholder": "/path/to/audio.wav",
|
11 |
+
"category": "Category",
|
12 |
+
"model": "Model",
|
13 |
+
"settings": "⚙ Settings",
|
14 |
+
"format": "Format",
|
15 |
+
"chunk_size": "Chunk Size",
|
16 |
+
"chunk_size_info": "Don't change unless you have specific requirements",
|
17 |
+
"overlap": "Overlap",
|
18 |
+
"overlap_info": "Recommended: 2-10 (Higher values increase quality but require more VRAM)",
|
19 |
+
"tta_boost": "TTA Boost",
|
20 |
+
"phase_fix": "Phase Fix",
|
21 |
+
"use_phase_correction": "Apply Advanced Phase Correction",
|
22 |
+
"phase_fix_info": "Advanced phase correction for instrumental tracks",
|
23 |
+
"instrumental": "Instrumental",
|
24 |
+
"process": "🚀 Process",
|
25 |
+
"reset": "🧹 Reset",
|
26 |
+
"status": "Status",
|
27 |
+
"main_tab": "🎧 Main",
|
28 |
+
"original": "Original",
|
29 |
+
"vocals": "Vocals",
|
30 |
+
"instrumental_output": "Instrumental",
|
31 |
+
"other": "Other",
|
32 |
+
"details_tab": "🔍 Details",
|
33 |
+
"male": "Male",
|
34 |
+
"female": "Female",
|
35 |
+
"speech": "Speech",
|
36 |
+
"drums": "Drums",
|
37 |
+
"bass": "Bass",
|
38 |
+
"effects": "Effects",
|
39 |
+
"advanced_tab": "⚙ Advanced",
|
40 |
+
"phase_remix": "Phase Remix",
|
41 |
+
"dry": "Dry",
|
42 |
+
"music": "Music",
|
43 |
+
"karaoke": "Karaoke",
|
44 |
+
"bleed": "Bleed",
|
45 |
+
"copy_to_drive": "📂 Copy to Drive",
|
46 |
+
"copy_status": "Copy Status",
|
47 |
+
"files_will_be_copied": "Files will be copied here...",
|
48 |
+
"processing_tip": "<b>🔈 Processing Tip:</b> For noisy results, use <code>bleed_suppressor_v1</code> or <code>denoisedebleed</code> models in the <i>\"Denoise & Effect Removal\"</i> category to clean the output",
|
49 |
+
"waiting_for_processing": "Waiting for processing...",
|
50 |
+
"auto_ensemble_tab": "🤖 Auto Ensemble",
|
51 |
+
"upload_file": "Upload file",
|
52 |
+
"enter_file_path": "Or enter file path",
|
53 |
+
"file_path_placeholder": "Enter full path to audio file",
|
54 |
+
"advanced_settings": "⚙️ Advanced Settings",
|
55 |
+
"use_tta": "Use TTA",
|
56 |
+
"instrumental_only": "Instrumental Only",
|
57 |
+
"auto_overlap": "Overlap",
|
58 |
+
"auto_chunk_size": "Chunk Size",
|
59 |
+
"output_format": "Output Format",
|
60 |
+
"model_selection": "🧠 Model Selection",
|
61 |
+
"model_category": "Model Category",
|
62 |
+
"select_models": "Select Models from Category",
|
63 |
+
"ensemble_settings": "⚡ Ensemble Settings",
|
64 |
+
"method": "Method",
|
65 |
+
"recommendation": "**Recommendation:** avg_wave and max_fft best results",
|
66 |
+
"start_processing": "🚀 Start Processing",
|
67 |
+
"original_audio_tab": "🔊 Original Audio",
|
68 |
+
"original_audio": "Original Audio",
|
69 |
+
"ensemble_result_tab": "🎚️ Ensemble Result",
|
70 |
+
"output_preview": "Output Preview",
|
71 |
+
"refresh_output": "🔄 Refresh Output",
|
72 |
+
"ensemble_copy_status": "Ensemble output will be copied here...",
|
73 |
+
"guidelines": "<h4>Model Selection Guidelines</h4><ul><li><strong>Avoid cross-category mixing:</strong> Combining vocal and instrumental models may create unwanted blends</li><li><strong>Special model notes:</strong><ul><li>Duality models (v1/v2) - Output both stems</li><li>MDX23C Separator - Hybrid results</li></ul></li><li><strong>Best practice:</strong> Use 3-5 similar models from same category</li></ul><div>💡 Pro Tip: Start with \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\" combination</div>",
|
74 |
+
"download_sources_tab": "⬇️ Download Sources",
|
75 |
+
"direct_links": "🌐 Direct Links",
|
76 |
+
"audio_file_url": "Audio File URL",
|
77 |
+
"download_from_url": "⬇️ Download from URL",
|
78 |
+
"download_status": "Download Status",
|
79 |
+
"downloaded_file": "Downloaded File",
|
80 |
+
"cookie_management": "🍪 Cookie Management",
|
81 |
+
"upload_cookies_txt": "Upload Cookies.txt",
|
82 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 Why Needed?**<br>- Access age-restricted content<br>- Download private/unlisted videos<br>- Bypass regional restrictions<br>- Avoid YouTube download limits<br><br>**⚠️ Important Notes**<br>- NEVER share your cookie files!<br>- Refresh cookies when:<br> • Getting \"403 Forbidden\" errors<br> • Downloads suddenly stop<br> • Seeing \"Session expired\" messages<br><br>**🔄 Renewal Steps**<br>1. Install this <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">Chrome extension</a><br>2. Login to YouTube in Chrome<br>3. Click extension icon → \"Export\"<br>4. Upload the downloaded file here<br><br>**⏳ Cookie Lifespan**<br>- Normal sessions: 24 hours<br>- Sensitive operations: 1 hour<br>- Password changes: Immediate invalidation</div>",
|
83 |
+
"manual_ensemble_tab": "🎚️ Manual Ensemble",
|
84 |
+
"input_sources": "📂 Input Sources",
|
85 |
+
"refresh": "🔄 Refresh",
|
86 |
+
"ensemble_algorithm": "Ensemble Algorithm",
|
87 |
+
"select_audio_files": "Select Audio Files",
|
88 |
+
"available_files": "Available Files",
|
89 |
+
"custom_weights": "Custom Weights (comma separated)",
|
90 |
+
"custom_weights_placeholder": "Example: 0.8, 1.2, 1.0, ...",
|
91 |
+
"custom_weights_info": "Leave empty for equal weights",
|
92 |
+
"result_preview_tab": "🎧 Result Preview",
|
93 |
+
"ensembled_output": "Ensembled Output",
|
94 |
+
"processing_log_tab": "📋 Processing Log",
|
95 |
+
"processing_details": "Processing Details",
|
96 |
+
"process_ensemble": "⚡ Process Ensemble",
|
97 |
+
"languages_tab": "🌐 Languages",
|
98 |
+
"Vocal Models": "Vocal Models",
|
99 |
+
"Instrumental Models": "Instrumental Models",
|
100 |
+
"4-Stem Models": "4-Stem Models",
|
101 |
+
"Denoise Models": "Denoise Models",
|
102 |
+
"Dereverb Models": "Dereverb Models",
|
103 |
+
"Other Shapes": "Other Models",
|
104 |
+
"ensemble_files_description": "Combines multiple audio files into a single output using specified ensemble methods.",
|
105 |
+
"ensemble_files_help": "Path to all audio-files to ensemble",
|
106 |
+
"ensemble_type_help": "One of avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
107 |
+
"ensemble_weights_help": "Weights to create ensemble. Number of weights must be equal to number of files",
|
108 |
+
"ensemble_output_help": "Path to wav file where ensemble result will be stored",
|
109 |
+
"ensemble_type_print": "Ensemble type: {}",
|
110 |
+
"num_input_files_print": "Number of input files: {}",
|
111 |
+
"weights_print": "Weights: {}",
|
112 |
+
"output_file_print": "Output file: {}",
|
113 |
+
"duration_mismatch_error": "All files must have the same duration",
|
114 |
+
"file_not_found_error": "Error. Can't find file: {}. Check paths.",
|
115 |
+
"reading_chunk_print": "Reading chunk from file: {} (start: {}s, duration: {}s)",
|
116 |
+
"chunk_result_shape_print": "Chunk result shape: {}",
|
117 |
+
"ensemble_completed_print": "Ensemble completed. Output saved to: {}",
|
118 |
+
"file_deletion_error": "{} could not be deleted: {}",
|
119 |
+
"directory_not_exist_warning": "⚠️ Directory does not exist: {}",
|
120 |
+
"not_a_directory_warning": "⚠️ Path is not a directory: {}",
|
121 |
+
"item_deletion_error": "⚠️ Error deleting {}: {}",
|
122 |
+
"critical_error": "❌ Critical error: {}",
|
123 |
+
"old_output_not_exist": "❌ Old output folder does not exist",
|
124 |
+
"old_outputs_cleared": "✅ Old outputs successfully cleared!",
|
125 |
+
"error": "🔥 Error: {}",
|
126 |
+
"ffmpeg_error": "FFmpeg Error ({}): {}",
|
127 |
+
"file_saved_successfully": "File saved successfully: {}",
|
128 |
+
"total_files_found": "Total files found: {}. Using sample rate: {}",
|
129 |
+
"total_progress": "Total progress",
|
130 |
+
"detailed_pbar_enabled": "Detailed progress bar enabled: {}",
|
131 |
+
"loaded_audio": "Loaded audio: {}, shape: {}",
|
132 |
+
"cannot_read_track": "Cannot read track: {}",
|
133 |
+
"error_message": "Error message: {}",
|
134 |
+
"demudding_track": "Demudding track (phase remix - instrumental): {}",
|
135 |
+
"elapsed_time": "Elapsed time: {:.2f} seconds.",
|
136 |
+
"proc_folder_description": "Processes audio files in a folder using a specified model.",
|
137 |
+
"model_type_help": "Model type (bandit, bs_roformer, mdx23c, etc.)",
|
138 |
+
"config_path_help": "Path to config file",
|
139 |
+
"demud_phaseremix_help": "Enable phase remix for instrumental",
|
140 |
+
"start_checkpoint_help": "Initial checkpoint to valid weights",
|
141 |
+
"input_folder_help": "Folder with mixtures to process",
|
142 |
+
"audio_path_help": "Path to a single audio file to process",
|
143 |
+
"store_dir_help": "Path to store results",
|
144 |
+
"device_ids_help": "List of GPU IDs",
|
145 |
+
"extract_instrumental_help": "Invert vocals to get instrumental if provided",
|
146 |
+
"disable_detailed_pbar_help": "Disable detailed progress bar in demix",
|
147 |
+
"force_cpu_help": "Force the use of CPU even if CUDA is available",
|
148 |
+
"flac_file_help": "Output flac file instead of wav",
|
149 |
+
"export_format_help": "Export format and PCM type",
|
150 |
+
"pcm_type_help": "PCM type for FLAC files",
|
151 |
+
"use_tta_help": "Enable test time augmentation",
|
152 |
+
"lora_checkpoint_help": "Initial checkpoint to LoRA weights",
|
153 |
+
"cuda_available": "CUDA is available, use --force_cpu to disable it.",
|
154 |
+
"using_device": "Using device: {}",
|
155 |
+
"instruments_print": "Instruments: {}",
|
156 |
+
"model_load_time": "Model load time: {:.2f} sec",
|
157 |
+
"invalid_url": "❌ Invalid URL",
|
158 |
+
"cookie_file_updated": "✅ Cookie file updated!",
|
159 |
+
"cookie_installation_error": "⚠️ Cookie installation error: {}",
|
160 |
+
"google_drive_mount_error": "❌ Google Drive linking error: {}",
|
161 |
+
"file_size_zero_error": "File size zero or file not created",
|
162 |
+
"google_drive_error": "❌ Google Drive download error: {}",
|
163 |
+
"wav_conversion_failed": "WAV conversion failed",
|
164 |
+
"download_error": "❌ Download error: {}",
|
165 |
+
"file_copied_to_drive": "File copied to Google Drive: {}",
|
166 |
+
"copy_to_drive_error": "❌ Error copying to Google Drive: {}",
|
167 |
+
"direct_download_failed": "Failed to download the file directly",
|
168 |
+
"download_success": "🎉 Downloaded successfully!",
|
169 |
+
"download_failed": "❌ Download failed",
|
170 |
+
"no_output_files_found": "❌ No output files found.",
|
171 |
+
"output_refreshed_successfully": "✅ Output refreshed successfully!",
|
172 |
+
"error_refreshing_output": "❌ Error refreshing output: {}",
|
173 |
+
"starting_audio_separation": "Starting audio separation...",
|
174 |
+
"processing_audio": "Processing audio",
|
175 |
+
"separating_audio": "Separating audio... ({:.1f}%)",
|
176 |
+
"separation_complete": "Separation complete!",
|
177 |
+
"progress_parsing_error": "Progress parsing error: {}",
|
178 |
+
"error_occurred": "An error occurred: {}",
|
179 |
+
"separation_process_completed": "Separation process completed!",
|
180 |
+
"no_audio_file_error": "❌ No audio file provided and no existing file in input directory.",
|
181 |
+
"no_input_progress_label": "Error: No input provided -- 0.0%",
|
182 |
+
"processing_audio_print": "Processing audio from: {} using model: {}",
|
183 |
+
"starting_audio_separation_progress_label": "Starting audio separation... -- 0.0%",
|
184 |
+
"separating_audio_progress_label": "Separating audio... -- {}.0%",
|
185 |
+
"audio_processing_completed_progress_label": "Audio processing completed! -- 100.0%",
|
186 |
+
"audio_processing_completed": "✅ Audio processing completed!",
|
187 |
+
"error_occurred_progress_label": "Error occurred -- 0.0%",
|
188 |
+
"minimum_files_required": "⚠️ Minimum 2 files required",
|
189 |
+
"valid_files_not_found": "❌ Valid files not found",
|
190 |
+
"starting_ensemble_process": "Starting ensemble process...",
|
191 |
+
"ensembling_progress": "Ensembling... ({:.1f}%)",
|
192 |
+
"finalizing_ensemble_output": "Finalizing ensemble output...",
|
193 |
+
"success_log": "✅ Success!\n{}",
|
194 |
+
"error_log": "❌ Error!\n{}",
|
195 |
+
"ensemble_process_completed": "Ensemble process completed!",
|
196 |
+
"no_models_selected": "❌ No models selected",
|
197 |
+
"no_input_audio_provided": "❌ No input audio provided",
|
198 |
+
"loading_model": "Loading model {}/{}: {}...",
|
199 |
+
"loading_model_progress_label": "Loading model {}/{}: {}... -- {}.0%",
|
200 |
+
"completed_model": "Completed model {}/{}: {}",
|
201 |
+
"completed_model_progress_label": "Completed model {}/{}: {} -- {}.0%",
|
202 |
+
"running_command": "Running command: {}",
|
203 |
+
"model_failed": "Model {} failed: {}",
|
204 |
+
"critical_error_with_model": "Critical error with {}: {}",
|
205 |
+
"model_output_failed": "{} failed to produce output",
|
206 |
+
"waiting_for_files": "Waiting for all files to be ready...",
|
207 |
+
"waiting_for_files_progress_label": "Waiting for all files to be ready... -- 90.0%",
|
208 |
+
"performing_ensemble": "Performing ensemble...",
|
209 |
+
"performing_ensemble_progress_label": "Performing ensemble... -- 92.0%",
|
210 |
+
"memory_usage_before_ensemble": "Memory usage before ensemble: {}%",
|
211 |
+
"memory_usage_after_ensemble": "Memory usage after ensemble: {}%",
|
212 |
+
"finalizing_ensemble_output_progress_label": "Finalizing ensemble output... -- 98.0%",
|
213 |
+
"ensemble_file_creation_failed": "Ensemble file could not be created: {}",
|
214 |
+
"ensemble_completed_progress_label": "Ensemble completed successfully! -- 100.0%",
|
215 |
+
"success_output_created": "✅ Success! Output file created.",
|
216 |
+
"drive_mounted_copying_ensemble": "Google Drive mounted. Copying ensemble output...",
|
217 |
+
"drive_already_mounted_copying_ensemble": "Google Drive already mounted. Copying ensemble output...",
|
218 |
+
"no_ensemble_output_files_found": "❌ No ensemble output files found.",
|
219 |
+
"ensemble_output_copied": "✅ Ensemble output copied to {}",
|
220 |
+
"error_copying_ensemble_output": "❌ Error copying ensemble output: {}",
|
221 |
+
"drive_mounted_copying_files": "Google Drive mounted. Copying files...",
|
222 |
+
"drive_already_mounted_copying_files": "Google Drive already mounted. Copying files...",
|
223 |
+
"files_copied_to_drive": "✅ Files copied to {}",
|
224 |
+
"error_copying_files": "❌ Error copying files: {}",
|
225 |
+
"mounting_drive": "Mounting Google Drive...",
|
226 |
+
"settings_saved": "Settings saved to config.json: Language={lang}, Method={method}, Port={port}",
|
227 |
+
"selected_language": "Selected language: {lang}",
|
228 |
+
"available_languages": "Available languages: {langs}",
|
229 |
+
"select_language_prompt": "Select a language (default: {default}): ",
|
230 |
+
"invalid_language": "Invalid language selection! Using default language ({default}).",
|
231 |
+
"available_sharing_methods": "Available sharing methods: gradio, localtunnel, ngrok",
|
232 |
+
"select_sharing_method_prompt": "Choose a sharing method (default: {default}): ",
|
233 |
+
"enter_ngrok_token_prompt": "Enter your Ngrok token (default: {default}): ",
|
234 |
+
"ngrok_token_required": "Error: Ngrok token is required for ngrok method!",
|
235 |
+
"enter_port_prompt": "Enter port number (default: {default}): ",
|
236 |
+
"opening_previous_url": "Opening previous URL: {url}",
|
237 |
+
"open_url_manually": "Manually open the URL in Colab: {url}",
|
238 |
+
"invalid_previous_url": "Invalid previous URL: {url}, not opened.",
|
239 |
+
"starting_method": "Starting {method} on port {port}...",
|
240 |
+
"process_stopped": "\n🛑 Process stopped by user",
|
241 |
+
"selected_port": "Selected port: {port}",
|
242 |
+
"starting_gradio_with_sharing": "Starting Gradio with built-in sharing...",
|
243 |
+
"starting_localtunnel": "Starting Localtunnel on port {port}...",
|
244 |
+
"share_link": "Share Link: {url}",
|
245 |
+
"password_ip": "Password IP: {ip}",
|
246 |
+
"starting_ngrok": "Starting Ngrok on port {port}...",
|
247 |
+
"ngrok_url": "Ngrok URL: {url}",
|
248 |
+
"ngrok_error": "Error starting ngrok: {error}",
|
249 |
+
"auto_apollo_chunk_size": "Apollo Chunk Size",
|
250 |
+
"auto_apollo_chunk_size_info": "Chunk size for Apollo enhancement (recommended: 19 for Universal Model)",
|
251 |
+
"auto_apollo_overlap": "Apollo Overlap",
|
252 |
+
"auto_enhancing_with_apollo": "Enhancing with Apollo ({}/{} files)...",
|
253 |
+
"auto_apollo_processing_completed": "Apollo processing completed!",
|
254 |
+
"auto_apollo_overlap_info": "Overlap for Apollo enhancement (recommended: 2)",
|
255 |
+
"apollo_chunk_size": "Apollo Chunk Size",
|
256 |
+
"apollo_chunk_size_info": "Chunk size for Apollo enhancement (recommended: 19 for Universal Model)",
|
257 |
+
"apollo_overlap": "Apollo Overlap",
|
258 |
+
"enhance_with_apollo": "Enhance With Apollo",
|
259 |
+
"apollo_enhancement_info": "Audio quality enhancement",
|
260 |
+
"enhancing_with_apollo": "Enhancing with Apollo ({}/{} files)...",
|
261 |
+
"apollo_processing_completed": "Apollo processing completed!",
|
262 |
+
"apollo_overlap_info": "Overlap for Apollo enhancement (recommended: 2)",
|
263 |
+
"selected_models": "Selected Models",
|
264 |
+
"save_preset": "Save Preset",
|
265 |
+
"delete_preset": "Delete Preset",
|
266 |
+
"refresh_presets": "Refresh Presets",
|
267 |
+
"preset_name": "Preset Name",
|
268 |
+
"select_preset": "Select Preset",
|
269 |
+
"add_favorite": "Add to Favorites",
|
270 |
+
"apply_matchering": "Apply Matchering",
|
271 |
+
"matchering_info": "Apply Matchering to enhance audio mastering and balance",
|
272 |
+
"matchering_passes": "Matchering Passes",
|
273 |
+
"matchering_passes_info": "Number of Matchering iterations (1-5, higher values improve quality but take longer)",
|
274 |
+
"matchering_processing": "Applying Matchering... ({:.1f}%)",
|
275 |
+
"matchering_completed": "✅ Matchering processing completed!",
|
276 |
+
"matchering_error": "❌ Error during Matchering: {}",
|
277 |
+
"invalid_method": "Error: Invalid method! Use 'gradio', 'localtunnel', or 'ngrok'.",
|
278 |
+
"language_changed_message": "Language changed. please restart the cell."
|
279 |
+
}
|
assets/i18n/languages/es_es.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Seleccionar idioma",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "Tu separación de audio definitiva",
|
5 |
+
"presented_by": "Presentado por Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ Separación de audio",
|
7 |
+
"input_model": "📥 Entrada y modelo",
|
8 |
+
"upload": "🖥 Subir",
|
9 |
+
"path": "📂 Ruta",
|
10 |
+
"path_placeholder": "/ruta/a/audio.wav",
|
11 |
+
"category": "Categoría",
|
12 |
+
"model": "Modelo",
|
13 |
+
"settings": "⚙ Configuración",
|
14 |
+
"format": "Formato",
|
15 |
+
"chunk_size": "Tamaño de fragmento",
|
16 |
+
"chunk_size_info": "No cambies a menos que tengas requisitos específicos",
|
17 |
+
"overlap": "Solapamiento",
|
18 |
+
"overlap_info": "Recomendado: 2-10 (valores más altos mejoran la calidad pero requieren más VRAM)",
|
19 |
+
"tta_boost": "Impulso TTA",
|
20 |
+
"tta_info": "Mejora la calidad pero ralentiza la velocidad de procesamiento",
|
21 |
+
"phase_fix": "Corrección de fase",
|
22 |
+
"phase_fix_info": "Corrección avanzada de fase para pistas instrumentales",
|
23 |
+
"instrumental": "Instrumental",
|
24 |
+
"instrumental_info": "Normalmente da 2 salidas, pero a veces da una sola salida, ¡tienes que probar! :)",
|
25 |
+
"process": "🚀 Procesar",
|
26 |
+
"reset": "🧹 Restablecer",
|
27 |
+
"status": "Estado",
|
28 |
+
"main_tab": "🎧 Principal",
|
29 |
+
"original": "Original",
|
30 |
+
"vocals": "Voces",
|
31 |
+
"instrumental_output": "Instrumental",
|
32 |
+
"other": "Otros",
|
33 |
+
"details_tab": "🔍 Detalles",
|
34 |
+
"male": "Masculino",
|
35 |
+
"female": "Femenino",
|
36 |
+
"speech": "Habla",
|
37 |
+
"drums": "Batería",
|
38 |
+
"bass": "Bajo",
|
39 |
+
"effects": "Efectos",
|
40 |
+
"advanced_tab": "⚙ Avanzado",
|
41 |
+
"phase_remix": "Remezcla de fase",
|
42 |
+
"dry": "Seco",
|
43 |
+
"music": "Música",
|
44 |
+
"karaoke": "Karaoke",
|
45 |
+
"bleed": "Sangrado",
|
46 |
+
"copy_to_drive": "📂 Copiar a Drive",
|
47 |
+
"copy_status": "Estado de la copia",
|
48 |
+
"files_will_be_copied": "Los archivos se copiarán aquí...",
|
49 |
+
"processing_tip": "<b>🔈 Consejo de procesamiento:</b> Para resultados ruidosos, usa modelos <code>bleed_suppressor_v1</code> o <code>denoisedebleed</code> en la categoría <i>\"Eliminación de ruido y efectos\"</i> para limpiar la salida",
|
50 |
+
"waiting_for_processing": "Esperando procesamiento...",
|
51 |
+
"auto_ensemble_tab": "🤖 Ensamblaje automático",
|
52 |
+
"upload_file": "Subir archivo",
|
53 |
+
"enter_file_path": "O ingresa la ruta del archivo",
|
54 |
+
"file_path_placeholder": "Ingresa la ruta completa al archivo de audio",
|
55 |
+
"advanced_settings": "⚙️ Configuración avanzada",
|
56 |
+
"use_tta": "Usar TTA",
|
57 |
+
"instrumental_only": "Solo instrumental",
|
58 |
+
"auto_overlap": "Solapamiento",
|
59 |
+
"auto_chunk_size": "Tamaño de fragmento",
|
60 |
+
"output_format": "Formato de salida",
|
61 |
+
"model_selection": "🧠 Selección de modelo",
|
62 |
+
"model_category": "Categoría del modelo",
|
63 |
+
"select_models": "Seleccionar modelos de la categoría",
|
64 |
+
"ensemble_settings": "⚡ Configuración de ensamblaje",
|
65 |
+
"method": "Método",
|
66 |
+
"recommendation": "**Recomendación:** avg_wave y max_fft ofrecen los mejores resultados",
|
67 |
+
"start_processing": "🚀 Iniciar procesamiento",
|
68 |
+
"original_audio_tab": "🔊 Audio original",
|
69 |
+
"original_audio": "Audio original",
|
70 |
+
"ensemble_result_tab": "🎚️ Resultado del ensamblaje",
|
71 |
+
"output_preview": "Vista previa de salida",
|
72 |
+
"refresh_output": "🔄 Actualizar salida",
|
73 |
+
"ensemble_copy_status": "La salida del ensamblaje se copiará aquí...",
|
74 |
+
"guidelines": "<h4>Directrices para la selección de modelos</h4><ul><li><strong>Evita mezclar categorías:</strong> Combinar modelos vocales e instrumentales puede crear mezclas no deseadas</li><li><strong>Notas sobre modelos especiales:</strong><ul><li>Modelos de dualidad (v1/v2) - Producen ambos stems</li><li>Separador MDX23C - Resultados híbridos</li></ul></li><li><strong>Mejor práctica:</strong> Usa 3-5 modelos similares de la misma categoría</li></ul><div>💡 Consejo profesional: Comienza con la combinación \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\"</div>",
|
75 |
+
"download_sources_tab": "⬇️ Descargar fuentes",
|
76 |
+
"direct_links": "🌐 Enlaces directos",
|
77 |
+
"audio_file_url": "URL del archivo de audio",
|
78 |
+
"download_from_url": "⬇️ Descargar desde URL",
|
79 |
+
"download_status": "Estado de la descarga",
|
80 |
+
"downloaded_file": "Archivo descargado",
|
81 |
+
"cookie_management": "🍪 Gestión de cookies",
|
82 |
+
"upload_cookies_txt": "Subir Cookies.txt",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 ¿Por qué es necesario?**<br>- Acceso a contenido restringido por edad<br>- Descarga de videos privados/no listados<br>- Evitar restricciones regionales<br>- Evitar límites de descarga de YouTube<br><br>**⚠️ Notas importantes**<br>- ¡NUNCA compartas tus archivos de cookies!<br>- Actualiza las cookies cuando:<br> • Recibes errores \"403 Prohibido\"<br> • Las descargas se detienen repentinamente<br> • Ves mensajes de \"Sesión expirada\"<br><br>**🔄 Pasos para renovar**<br>1. Instala esta <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">extensión de Chrome</a><br>2. Inicia sesión en YouTube en Chrome<br>3. Haz clic en el ícono de la extensión → \"Exportar\"<br>4. Sube el archivo descargado aquí<br><br>**⏳ Vida útil de las cookies**<br>- Sesiones normales: 24 horas<br>- Operaciones sensibles: 1 hora<br>- Cambios de contraseña: Invalidación inmediata</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ Ensamblaje manual",
|
85 |
+
"input_sources": "📂 Fuentes de entrada",
|
86 |
+
"refresh": "🔄 Actualizar",
|
87 |
+
"ensemble_algorithm": "Algoritmo de ensamblaje",
|
88 |
+
"select_audio_files": "Seleccionar archivos de audio",
|
89 |
+
"available_files": "Archivos disponibles",
|
90 |
+
"custom_weights": "Pesos personalizados (separados por comas)",
|
91 |
+
"custom_weights_placeholder": "Ejemplo: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "Dejar vacío para pesos iguales",
|
93 |
+
"result_preview_tab": "🎧 Vista previa del resultado",
|
94 |
+
"ensembled_output": "Salida ensamblada",
|
95 |
+
"processing_log_tab": "📋 Registro de procesamiento",
|
96 |
+
"processing_details": "Detalles de procesamiento",
|
97 |
+
"process_ensemble": "⚡ Procesar ensamblaje",
|
98 |
+
"languages_tab": "🌐 Idiomas",
|
99 |
+
"Vocal Models": "Modelos vocales",
|
100 |
+
"Instrumental Models": "Modelos instrumentales",
|
101 |
+
"4-Stem Models": "Modelos de 4 stems",
|
102 |
+
"Denoise Models": "Modelos de eliminación de ruido",
|
103 |
+
"Dereverb Models": "Modelos de eliminación de reverberación",
|
104 |
+
"Other Models": "Otros modelos",
|
105 |
+
"ensemble_files_description": "Combina varios archivos de audio en una sola salida usando métodos de ensamblaje especificados.",
|
106 |
+
"ensemble_files_help": "Ruta a todos los archivos de audio para el ensamblaje",
|
107 |
+
"ensemble_type_help": "Uno de avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "Pesos para crear el ensamblaje. El número de pesos debe igualar el número de archivos",
|
109 |
+
"ensemble_output_help": "Ruta al archivo WAV donde se almacenará el resultado del ensamblaje",
|
110 |
+
"ensemble_type_print": "Tipo de ensamblaje: {}",
|
111 |
+
"num_input_files_print": "Número de archivos de entrada: {}",
|
112 |
+
"weights_print": "Pesos: {}",
|
113 |
+
"output_file_print": "Archivo de salida: {}",
|
114 |
+
"duration_mismatch_error": "Todos los archivos deben tener la misma duración",
|
115 |
+
"file_not_found_error": "Error. No se puede encontrar el archivo: {}. Verifica las rutas.",
|
116 |
+
"reading_chunk_print": "Leyendo fragmento del archivo: {} (inicio: {}s, duración: {}s)",
|
117 |
+
"chunk_result_shape_print": "Forma del resultado del fragmento: {}",
|
118 |
+
"ensemble_completed_print": "Ensamblaje completado. Salida guardada en: {}",
|
119 |
+
"file_deletion_error": "{} no pudo ser eliminado: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ El directorio no existe: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ La ruta no es un directorio: {}",
|
122 |
+
"item_deletion_error": "⚠️ Error al eliminar {}: {}",
|
123 |
+
"old_output_not_exist": "❌ La carpeta de salida antigua no existe",
|
124 |
+
"old_outputs_cleared": "✅ ¡Salidas antiguas eliminadas con éxito!",
|
125 |
+
"error": "🔥 Error: {}",
|
126 |
+
"ffmpeg_error": "Error de FFmpeg ({}): {}",
|
127 |
+
"file_saved_successfully": "Archivo guardado con éxito: {}",
|
128 |
+
"total_files_found": "Total de archivos encontrados: {}. Usando tasa de muestreo: {}",
|
129 |
+
"total_progress": "Progreso total",
|
130 |
+
"detailed_pbar_enabled": "Barra de progreso detallada activada: {}",
|
131 |
+
"loaded_audio": "Audio cargado: {}, forma: {}",
|
132 |
+
"cannot_read_track": "No se puede leer la pista: {}",
|
133 |
+
"error_message": "Mensaje de error: {}",
|
134 |
+
"demudding_track": "Desm Mezclando pista (remezcla de fase - instrumental): {}",
|
135 |
+
"elapsed_time": "Tiempo transcurrido: {:.2f} segundos.",
|
136 |
+
"proc_folder_description": "Procesa archivos de audio en una carpeta usando un modelo especificado.",
|
137 |
+
"model_type_help": "Tipo de modelo (bandit, bs_roformer, mdx23c, etc.)",
|
138 |
+
"config_path_help": "Ruta al archivo de configuración",
|
139 |
+
"demud_phaseremix_help": "Habilitar remezcla de fase para instrumental",
|
140 |
+
"start_checkpoint_help": "Punto de control inicial para pesos válidos",
|
141 |
+
"input_folder_help": "Carpeta con mezclas para procesar",
|
142 |
+
"audio_path_help": "Ruta a un solo archivo de audio para procesar",
|
143 |
+
"store_dir_help": "Ruta para almacenar los resultados",
|
144 |
+
"device_ids_help": "Lista de IDs de GPU",
|
145 |
+
"extract_instrumental_help": "Invertir las voces para obtener instrumental si se proporciona",
|
146 |
+
"disable_detailed_pbar_help": "Deshabilitar barra de progreso detallada en la desmezcla",
|
147 |
+
"force_cpu_help": "Forzar el uso de CPU incluso si CUDA está disponible",
|
148 |
+
"flac_file_help": "Generar archivo FLAC en lugar de WAV",
|
149 |
+
"export_format_help": "Formato de exportación y tipo PCM",
|
150 |
+
"pcm_type_help": "Tipo PCM para archivos FLAC",
|
151 |
+
"use_tta_help": "Habilitar aumento en tiempo de prueba",
|
152 |
+
"lora_checkpoint_help": "Punto de control inicial para pesos LoRA",
|
153 |
+
"cuda_available": "CUDA está disponible, usa --force_cpu para deshabilitarlo.",
|
154 |
+
"using_device": "Usando dispositivo: {}",
|
155 |
+
"instruments_print": "Instrumentos: {}",
|
156 |
+
"model_load_time": "Tiempo de carga del modelo: {:.2f} seg",
|
157 |
+
"invalid_url": "❌ URL inválida",
|
158 |
+
"cookie_file_updated": "✅ ¡Archivo de cookies actualizado!",
|
159 |
+
"cookie_installation_error": "⚠️ Error en la instalación de cookies: {}",
|
160 |
+
"file_size_zero_error": "Tamaño del archivo cero o archivo no creado",
|
161 |
+
"google_drive_error": "❌ Error de descarga de Google Drive: {}",
|
162 |
+
"wav_conversion_failed": "Fallo en la conversión a WAV",
|
163 |
+
"download_error": "❌ Error de descarga: {}",
|
164 |
+
"download_success": "🎉 ¡Descargado con éxito!",
|
165 |
+
"download_failed": "❌ Fallo en la descarga",
|
166 |
+
"no_output_files_found": "❌ No se encontraron archivos de salida.",
|
167 |
+
"output_refreshed_successfully": "✅ ¡Salida actualizada con éxito!",
|
168 |
+
"error_refreshing_output": "❌ Error al actualizar la salida: {}",
|
169 |
+
"starting_audio_separation": "Iniciando separación de audio...",
|
170 |
+
"processing_audio": "Procesando audio",
|
171 |
+
"separating_audio": "Separando audio... ({:.1f}%)",
|
172 |
+
"separation_complete": "¡Separación completada!",
|
173 |
+
"progress_parsing_error": "Error al analizar el progreso: {}",
|
174 |
+
"error_occurred": "Ocurrió un error: {}",
|
175 |
+
"separation_process_completed": "¡Proceso de separación completado!",
|
176 |
+
"no_audio_file_error": "❌ No se proporcionó archivo de audio y no hay archivo existente en el directorio de entrada.",
|
177 |
+
"no_input_progress_label": "Error: No se proporcionó entrada -- 0.0%",
|
178 |
+
"processing_audio_print": "Procesando audio desde: {} usando el modelo: {}",
|
179 |
+
"starting_audio_separation_progress_label": "Iniciando separación de audio... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "Separando audio... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "¡Procesamiento de audio completado! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ ¡Procesamiento de audio completado!",
|
183 |
+
"error_occurred_progress_label": "Ocurrió un error -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ Se requieren al menos 2 archivos",
|
185 |
+
"valid_files_not_found": "❌ No se encontraron archivos válidos",
|
186 |
+
"starting_ensemble_process": "Iniciando proceso de ensamblaje...",
|
187 |
+
"ensembling_progress": "Ensamblando... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "Finalizando salida del ensamblaje...",
|
189 |
+
"success_log": "✅ ¡Éxito!\n{}",
|
190 |
+
"error_log": "❌ ¡Error!\n{}",
|
191 |
+
"critical_error": "⛔ Error crítico: {}",
|
192 |
+
"ensemble_process_completed": "¡Proceso de ensamblaje completado!",
|
193 |
+
"no_models_selected": "❌ No se seleccionaron modelos",
|
194 |
+
"no_input_audio_provided": "❌ No se proporcionó audio de entrada",
|
195 |
+
"loading_model": "Cargando modelo {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "Cargando modelo {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "Modelo completado {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "Modelo completado {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "Ejecutando comando: {}",
|
200 |
+
"model_failed": "El modelo {} falló: {}",
|
201 |
+
"critical_error_with_model": "Error crítico con {}: {}",
|
202 |
+
"model_output_failed": "{} falló al producir salida",
|
203 |
+
"waiting_for_files": "Esperando a que todos los archivos estén listos...",
|
204 |
+
"waiting_for_files_progress_label": "Esperando a que todos los archivos estén listos... -- 90.0%",
|
205 |
+
"performing_ensemble": "Realizando ensamblaje...",
|
206 |
+
"performing_ensemble_progress_label": "Realizando ensamblaje... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "Uso de memoria antes del ensamblaje: {}%",
|
208 |
+
"memory_usage_after_ensemble": "Uso de memoria después del ensamblaje: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "Finalizando salida del ensamblaje... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "No se pudo crear el archivo de ensamblaje: {}",
|
211 |
+
"ensemble_completed_progress_label": "¡Ensamblaje completado con éxito! -- 100.0%",
|
212 |
+
"success_output_created": "✅ ¡Éxito! Archivo de salida creado.",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive montado. Copiando salida del ensamblaje...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive ya montado. Copiando salida del ensamblaje...",
|
215 |
+
"no_ensemble_output_files_found": "❌ No se encontraron archivos de salida de ensamblaje.",
|
216 |
+
"ensemble_output_copied": "✅ Salida del ensamblaje copiada a {}",
|
217 |
+
"error_copying_ensemble_output": "❌ Error al copiar la salida del ensamblaje: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive montado. Copiando archivos...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive ya montado. Copiando archivos...",
|
220 |
+
"files_copied_to_drive": "✅ Archivos copiados a {}",
|
221 |
+
"error_copying_files": "❌ Error al copiar archivos: {}",
|
222 |
+
"mounting_drive": "Montando Google Drive...",
|
223 |
+
"settings_saved": "Configuración guardada en config.json: Idioma={lang}, Método={method}, Puerto={port}",
|
224 |
+
"selected_language": "Idioma seleccionado: {lang}",
|
225 |
+
"available_languages": "Idiomas disponibles: {langs}",
|
226 |
+
"select_language_prompt": "Selecciona un idioma (predeterminado: {default}): ",
|
227 |
+
"invalid_language": "¡Selección de idioma inválida! Usando idioma predeterminado ({default}).",
|
228 |
+
"available_sharing_methods": "Métodos de compartición disponibles: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "Elige un método de compartición (predeterminado: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "Ingresa tu token de Ngrok (predeterminado: {default}): ",
|
231 |
+
"ngrok_token_required": "Error: ¡Se requiere un token de Ngrok para el método ngrok!",
|
232 |
+
"enter_port_prompt": "Ingresa el número de puerto (predeterminado: {default}): ",
|
233 |
+
"opening_previous_url": "Abriendo URL anterior: {url}",
|
234 |
+
"open_url_manually": "Abre la URL manualmente en Colab: {url}",
|
235 |
+
"invalid_previous_url": "URL anterior inválida: {url}, no abierta.",
|
236 |
+
"starting_method": "Iniciando {method} en el puerto {port}...",
|
237 |
+
"process_stopped": "\n🛑 Proceso detenido por el usuario",
|
238 |
+
"selected_port": "Puerto seleccionado: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Iniciando Gradio con compartición integrada...",
|
240 |
+
"starting_localtunnel": "Iniciando Localtunnel en el puerto {port}...",
|
241 |
+
"share_link": "Enlace para compartir: {url}",
|
242 |
+
"password_ip": "Contraseña IP: {ip}",
|
243 |
+
"starting_ngrok": "Iniciando Ngrok en el puerto {port}...",
|
244 |
+
"ngrok_url": "URL de Ngrok: {url}",
|
245 |
+
"ngrok_error": "Error al iniciar Ngrok: {error}",
|
246 |
+
"apollo_chunk_size": "Tamaño de fragmento Apollo",
|
247 |
+
"apollo_chunk_size_info": "Tamaño de fragmento para mejora Apollo (recomendado: 19 para modelo universal)",
|
248 |
+
"apollo_overlap": "Solapamiento Apollo",
|
249 |
+
"enhancing_with_apollo": "Mejorando con Apollo ({}/{} archivos)...",
|
250 |
+
"apollo_processing_completed": "¡Procesamiento Apollo completado!",
|
251 |
+
"apollo_overlap_info": "Solapamiento para mejora Apollo (recomendado: 2)",
|
252 |
+
"invalid_method": "Error: ¡Método inválido! Usa 'gradio', 'localtunnel' o 'ngrok'.",
|
253 |
+
"apollo_enhancement_settings": "Configuración de mejora Apollo",
|
254 |
+
"enhance_with_apollo": "Mejorar con Apollo",
|
255 |
+
"enhance_with_apollo_info": "Habilitar Apollo para mejora de audio después de la separación",
|
256 |
+
"apollo_method": "Método Apollo",
|
257 |
+
"apollo_method_info": "Selecciona el método de procesamiento para Apollo",
|
258 |
+
"normal_method": "Método normal",
|
259 |
+
"mid_side_method": "Método centro/lateral",
|
260 |
+
"apollo_normal_model": "Modelo Apollo normal",
|
261 |
+
"apollo_normal_model_info": "Modelo a usar para procesamiento Apollo normal",
|
262 |
+
"apollo_midside_model": "Modelo Apollo centro/lateral",
|
263 |
+
"apollo_enhancement_info": "Mejora de la calidad del sonido",
|
264 |
+
"selected_models": "Modelos Seleccionados",
|
265 |
+
"save_preset": "Guardar Preajuste",
|
266 |
+
"delete_preset": "Eliminar Preajuste",
|
267 |
+
"refresh_presets": "Actualizar Preajustes",
|
268 |
+
"preset_name": "Nombre del Preajuste",
|
269 |
+
"select_preset": "Seleccionar Preajuste",
|
270 |
+
"add_favorite": "Añadir a Favoritos",
|
271 |
+
"apollo_midside_model_info": "Modelo a usar para procesamiento centro/lateral (opcional)",
|
272 |
+
"language_changed_message": "Idioma cambiado. Por favor, reinicia la celda.",
|
273 |
+
"apply_matchering": "Aplicar Matchering",
|
274 |
+
"matchering_info": "Aplicar Matchering para mejorar el masterizado y el balance del audio",
|
275 |
+
"matchering_passes": "Pasadas de Matchering",
|
276 |
+
"matchering_passes_info": "Número de iteraciones de Matchering (1-5, valores más altos mejoran la calidad pero toman más tiempo)",
|
277 |
+
"matchering_processing": "Aplicando Matchering... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ ¡Procesamiento de Matchering completado!",
|
279 |
+
"matchering_error": "❌ Error durante Matchering: {}"
|
280 |
+
}
|
assets/i18n/languages/fr_fr.json
ADDED
@@ -0,0 +1,273 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Sélectionner la langue",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "Votre séparation audio ultime",
|
5 |
+
"presented_by": "Présenté par Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ Séparation audio",
|
7 |
+
"input_model": "📥 Entrée et modèle",
|
8 |
+
"upload": "🖥 Télécharger",
|
9 |
+
"path": "📂 Chemin",
|
10 |
+
"path_placeholder": "/chemin/vers/audio.wav",
|
11 |
+
"category": "Catégorie",
|
12 |
+
"model": "Modèle",
|
13 |
+
"settings": "⚙ Paramètres",
|
14 |
+
"format": "Format",
|
15 |
+
"chunk_size": "Taille de fragment",
|
16 |
+
"chunk_size_info": "Ne changez pas sauf si vous avez des exigences spécifiques",
|
17 |
+
"overlap": "Chevauchement",
|
18 |
+
"overlap_info": "Recommandé : 2-10 (des valeurs plus élevées améliorent la qualité mais nécessitent plus de VRAM)",
|
19 |
+
"tta_boost": "Boost TTA",
|
20 |
+
"tta_info": "Améliore la qualité mais ralentit la vitesse de traitement",
|
21 |
+
"phase_fix": "Correction de phase",
|
22 |
+
"phase_fix_info": "Correction avancée de phase pour les pistes instrumentales",
|
23 |
+
"instrumental": "Instrumental",
|
24 |
+
"instrumental_info": "Donne généralement 2 sorties, mais parfois une seule, il faut essayer ! :)",
|
25 |
+
"process": "🚀 Traiter",
|
26 |
+
"reset": "🧹 Réinitialiser",
|
27 |
+
"status": "Statut",
|
28 |
+
"main_tab": "🎧 Principal",
|
29 |
+
"original": "Original",
|
30 |
+
"vocals": "Voix",
|
31 |
+
"instrumental_output": "Instrumental",
|
32 |
+
"other": "Autres",
|
33 |
+
"details_tab": "🔍 Détails",
|
34 |
+
"male": "Masculin",
|
35 |
+
"female": "Féminin",
|
36 |
+
"speech": "Parole",
|
37 |
+
"drums": "Batterie",
|
38 |
+
"bass": "Basse",
|
39 |
+
"effects": "Effets",
|
40 |
+
"advanced_tab": "⚙ Avancé",
|
41 |
+
"phase_remix": "Remix de phase",
|
42 |
+
"dry": "Sec",
|
43 |
+
"music": "Musique",
|
44 |
+
"karaoke": "Karaoké",
|
45 |
+
"bleed": "Saignement",
|
46 |
+
"copy_to_drive": "📂 Copier sur Drive",
|
47 |
+
"copy_status": "Statut de la copie",
|
48 |
+
"files_will_be_copied": "Les fichiers seront copiés ici...",
|
49 |
+
"processing_tip": "<b>🔈 Astuce de traitement :</b> Pour des résultats bruités, utilisez les modèles <code>bleed_suppressor_v1</code> ou <code>denoisedebleed</code> dans la catégorie <i>\"Suppression de bruit et d'effets\"</i> pour nettoyer la sortie",
|
50 |
+
"waiting_for_processing": "En attente de traitement...",
|
51 |
+
"auto_ensemble_tab": "🤖 Assemblage automatique",
|
52 |
+
"upload_file": "Télécharger un fichier",
|
53 |
+
"enter_file_path": "Ou entrez le chemin du fichier",
|
54 |
+
"file_path_placeholder": "Entrez le chemin complet vers le fichier audio",
|
55 |
+
"advanced_settings": "⚙️ Paramètres avancés",
|
56 |
+
"use_tta": "Utiliser TTA",
|
57 |
+
"instrumental_only": "Instrumental uniquement",
|
58 |
+
"auto_overlap": "Chevauchement",
|
59 |
+
"auto_chunk_size": "Taille de fragment",
|
60 |
+
"output_format": "Format de sortie",
|
61 |
+
"model_selection": "🧠 Sélection de modèle",
|
62 |
+
"model_category": "Catégorie de modèle",
|
63 |
+
"select_models": "Sélectionner des modèles dans la catégorie",
|
64 |
+
"ensemble_settings": "⚡ Paramètres d'assemblage",
|
65 |
+
"method": "Méthode",
|
66 |
+
"recommendation": "**Recommandation :** avg_wave et max_fft donnent les meilleurs résultats",
|
67 |
+
"start_processing": "🚀 Démarrer le traitement",
|
68 |
+
"original_audio_tab": "🔊 Audio original",
|
69 |
+
"original_audio": "Audio original",
|
70 |
+
"ensemble_result_tab": "🎚️ Résultat de l'assemblage",
|
71 |
+
"output_preview": "Aperçu de la sortie",
|
72 |
+
"refresh_output": "🔄 Actualiser la sortie",
|
73 |
+
"ensemble_copy_status": "La sortie de l'assemblage sera copiée ici...",
|
74 |
+
"guidelines": "<h4>Directives pour la sélection de modèles</h4><ul><li><strong>Évitez de mélanger les catégories :</strong> Combiner des modèles vocaux et instrumentaux peut créer des mélanges indésirables</li><li><strong>Notes sur les modèles spéciaux :</strong><ul><li>Modèles de dualité (v1/v2) - Produisent les deux stems</li><li>Séparateur MDX23C - Résultats hybrides</li></ul></li><li><strong>Meilleure pratique :</strong> Utilisez 3-5 modèles similaires de la même catégorie</li></ul><div>💡 Astuce pro : Commencez avec la combinaison \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\"</div>",
|
75 |
+
"download_sources_tab": "⬇️ Télécharger les sources",
|
76 |
+
"direct_links": "🌐 Liens directs",
|
77 |
+
"audio_file_url": "URL du fichier audio",
|
78 |
+
"download_from_url": "⬇️ Télécharger depuis l'URL",
|
79 |
+
"download_status": "Statut du téléchargement",
|
80 |
+
"downloaded_file": "Fichier téléchargé",
|
81 |
+
"cookie_management": "🍪 Gestion des cookies",
|
82 |
+
"upload_cookies_txt": "Télécharger Cookies.txt",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 Pourquoi est-ce nécessaire ?**<br>- Accès au contenu restreint par âge<br>- Téléchargement de vidéos privées/non listées<br>- Contournement des restrictions régionales<br>- Éviter les limites de téléchargement de YouTube<br><br>**⚠️ Notes importantes**<br>- NE PARTAGEZ JAMAIS vos fichiers de cookies !<br>- Actualisez les cookies lorsque :<br> • Vous obtenez des erreurs \"403 Interdit\"<br> • Les téléchargements s'arrêtent soudainement<br> • Vous voyez des messages \"Session expirée\"<br><br>**🔄 Étapes de renouvellement**<br>1. Installez cette <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">extension Chrome</a><br>2. Connectez-vous à YouTube dans Chrome<br>3. Cliquez sur l'icône de l'extension → \"Exporter\"<br>4. Téléchargez le fichier téléchargé ici<br><br>**⏳ Durée de vie des cookies**<br>- Sessions normales : 24 heures<br>- Opérations sensibles : 1 heure<br>- Changements de mot de passe : Invalidité immédiate</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ Assemblage manuel",
|
85 |
+
"input_sources": "📂 Sources d'entrée",
|
86 |
+
"refresh": "🔄 Actualiser",
|
87 |
+
"ensemble_algorithm": "Algorithme d'assemblage",
|
88 |
+
"select_audio_files": "Sélectionner des fichiers audio",
|
89 |
+
"available_files": "Fichiers disponibles",
|
90 |
+
"custom_weights": "Poids personnalisés (séparés par des virgules)",
|
91 |
+
"custom_weights_placeholder": "Exemple : 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "Laissez vide pour des poids égaux",
|
93 |
+
"result_preview_tab": "🎧 Aperçu du résultat",
|
94 |
+
"ensembled_output": "Sortie assemblée",
|
95 |
+
"processing_log_tab": "📋 Journal de traitement",
|
96 |
+
"processing_details": "Détails du traitement",
|
97 |
+
"process_ensemble": "⚡ Traiter l'assemblage",
|
98 |
+
"languages_tab": "🌐 Langues",
|
99 |
+
"Vocal Models": "Modèles vocaux",
|
100 |
+
"Instrumental Models": "Modèles instrumentaux",
|
101 |
+
"4-Stem Models": "Modèles à 4 stems",
|
102 |
+
"Denoise Models": "Modèles de débruitage",
|
103 |
+
"Dereverb Models": "Modèles de suppression de réverbération",
|
104 |
+
"Other Models": "Autres modèles",
|
105 |
+
"ensemble_files_description": "Combine plusieurs fichiers audio en une seule sortie en utilisant des méthodes d'assemblage spécifiées.",
|
106 |
+
"ensemble_files_help": "Chemin vers tous les fichiers audio pour l'assemblage",
|
107 |
+
"ensemble_type_help": "L'un des suivants : avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "Poids pour créer l'assemblage. Le nombre de poids doit correspondre au nombre de fichiers",
|
109 |
+
"ensemble_output_help": "Chemin vers le fichier WAV où le résultat de l'assemblage sera stocké",
|
110 |
+
"ensemble_type_print": "Type d'assemblage : {}",
|
111 |
+
"num_input_files_print": "Nombre de fichiers d'entrée : {}",
|
112 |
+
"weights_print": "Poids : {}",
|
113 |
+
"output_file_print": "Fichier de sortie : {}",
|
114 |
+
"duration_mismatch_error": "Tous les fichiers doivent avoir la même durée",
|
115 |
+
"file_not_found_error": "Erreur. Impossible de trouver le fichier : {}. Vérifiez les chemins.",
|
116 |
+
"reading_chunk_print": "Lecture d'un fragment du fichier : {} (début : {}s, durée : {}s)",
|
117 |
+
"chunk_result_shape_print": "Forme du résultat du fragment : {}",
|
118 |
+
"ensemble_completed_print": "Assemblage terminé. Sortie enregistrée sous : {}",
|
119 |
+
"file_deletion_error": "{} n'a pas pu être supprimé : {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ Le répertoire n'existe pas : {}",
|
121 |
+
"not_a_directory_warning": "⚠️ Le chemin n'est pas un répertoire : {}",
|
122 |
+
"item_deletion_error": "⚠️ Erreur lors de la suppression de {} : {}",
|
123 |
+
"old_output_not_exist": "❌ Le dossier de sortie ancien n'existe pas",
|
124 |
+
"old_outputs_cleared": "✅ Les anciennes sorties ont été supprimées avec succès !",
|
125 |
+
"error": "🔥 Erreur : {}",
|
126 |
+
"ffmpeg_error": "Erreur FFmpeg ({}): {}",
|
127 |
+
"file_saved_successfully": "Fichier enregistré avec succès : {}",
|
128 |
+
"total_files_found": "Nombre total de fichiers trouvés : {}. Taux d'échantillonnage utilisé : {}",
|
129 |
+
"total_progress": "Progrès total",
|
130 |
+
"detailed_pbar_enabled": "Barre de progression détaillée activée : {}",
|
131 |
+
"loaded_audio": "Audio chargé : {}, forme : {}",
|
132 |
+
"cannot_read_track": "Impossible de lire la piste : {}",
|
133 |
+
"error_message": "Message d'erreur : {}",
|
134 |
+
"demudding_track": "Nettoyage de la piste (remix de phase - instrumental) : {}",
|
135 |
+
"elapsed_time": "Temps écoulé : {:.2f} secondes.",
|
136 |
+
"proc_folder_description": "Traite les fichiers audio dans un dossier en utilisant un modèle spécifié.",
|
137 |
+
"model_type_help": "Type de modèle (bandit, bs_roformer, mdx23c, etc.)",
|
138 |
+
"config_path_help": "Chemin vers le fichier de configuration",
|
139 |
+
"demud_phaseremix_help": "Activer le remix de phase pour l'instrumental",
|
140 |
+
"start_checkpoint_help": "Point de contrôle initial pour des poids valides",
|
141 |
+
"input_folder_help": "Dossier contenant les mélanges à traiter",
|
142 |
+
"audio_path_help": "Chemin vers un seul fichier audio à traiter",
|
143 |
+
"store_dir_help": "Chemin pour stocker les résultats",
|
144 |
+
"device_ids_help": "Liste des identifiants GPU",
|
145 |
+
"extract_instrumental_help": "Inverser les voix pour obtenir l'instrumental si fourni",
|
146 |
+
"disable_detailed_pbar_help": "Désactiver la barre de progression détaillée dans le démixage",
|
147 |
+
"force_cpu_help": "Forcer l'utilisation du CPU même si CUDA est disponible",
|
148 |
+
"flac_file_help": "Générer un fichier FLAC au lieu de WAV",
|
149 |
+
"export_format_help": "Format d'exportation et type PCM",
|
150 |
+
"pcm_type_help": "Type PCM pour les fichiers FLAC",
|
151 |
+
"use_tta_help": "Activer l'augmentation en temps de test",
|
152 |
+
"lora_checkpoint_help": "Point de contrôle initial pour les poids LoRA",
|
153 |
+
"cuda_available": "CUDA est disponible, utilisez --force_cpu pour le désactiver.",
|
154 |
+
"using_device": "Utilisation de l'appareil : {}",
|
155 |
+
"instruments_print": "Instruments : {}",
|
156 |
+
"model_load_time": "Temps de chargement du modèle : {:.2f} sec",
|
157 |
+
"invalid_url": "❌ URL invalide",
|
158 |
+
"cookie_file_updated": "✅ Fichier de cookies mis à jour !",
|
159 |
+
"cookie_installation_error": "⚠️ Erreur d'installation des cookies : {}",
|
160 |
+
"file_size_zero_error": "Taille du fichier zéro ou fichier non créé",
|
161 |
+
"google_drive_error": "❌ Erreur de téléchargement Google Drive : {}",
|
162 |
+
"wav_conversion_failed": "Échec de la conversion WAV",
|
163 |
+
"download_error": "❌ Erreur de téléchargement : {}",
|
164 |
+
"download_success": "🎉 Téléchargé avec succès !",
|
165 |
+
"download_failed": "❌ Échec du téléchargement",
|
166 |
+
"no_output_files_found": "❌ Aucun fichier de sortie trouvé.",
|
167 |
+
"output_refreshed_successfully": "✅ Sortie actualisée avec succès !",
|
168 |
+
"error_refreshing_output": "❌ Erreur lors de l'actualisation de la sortie : {}",
|
169 |
+
"starting_audio_separation": "Démarrage de la séparation audio...",
|
170 |
+
"processing_audio": "Traitement de l'audio",
|
171 |
+
"separating_audio": "Séparation de l'audio... ({:.1f}%)",
|
172 |
+
"separation_complete": "Séparation terminée !",
|
173 |
+
"progress_parsing_error": "Erreur d'analyse de la progression : {}",
|
174 |
+
"error_occurred": "Une erreur est survenue : {}",
|
175 |
+
"separation_process_completed": "Processus de séparation terminé !",
|
176 |
+
"no_audio_file_error": "❌ Aucun fichier audio fourni et aucun fichier existant dans le répertoire d'entrée.",
|
177 |
+
"no_input_progress_label": "Erreur : Aucune entrée fournie -- 0.0%",
|
178 |
+
"processing_audio_print": "Traitement de l'audio depuis : {} en utilisant le modèle : {}",
|
179 |
+
"starting_audio_separation_progress_label": "Démarrage de la séparation audio... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "Séparation de l'audio... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "Traitement audio terminé ! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ Traitement audio terminé !",
|
183 |
+
"error_occurred_progress_label": "Erreur survenue -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ Minimum de 2 fichiers requis",
|
185 |
+
"valid_files_not_found": "❌ Aucun fichier valide trouvé",
|
186 |
+
"starting_ensemble_process": "Démarrage du processus d'assemblage...",
|
187 |
+
"ensembling_progress": "Assemblage en cours... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "Finalisation de la sortie de l'assemblage...",
|
189 |
+
"success_log": "✅ Succès !\n{}",
|
190 |
+
"error_log": "❌ Erreur !\n{}",
|
191 |
+
"critical_error": "⛔ Erreur critique : {}",
|
192 |
+
"ensemble_process_completed": "Processus d'assemblage terminé !",
|
193 |
+
"no_models_selected": "❌ Aucun modèle sélectionné",
|
194 |
+
"no_input_audio_provided": "❌ Aucun audio d'entrée fourni",
|
195 |
+
"loading_model": "Chargement du modèle {}/{} : {}...",
|
196 |
+
"loading_model_progress_label": "Chargement du modèle {}/{} : {}... -- {}.0%",
|
197 |
+
"completed_model": "Modèle terminé {}/{} : {}",
|
198 |
+
"completed_model_progress_label": "Modèle terminé {}/{} : {} -- {}.0%",
|
199 |
+
"running_command": "Exécution de la commande : {}",
|
200 |
+
"model_failed": "Le modèle {} a échoué : {}",
|
201 |
+
"critical_error_with_model": "Erreur critique avec {} : {}",
|
202 |
+
"model_output_failed": "{} n'a pas réussi à produire une sortie",
|
203 |
+
"waiting_for_files": "En attente que tous les fichiers soient prêts...",
|
204 |
+
"waiting_for_files_progress_label": "En attente que tous les fichiers soient prêts... -- 90.0%",
|
205 |
+
"performing_ensemble": "Réalisation de l'assemblage...",
|
206 |
+
"performing_ensemble_progress_label": "Réalisation de l'assemblage... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "Utilisation de la mémoire avant l'assemblage : {}%",
|
208 |
+
"memory_usage_after_ensemble": "Utilisation de la mémoire après l'assemblage : {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "Finalisation de la sortie de l'assemblage... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "Le fichier d'assemblage n'a pas pu être créé : {}",
|
211 |
+
"ensemble_completed_progress_label": "Assemblage terminé avec succès ! -- 100.0%",
|
212 |
+
"success_output_created": "✅ Succès ! Fichier de sortie créé.",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive monté. Copie de la sortie de l'assemblage...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive déjà monté. Copie de la sortie de l'assemblage...",
|
215 |
+
"no_ensemble_output_files_found": "❌ Aucun fichier de sortie d'assemblage trouvé.",
|
216 |
+
"ensemble_output_copied": "✅ Sortie de l'assemblage copiée vers {}",
|
217 |
+
"error_copying_ensemble_output": "❌ Erreur lors de la copie de la sortie de l'assemblage : {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive monté. Copie des fichiers...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive déjà monté. Copie des fichiers...",
|
220 |
+
"files_copied_to_drive": "✅ Fichiers copiés vers {}",
|
221 |
+
"error_copying_files": "❌ Erreur lors de la copie des fichiers : {}",
|
222 |
+
"mounting_drive": "Montage de Google Drive...",
|
223 |
+
"settings_saved": "Paramètres enregistrés dans config.json : Langue={lang}, Méthode={method}, Port={port}",
|
224 |
+
"selected_language": "Langue sélectionnée : {lang}",
|
225 |
+
"available_languages": "Langues disponibles : {langs}",
|
226 |
+
"select_language_prompt": "Sélectionnez une langue (par défaut : {default}) : ",
|
227 |
+
"invalid_language": "Sélection de langue invalide ! Utilisation de la langue par défaut ({default}).",
|
228 |
+
"available_sharing_methods": "Méthodes de partage disponibles : gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "Choisissez une méthode de partage (par défaut : {default}) : ",
|
230 |
+
"enter_ngrok_token_prompt": "Entrez votre jeton Ngrok (par défaut : {default}) : ",
|
231 |
+
"ngrok_token_required": "Erreur : Un jeton Ngrok est requis pour la méthode ngrok !",
|
232 |
+
"enter_port_prompt": "Entrez le numéro de port (par défaut : {default}) : ",
|
233 |
+
"opening_previous_url": "Ouverture de l'URL précédente : {url}",
|
234 |
+
"open_url_manually": "Ouvrez l'URL manuellement dans Colab : {url}",
|
235 |
+
"invalid_previous_url": "URL précédente invalide : {url}, non ouverte.",
|
236 |
+
"starting_method": "Démarrage de {method} sur le port {port}...",
|
237 |
+
"process_stopped": "\n🛑 Processus arrêté par l'utilisateur",
|
238 |
+
"selected_port": "Port sélectionné : {port}",
|
239 |
+
"starting_gradio_with_sharing": "Démarrage de Gradio avec partage intégré...",
|
240 |
+
"starting_localtunnel": "Démarrage de Localtunnel sur le port {port}...",
|
241 |
+
"share_link": "Lien de partage : {url}",
|
242 |
+
"password_ip": "Mot de passe IP : {ip}",
|
243 |
+
"starting_ngrok": "Démarrage de Ngrok sur le port {port}...",
|
244 |
+
"ngrok_url": "URL Ngrok : {url}",
|
245 |
+
"ngrok_error": "Erreur lors du démarrage de Ngrok : {error}",
|
246 |
+
"apollo_chunk_size": "Taille de fragment Apollo",
|
247 |
+
"apollo_chunk_size_info": "Taille de fragment pour l'amélioration Apollo (recommandé : 19 pour le modèle universel)",
|
248 |
+
"apollo_overlap": "Chevauchement Apollo",
|
249 |
+
"enhancing_with_apollo": "Amélioration avec Apollo ({}/{} fichiers)...",
|
250 |
+
"apollo_processing_completed": "Traitement Apollo terminé !",
|
251 |
+
"apollo_overlap_info": "Chevauchement pour l'amélioration Apollo (recommandé : 2)",
|
252 |
+
"invalid_method": "Erreur : Méthode invalide ! Utilisez 'gradio', 'localtunnel' ou 'ngrok'.",
|
253 |
+
"apollo_enhancement_settings": "Paramètres d'amélioration Apollo",
|
254 |
+
"enhance_with_apollo": "Améliorer avec Apollo",
|
255 |
+
"enhance_with_apollo_info": "Activer Apollo pour l'amélioration audio après la séparation",
|
256 |
+
"apollo_method": "Méthode Apollo",
|
257 |
+
"apollo_method_info": "Sélectionnez la méthode de traitement pour Apollo",
|
258 |
+
"normal_method": "Méthode normale",
|
259 |
+
"mid_side_method": "Méthode centre/côté",
|
260 |
+
"apollo_normal_model": "Modèle Apollo normal",
|
261 |
+
"apollo_normal_model_info": "Modèle à utiliser pour le traitement Apollo normal",
|
262 |
+
"apollo_midside_model": "Modèle Apollo centre/côté",
|
263 |
+
"apollo_enhancement_info": "Amélioration de la qualité sonore",
|
264 |
+
"selected_models": "Modèles Sélectionnés",
|
265 |
+
"save_preset": "Enregistrer le Préréglage",
|
266 |
+
"delete_preset": "Supprimer le Préréglage",
|
267 |
+
"refresh_presets": "Actualiser les Préréglages",
|
268 |
+
"preset_name": "Nom du Préréglage",
|
269 |
+
"select_preset": "Sélectionner un Préréglage",
|
270 |
+
"add_favorite": "Ajouter aux Favoris",
|
271 |
+
"apollo_midside_model_info": "Modèle à utiliser pour le traitement centre/côté (optionnel)",
|
272 |
+
"language_changed_message": "Langue modifiée. Veuillez redémarrer la cellule."
|
273 |
+
}
|
assets/i18n/languages/hi_in.json
ADDED
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "भाषा चुनें",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "आपका अंतिम ऑडियो पृथक्करण",
|
5 |
+
"presented_by": "Gecekondu Production © 2025 द्वारा प्रस्तुत",
|
6 |
+
"audio_separation_tab": "🎙️ ऑडियो पृथक्करण",
|
7 |
+
"input_model": "📥 इनपुट और मॉडल",
|
8 |
+
"upload": "🖥 अपलोड करें",
|
9 |
+
"path": "📂 पथ",
|
10 |
+
"path_placeholder": "/पथ/से/ऑडियो.wav",
|
11 |
+
"category": "श्रेणी",
|
12 |
+
"model": "मॉडल",
|
13 |
+
"settings": "⚙ सेटिंग्स",
|
14 |
+
"format": "प्रारूप",
|
15 |
+
"chunk_size": "खंड आकार",
|
16 |
+
"chunk_size_info": "जब तक आपके पास विशिष्ट आवश्यकताएं न हों, इसे न बदलें",
|
17 |
+
"overlap": "ओवरलैप",
|
18 |
+
"overlap_info": "अनुशंसित: 2-10 (उच्च मान गुणवत्ता बढ़ाते हैं लेकिन अधिक VRAM की आवश्यकता होती है)",
|
19 |
+
"tta_boost": "TTA बूस्ट",
|
20 |
+
"tta_info": "गुणवत्ता में सुधार करता है लेकिन प्रसंस्करण गति को धीमा करता है",
|
21 |
+
"phase_fix": "फेज सुधार",
|
22 |
+
"phase_fix_info": "वाद्य ट्रैक के लिए उन्नत फेज सुधार",
|
23 |
+
"instrumental": "वाद्य",
|
24 |
+
"instrumental_info": "आमतौर पर 2 आउटपुट देता है, लेकिन कभी-कभी एक ही आउटपुट देता है, आपको कोशिश करनी होगी :)",
|
25 |
+
"process": "🚀 प्रक्रिया करें",
|
26 |
+
"reset": "🧹 रीसेट करें",
|
27 |
+
"status": "स्थिति",
|
28 |
+
"main_tab": "🎧 मुख्य",
|
29 |
+
"original": "मूल",
|
30 |
+
"vocals": "स्वर",
|
31 |
+
"instrumental_output": "वाद्य",
|
32 |
+
"other": "अन्य",
|
33 |
+
"details_tab": "🔍 विवरण",
|
34 |
+
"male": "पुरुष",
|
35 |
+
"female": "महिला",
|
36 |
+
"speech": "भाषण",
|
37 |
+
"drums": "ड्रम",
|
38 |
+
"bass": "बास",
|
39 |
+
"effects": "प्रभाव",
|
40 |
+
"advanced_tab": "⚙ उन्नत",
|
41 |
+
"phase_remix": "फेज रीमिक्स",
|
42 |
+
"dry": "शुष्क",
|
43 |
+
"music": "संगीत",
|
44 |
+
"karaoke": "कराओके",
|
45 |
+
"bleed": "रिसाव",
|
46 |
+
"copy_to_drive": "📂 ड्राइव पर कॉपी करें",
|
47 |
+
"copy_status": "कॉपी स्थिति",
|
48 |
+
"files_will_be_copied": "फाइलें यहाँ कॉपी की जाएंगी...",
|
49 |
+
"processing_tip": "<b>🔈 प्रसंस्करण टिप:</b> शोरयुक्त परिणामों के लिए, <i>\"शोर और प्रभाव हटाने\"</i> श्रेणी में <code>bleed_suppressor_v1</code> या <code>denoisedebleed</code> मॉडल का उपयोग करें ताकि आउटपुट साफ हो",
|
50 |
+
"waiting_for_processing": "प्रसंस्करण की प्रतीक्षा में...",
|
51 |
+
"auto_ensemble_tab": "🤖 स्वचालित संयोजन",
|
52 |
+
"upload_file": "फाइल अपलोड करें",
|
53 |
+
"enter_file_path": "या फाइल पथ दर्ज करें",
|
54 |
+
"file_path_placeholder": "ऑडियो फाइल का पूरा पथ दर्ज करें",
|
55 |
+
"advanced_settings": "⚙️ उन्नत सेटिंग्स",
|
56 |
+
"use_tta": "TTA का उपयोग करें",
|
57 |
+
"instrumental_only": "केवल वाद्य",
|
58 |
+
"auto_overlap": "ओवरलैप",
|
59 |
+
"auto_chunk_size": "खंड आकार",
|
60 |
+
"output_format": "आउटपुट प्रारूप",
|
61 |
+
"model_selection": "🧠 मॉडल चयन",
|
62 |
+
"model_category": "मॉडल श्रेणी",
|
63 |
+
"select_models": "श्रेणी से मॉडल चुनें",
|
64 |
+
"ensemble_settings": "⚡ संयोजन सेटिंग्स",
|
65 |
+
"method": "विधि",
|
66 |
+
"recommendation": "**सिफारिश:** avg_wave और max_fft सर्वोत्तम परिणाम देते हैं",
|
67 |
+
"start_processing": "🚀 प्रसंस्करण शुरू करें",
|
68 |
+
"original_audio_tab": "🔊 मूल ऑडियो",
|
69 |
+
"original_audio": "मूल ऑडियो",
|
70 |
+
"ensemble_result_tab": "🎚️ संयोजन परिणाम",
|
71 |
+
"output_preview": "आउटपुट पूर्वावलोकन",
|
72 |
+
"refresh_output": "🔄 आउटपुट ताज़ा करें",
|
73 |
+
"ensemble_copy_status": "संयोजन आउटपुट यहाँ कॉपी किया जाएगा...",
|
74 |
+
"guidelines": "<h4>मॉडल चयन दिशानिर्देश</h4><ul><li><strong>क्रॉस-श्रेणी मिश्रण से बचें:</strong> स्वर और वाद्य मॉडल का संयोजन अवांछित मिश्रण बना सकता है</li><li><strong>विशेष मॉडल नोट्स:</strong><ul><li>द्वैत मॉडल (v1/v2) - दोनों स्टेम्स आउटपुट करते हैं</li><li>MDX23C सेपरेटर - हाइब्रिड परिणाम</li></ul></li><li><strong>सर्वोत्तम अभ्यास:</strong> एक ही श्रेणी से 3-5 समान मॉडल का उपयोग करें</li></ul><div>💡 प्रो टिप: \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\" संयोजन से शुरू करें</div>",
|
75 |
+
"download_sources_tab": "⬇️ स्रोत डाउनलोड करें",
|
76 |
+
"direct_links": "🌐 सीधे लिंक",
|
77 |
+
"audio_file_url": "ऑडियो फाइल URL",
|
78 |
+
"download_from_url": "⬇️ URL से डाउनलोड करें",
|
79 |
+
"download_status": "डाउनलोड स्थिति",
|
80 |
+
"downloaded_file": "डाउनलोड की गई फाइल",
|
81 |
+
"cookie_management": "🍪 कुकी प्रबंधन",
|
82 |
+
"upload_cookies_txt": "Cookies.txt अपलोड करें",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 क्यों जरूरी?**<br>- आयु-प्रतिबंधित सामग्री तक पहुंच<br>- निजी/असूचीबद्ध वीडियो डाउनलोड करें<br>- क्षेत्रीय प्रतिबंधों को बायपास करें<br>- यूट्यूब डाउनलोड सीमाओं से बचें<br><br>**⚠️ महत्वपूर्ण नोट्स**<br>- अपनी कुकी फाइलें कभी साझा न करें!<br>- कुकीज़ को ताज़ा करें जब:<br> • \"403 निषिद्ध\" त्रुटियाँ मिलें<br> • डाउनलोड अचानक रुक जाएँ<br> • \"सत्र समाप्त\" संदेश दिखें<br><br>**🔄 नवीकरण चरण**<br>1. इस <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">क्रोम एक्सटेंशन</a> को स्थापित करें<br>2. क्रोम में यूट्यूब में लॉगिन करें<br>3. एक्सटेंशन आइकन पर क्लिक करें → \"निर्यात\"<br>4. डाउनलोड की गई फाइल यहाँ अपलोड करें<br><br>**⏳ कुकी जीवनकाल**<br>- सामान्य सत्र: 24 घंटे<br>- संवेदनशील संचालन: 1 घंटा<br>- पासवर्ड परिवर्तन: तत्काल अमान्यता</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ मैनुअल संयोजन",
|
85 |
+
"input_sources": "📂 इनपुट स्रोत",
|
86 |
+
"refresh": "🔄 ताज़ा करें",
|
87 |
+
"ensemble_algorithm": "संयोजन एल्गोरिदम",
|
88 |
+
"select_audio_files": "ऑडियो फाइलें चुनें",
|
89 |
+
"available_files": "उपलब्ध फाइलें",
|
90 |
+
"custom_weights": "कस्टम वेट्स (अल्पविराम से अलग)",
|
91 |
+
"custom_weights_placeholder": "उदाहरण: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "समान वेट्स के लिए खाली छोड़ें",
|
93 |
+
"result_preview_tab": "🎧 परिणाम पूर्वावलोकन",
|
94 |
+
"ensembled_output": "संयोजित आउटपुट",
|
95 |
+
"processing_log_tab": "📋 प्रसंस्करण लॉग",
|
96 |
+
"processing_details": "प्रसंस्करण विवरण",
|
97 |
+
"process_ensemble": "⚡ संयोजन प्रक्रिया करें",
|
98 |
+
"languages_tab": "🌐 भाषाएँ",
|
99 |
+
"Vocal Models": "स्वर मॉडल",
|
100 |
+
"Instrumental Models": "वाद्य मॉडल",
|
101 |
+
"4-Stem Models": "4-स्टेम मॉडल",
|
102 |
+
"Denoise Models": "शोर हटाने के मॉडल",
|
103 |
+
"Dereverb Models": "रिवर्ब हटाने के मॉडल",
|
104 |
+
"Other Models": "अन्य मॉडल",
|
105 |
+
"ensemble_files_description": "निर्दिष्ट संयोजन विधियों का उपयोग करके कई ऑडियो फाइलों को एक ही आउटपुट में जोड़ता है।",
|
106 |
+
"ensemble_files_help": "संयोजन के लिए सभी ऑडियो फाइलों का पथ",
|
107 |
+
"ensemble_type_help": "avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft में से एक",
|
108 |
+
"ensemble_weights_help": "संयोजन बनाने के लिए वेट्स। वेट्स की संख्या फाइलों की संख्या के बराबर होनी चाहिए",
|
109 |
+
"ensemble_output_help": "WAV फाइल का पथ जहां संयोजन परिणाम संग्रहीत होगा",
|
110 |
+
"ensemble_type_print": "संयोजन प्रकार: {}",
|
111 |
+
"num_input_files_print": "इनपुट फाइलों की संख्या: {}",
|
112 |
+
"weights_print": "वेट्स: {}",
|
113 |
+
"output_file_print": "आउटपुट फाइल: {}",
|
114 |
+
"duration_mismatch_error": "सभी फाइलों की अवधि समान होनी चाहिए",
|
115 |
+
"file_not_found_error": "त्रुटि। फाइल नहीं मिली: {}। पथ जांचें।",
|
116 |
+
"reading_chunk_print": "फाइल से खंड पढ़ रहा है: {} (शुरुआत: {}सेकंड, अवधि: {}सेकंड)",
|
117 |
+
"chunk_result_shape_print": "खंड परिणाम आकार: {}",
|
118 |
+
"ensemble_completed_print": "संयोजन पूरा हुआ। आउटपुट यहाँ संग्रहीत: {}",
|
119 |
+
"file_deletion_error": "{} हटाया नहीं जा सका: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ डायरेक्टरी मौजूद नहीं है: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ पथ डायरेक्टरी नहीं है: {}",
|
122 |
+
"item_deletion_error": "⚠️ {} हटाने में त्रुटि: {}",
|
123 |
+
"old_output_not_exist": "❌ पुराना आउटपुट फ़ोल्डर मौजूद नहीं है",
|
124 |
+
"old_outputs_cleared": "✅ पुराने आउटपुट सफलतापूर्वक हटा दिए गए!",
|
125 |
+
"error": "🔥 त्रुटि: {}",
|
126 |
+
"ffmpeg_error": "FFmpeg त्रुटि ({}): {}",
|
127 |
+
"file_saved_successfully": "फाइल सफलतापूर्वक संग्रहीत: {}",
|
128 |
+
"total_files_found": "कुल फाइलें मिलीं: {}। सैंपल रेट का उपयोग: {}",
|
129 |
+
"total_progress": "कुल प्रगति",
|
130 |
+
"detailed_pbar_enabled": "विस्तृत प्रगति बार सक्षम: {}",
|
131 |
+
"loaded_audio": "लोड किया गया ऑडियो: {}, आकार: {}",
|
132 |
+
"cannot_read_track": "ट्रैक पढ़ा नहीं जा सकता: {}",
|
133 |
+
"error_message": "त्रुटि संदेश: {}",
|
134 |
+
"demudding_track": "ट्रैक को डिमड कर रहा है (फेज रीमिक्स - वाद्य): {}",
|
135 |
+
"elapsed_time": "बीता हुआ समय: {:.2f} सेकंड।",
|
136 |
+
"proc_folder_description": "एक निर्दिष्ट मॉडल का उपयोग करके फ़ोल्डर में ऑडियो फाइलों को प्रोसेस करता है।",
|
137 |
+
"model_type_help": "मॉडल प्रकार (bandit, bs_roformer, mdx23c, आदि)",
|
138 |
+
"config_path_help": "कॉन्फ़िग फाइल का पथ",
|
139 |
+
"demud_phaseremix_help": "वाद्य के लिए फेज रीमिक्स सक्षम करें",
|
140 |
+
"start_checkpoint_help": "मान्य वेट्स के लिए प्रारंभिक चेकपॉइंट",
|
141 |
+
"input_folder_help": "प्रोसेस करने के लिए मिश्रणों वाला फ़ोल्डर",
|
142 |
+
"audio_path_help": "प्रोसेस करने के लिए एकल ऑडियो फाइल का पथ",
|
143 |
+
"store_dir_help": "परिणाम संग्रहीत करने का पथ",
|
144 |
+
"device_ids_help": "GPU IDs की सूची",
|
145 |
+
"extract_instrumental_help": "यदि प्रदान किया गया हो तो स्वर को उलटकर वाद्य प्राप्त करें",
|
146 |
+
"disable_detailed_pbar_help": "डिमिक्स में विस्तृत प्रगति बार अक्षम करें",
|
147 |
+
"force_cpu_help": "CUDA उपलब्ध होने पर भी CPU का उपयोग करें",
|
148 |
+
"flac_file_help": "WAV के बजाय FLAC फाइल आउटपुट करें",
|
149 |
+
"export_format_help": "निर्यात प्रारूप और PCM प्रकार",
|
150 |
+
"pcm_type_help": "FLAC फाइलों के लिए PCM प्रकार",
|
151 |
+
"use_tta_help": "टेस्ट टाइम ऑगमेंटेशन सक्षम करें",
|
152 |
+
"lora_checkpoint_help": "LoRA वेट्स के लिए प्रारंभिक चेकपॉइंट",
|
153 |
+
"cuda_available": "CUDA उपलब्ध है, इसे अक्षम करने के लिए --force_cpu का उपयोग करें।",
|
154 |
+
"using_device": "उपयोग किया जा रहा डिवाइस: {}",
|
155 |
+
"instruments_print": "वाद्य: {}",
|
156 |
+
"model_load_time": "मॉडल लोड समय: {:.2f} सेकंड",
|
157 |
+
"invalid_url": "❌ अमान्य URL",
|
158 |
+
"cookie_file_updated": "✅ कुकी फाइल अपडेट की गई!",
|
159 |
+
"cookie_installation_error": "⚠️ कुकी स्थापना त्रुटि: {}",
|
160 |
+
"file_size_zero_error": "फाइल आकार शून्य या फाइल नहीं बनाई गई",
|
161 |
+
"google_drive_error": "❌ Google Drive डाउनलोड त्रुटि: {}",
|
162 |
+
"wav_conversion_failed": "WAV रूपांतरण विफल",
|
163 |
+
"download_error": "❌ डाउनलोड त्रुटि: {}",
|
164 |
+
"download_success": "🎉 सफलतापूर्वक डाउनलोड किया गया!",
|
165 |
+
"download_failed": "❌ डाउनलोड विफल",
|
166 |
+
"no_output_files_found": "❌ कोई आउटपुट फाइलें नहीं मिलीं।",
|
167 |
+
"output_refreshed_successfully": "✅ आउटपुट सफलतापूर्वक ताज़ा किया गया!",
|
168 |
+
"error_refreshing_output": "❌ आउटपुट ताज़ा करने में त्रुटि: {}",
|
169 |
+
"starting_audio_separation": "ऑडियो पृथक्करण शुरू हो रहा है...",
|
170 |
+
"processing_audio": "ऑडियो प्रोसेसिंग",
|
171 |
+
"separating_audio": "ऑडियो अलग कर रहा है... ({:.1f}%)",
|
172 |
+
"separation_complete": "पृथक्करण पूरा!",
|
173 |
+
"progress_parsing_error": "प्रगति पार्सिंग त्रुटि: {}",
|
174 |
+
"error_occurred": "एक त्रुटि हुई: {}",
|
175 |
+
"separation_process_completed": "पृथक्करण प्रक्रिया पूरी हुई!",
|
176 |
+
"no_audio_file_error": "❌ कोई ऑडियो फाइल प्रदान नहीं की गई और इनपुट डायरेक्टरी में कोई मौजूदा फाइल नहीं है।",
|
177 |
+
"no_input_progress_label": "त्रुटि: कोई इनपुट प्रदान नहीं किया गया -- 0.0%",
|
178 |
+
"processing_audio_print": "ऑडियो प्रोसेसिंग: {} से मॉडल का उपयोग करके: {}",
|
179 |
+
"starting_audio_separation_progress_label": "ऑडियो पृथक्करण शुरू हो रहा है... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "ऑडियो अलग कर रहा है... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "ऑडियो प्रोसेसिंग पूरी हुई! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ ऑडियो प्रोसेसिंग पूरी हुई!",
|
183 |
+
"error_occurred_progress_label": "त्रुटि हुई -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ न्यूनतम 2 फाइलें आवश्यक",
|
185 |
+
"valid_files_not_found": "❌ मान्य फाइलें नहीं मिलीं",
|
186 |
+
"starting_ensemble_process": "संयोजन प्रक्रिया शुरू हो रही है...",
|
187 |
+
"ensembling_progress": "संयोजन कर रहा है... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "संयोजन आउटपुट को अंतिम रूप दे रहा है...",
|
189 |
+
"success_log": "✅ सफलता!\n{}",
|
190 |
+
"error_log": "❌ त्रुटि!\n{}",
|
191 |
+
"critical_error": "⛔ गंभीर त्रुटि: {}",
|
192 |
+
"ensemble_process_completed": "संयोजन प्रक्रिया पूरी हुई!",
|
193 |
+
"no_models_selected": "❌ कोई मॉडल चयनित नहीं",
|
194 |
+
"no_input_audio_provided": "❌ कोई इनपुट ऑडियो प्रदान नहीं किया गया",
|
195 |
+
"loading_model": "मॉडल लोड कर रहा है {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "मॉडल लोड कर रहा है {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "मॉडल पूरा हुआ {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "मॉडल पूरा हुआ {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "कमांड चला रहा है: {}",
|
200 |
+
"model_failed": "मॉडल {} विफल: {}",
|
201 |
+
"critical_error_with_model": "{} के साथ गंभीर त्रुटि: {}",
|
202 |
+
"model_output_failed": "{} आउटपुट उत्पन्न करने में विफल",
|
203 |
+
"waiting_for_files": "सभी फाइलों के तैयार होने की प्रतीक्षा में...",
|
204 |
+
"waiting_for_files_progress_label": "सभी फाइलों के तैयार होने की प्रतीक्षा में... -- 90.0%",
|
205 |
+
"performing_ensemble": "संयोजन कर रहा है...",
|
206 |
+
"performing_ensemble_progress_label": "संयोजन कर रहा है... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "संयोजन से पहले मेमोरी उपयोग: {}%",
|
208 |
+
"memory_usage_after_ensemble": "संयोजन के बाद मेमोरी उपयोग: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "संयोजन आउटपुट को अंतिम रूप दे रहा है... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "संयोजन फाइल बनाई नहीं जा सकी: {}",
|
211 |
+
"ensemble_completed_progress_label": "संयोजन सफलतापूर्वक पूरा हुआ! -- 100.0%",
|
212 |
+
"success_output_created": "✅ सफलता! आउटपुट फाइल बनाई गई।",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive माउंट किया गया। संयोजन आउटपुट कॉपी हो रहा है...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive पहले से माउंट है। संयोजन आउटपुट कॉपी हो रहा है...",
|
215 |
+
"no_ensemble_output_files_found": "❌ कोई संयोजन आउटपुट फाइलें नहीं मिलीं।",
|
216 |
+
"ensemble_output_copied": "✅ संयोजन आउटपुट {} पर कॉपी किया गया",
|
217 |
+
"error_copying_ensemble_output": "❌ संयोजन आउटपुट कॉपी करने में त्रुटि: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive माउंट किया गया। फाइलें कॉपी हो रही हैं...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive पहले से माउंट है। फाइलें कॉपी हो रही हैं...",
|
220 |
+
"files_copied_to_drive": "✅ फाइलें {} पर कॉपी की गईं",
|
221 |
+
"error_copying_files": "❌ फाइलें कॉपी करने में त्रुटि: {}",
|
222 |
+
"mounting_drive": "Google Drive माउंट कर रहा है...",
|
223 |
+
"settings_saved": "सेटिंग्स config.json में संग्रहीत: भाषा={lang}, विधि={method}, पोर्ट={port}",
|
224 |
+
"selected_language": "चयनित भाषा: {lang}",
|
225 |
+
"available_languages": "उपलब्ध भाषाएँ: {langs}",
|
226 |
+
"select_language_prompt": "एक भाषा चुनें (डिफ़ॉल्ट: {default}): ",
|
227 |
+
"invalid_language": "अमान्य भाषा चयन! डिफ़ॉल्ट भाषा का उपयोग कर रहा हूँ ({default})।",
|
228 |
+
"available_sharing_methods": "उपलब्ध साझाकरण विधियाँ: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "एक साझाकरण विधि चुनें (डिफ़ॉल्ट: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "अपना Ngrok टोकन दर्ज करें (डिफ़ॉल्ट: {default}): ",
|
231 |
+
"ngrok_token_required": "त्रुटि: ngrok विधि के लिए Ngrok टोकन आवश्यक है!",
|
232 |
+
"enter_port_prompt": "पोर्ट नंबर दर्ज करें (डिफ़ॉल्ट: {default}): ",
|
233 |
+
"opening_previous_url": "पिछला URL खोल रहा है: {url}",
|
234 |
+
"open_url_manually": "Colab में URL मैन्युअल रूप से खोलें: {url}",
|
235 |
+
"invalid_previous_url": "अमान्य पिछला URL: {url}, खोला नहीं गया।",
|
236 |
+
"starting_method": "{method} को पोर्ट {port} पर शुरू कर रहा है...",
|
237 |
+
"process_stopped": "\n🛑 उपयोगकर्ता द्वारा प्रक्रिया रोक दी गई",
|
238 |
+
"selected_port": "चयनित पोर्ट: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Gradio को अंतर्निहित साझाकरण के साथ शुरू कर रहा है...",
|
240 |
+
"starting_localtunnel": "Localtunnel को पोर्ट {port} पर शुरू कर रहा है...",
|
241 |
+
"share_link": "साझा लिंक: {url}",
|
242 |
+
"password_ip": "पासवर्ड IP: {ip}",
|
243 |
+
"starting_ngrok": "Ngrok को पोर्ट {port} पर शुरू कर रहा है...",
|
244 |
+
"ngrok_url": "Ngrok URL: {url}",
|
245 |
+
"ngrok_error": "Ngrok शुरू करने में त्रुटि: {error}",
|
246 |
+
"apollo_chunk_size": "Apollo खंड आकार",
|
247 |
+
"apollo_chunk_size_info": "Apollo सुधार के लिए खंड आकार (यूनिवर्सल मॉडल के लिए अनुशंसित: 19)",
|
248 |
+
"apollo_overlap": "Apollo ओवरलैप",
|
249 |
+
"enhancing_with_apollo": "Apollo के साथ सुधार कर रहा है ({}/{} फाइलें)...",
|
250 |
+
"apollo_processing_completed": "Apollo प्रसंस्करण पूरा!",
|
251 |
+
"apollo_overlap_info": "Apollo सुधार के लिए ओवरलैप (अनुशंसित: 2)",
|
252 |
+
"invalid_method": "त्रुटि: अमान्य विधि! 'gradio', 'localtunnel', या 'ngrok' का उपयोग करें।",
|
253 |
+
"apollo_enhancement_settings": "Apollo सुधार सेटिंग्स",
|
254 |
+
"enhance_with_apollo": "Apollo के साथ सुधार करें",
|
255 |
+
"enhance_with_apollo_info": "पृथक्करण के बाद ऑडियो सुधार के लिए Apollo सक्षम करें",
|
256 |
+
"apollo_method": "Apollo विधि",
|
257 |
+
"apollo_method_info": "Apollo के लिए प्रसंस्करण विधि चुनें",
|
258 |
+
"normal_method": "सामान्य विधि",
|
259 |
+
"mid_side_method": "मध्य/पार्श्व विधि",
|
260 |
+
"apollo_normal_model": "Apollo सामान्य मॉडल",
|
261 |
+
"apollo_normal_model_info": "सामान्य Apollo प्रसंस्करण के लिए उपयोग करने वाला मॉडल",
|
262 |
+
"apollo_midside_model": "Apollo मध्य/पार्श्व मॉडल",
|
263 |
+
"apollo_enhancement_info": "ध्वनि गुणवत्ता सुधार",
|
264 |
+
"selected_models": "चयनित मॉडल",
|
265 |
+
"save_preset": "प्रीसेट सहेजें",
|
266 |
+
"delete_preset": "प्रीसेट हटाएं",
|
267 |
+
"refresh_presets": "प्रीसेट रिफ्रेश करें",
|
268 |
+
"presets_name": "प्रीसेट का नाम",
|
269 |
+
"select_preset": "प्रीसेट चुनें",
|
270 |
+
"add_favorite": "पसंदीदा में जोड़ें",
|
271 |
+
"apollo_midside_model_info": "मध्य/पार्श्व प्रसंस्करण के लिए उपयोग करने वाला मॉडल (वैकल्पिक)",
|
272 |
+
"language_changed_message": "भाषा बदली गई। कृपया सेल को पुनः शुरू करें।"
|
273 |
+
"selected_models": "選択されたモデル",
|
274 |
+
"save_preset": "プリセットを保存",
|
275 |
+
"delete_preset": "プリセットを削除",
|
276 |
+
"refresh_presets": "プリセットを更新",
|
277 |
+
"preset_name": "プリセット名",
|
278 |
+
"select_preset": "プリセットを選択",
|
279 |
+
"add_favorite": "お気に入りに追加",
|
280 |
+
"apply_matchering": "मैचरिंग लागू करें",
|
281 |
+
"matchering_info": "ऑडियो मास्टरिंग और संतुलन को बढ़ाने के लिए मैचरिंग लागू करें",
|
282 |
+
"matchering_passes": "मैचरिंग पास",
|
283 |
+
"matchering_passes_info": "मैचरिंग की पुनरावृत्तियों की संख्या (1-5, उच्च मान गुणवत्ता को बेहतर बनाते हैं लेकिन अधिक समय लेते हैं)",
|
284 |
+
"matchering_processing": "मैचरिंग लागू किया जा रहा है... ({:.1f}%)",
|
285 |
+
"matchering_completed": "✅ मैचरिंग प्रक्रिया पूरी हुई!",
|
286 |
+
"matchering_error": "❌ मैचरिंग के दौरान त्रुटि: {}"
|
287 |
+
}
|
assets/i18n/languages/it_it.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Seleziona lingua",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "La tua separazione audio definitiva",
|
5 |
+
"presented_by": "Presentato da Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ Separazione audio",
|
7 |
+
"input_model": "📥 Input e modello",
|
8 |
+
"upload": "🖥 Carica",
|
9 |
+
"path": "📂 Percorso",
|
10 |
+
"path_placeholder": "/percorso/a/audio.wav",
|
11 |
+
"category": "Categoria",
|
12 |
+
"model": "Modello",
|
13 |
+
"settings": "⚙ Impostazioni",
|
14 |
+
"format": "Formato",
|
15 |
+
"chunk_size": "Dimensione frammento",
|
16 |
+
"chunk_size_info": "Non modificare a meno che non ci siano esigenze specifiche",
|
17 |
+
"overlap": "Sovrapposizione",
|
18 |
+
"overlap_info": "Consigliato: 2-10 (valori più alti migliorano la qualità ma richiedono più VRAM)",
|
19 |
+
"tta_boost": "Boost TTA",
|
20 |
+
"tta_info": "Migliora la qualità ma rallenta la velocità di elaborazione",
|
21 |
+
"phase_fix": "Correzione fase",
|
22 |
+
"phase_fix_info": "Correzione avanzata della fase per tracce strumentali",
|
23 |
+
"instrumental": "Strumentale",
|
24 |
+
"instrumental_info": "Di solito produce 2 output, ma a volte solo uno, prova! :)",
|
25 |
+
"process": "🚀 Elabora",
|
26 |
+
"reset": "🧹 Ripristina",
|
27 |
+
"status": "Stato",
|
28 |
+
"main_tab": "🎧 Principale",
|
29 |
+
"original": "Originale",
|
30 |
+
"vocals": "Vocali",
|
31 |
+
"instrumental_output": "Strumentale",
|
32 |
+
"other": "Altro",
|
33 |
+
"details_tab": "🔍 Dettagli",
|
34 |
+
"male": "Maschile",
|
35 |
+
"female": "Femminile",
|
36 |
+
"speech": "Parlato",
|
37 |
+
"drums": "Batteria",
|
38 |
+
"bass": "Basso",
|
39 |
+
"effects": "Effetti",
|
40 |
+
"advanced_tab": "⚙ Avanzato",
|
41 |
+
"phase_remix": "Remix fase",
|
42 |
+
"dry": "Secco",
|
43 |
+
"music": "Musica",
|
44 |
+
"karaoke": "Karaoke",
|
45 |
+
"bleed": "Sanguinamento",
|
46 |
+
"copy_to_drive": "📂 Copia su Drive",
|
47 |
+
"copy_status": "Stato copia",
|
48 |
+
"files_will_be_copied": "I file verranno copiati qui...",
|
49 |
+
"processing_tip": "<b>🔈 Suggerimento per l'elaborazione:</b> Per risultati rumorosi, usa i modelli <code>bleed_suppressor_v1</code> o <code>denoisedebleed</code> nella categoria <i>\"Rimozione rumore ed effetti\"</i> per pulire l'output",
|
50 |
+
"waiting_for_processing": "In attesa di elaborazione...",
|
51 |
+
"auto_ensemble_tab": "🤖 Ensemble automatico",
|
52 |
+
"upload_file": "Carica file",
|
53 |
+
"enter_file_path": "O inserisci il percorso del file",
|
54 |
+
"file_path_placeholder": "Inserisci il percorso completo del file audio",
|
55 |
+
"advanced_settings": "⚙️ Impostazioni avanzate",
|
56 |
+
"use_tta": "Usa TTA",
|
57 |
+
"instrumental_only": "Solo strumentale",
|
58 |
+
"auto_overlap": "Sovrapposizione",
|
59 |
+
"auto_chunk_size": "Dimensione frammento",
|
60 |
+
"output_format": "Formato di output",
|
61 |
+
"model_selection": "🧠 Selezione modello",
|
62 |
+
"model_category": "Categoria modello",
|
63 |
+
"select_models": "Seleziona modelli dalla categoria",
|
64 |
+
"ensemble_settings": "⚡ Impostazioni ensemble",
|
65 |
+
"method": "Metodo",
|
66 |
+
"recommendation": "**Raccomandazione:** avg_wave e max_fft offrono i migliori risultati",
|
67 |
+
"start_processing": "🚀 Avvia elaborazione",
|
68 |
+
"original_audio_tab": "🔊 Audio originale",
|
69 |
+
"original_audio": "Audio originale",
|
70 |
+
"ensemble_result_tab": "🎚️ Risultato ensemble",
|
71 |
+
"output_preview": "Anteprima output",
|
72 |
+
"refresh_output": "🔄 Aggiorna output",
|
73 |
+
"ensemble_copy_status": "L'output dell'ensemble verrà copiato qui...",
|
74 |
+
"guidelines": "<h4>Linee guida per la selezione dei modelli</h4><ul><li><strong>Evita di mescolare categorie:</strong> Combinare modelli vocali e strumentali può creare mix indesiderati</li><li><strong>Note sui modelli speciali:</strong><ul><li>Modelli dualità (v1/v2) - Producono entrambi i canali</li><li>Separatore MDX23C - Risultati ibridi</li></ul></li><li><strong>Migliore pratica:</strong> Usa 3-5 modelli simili della stessa categoria</li></ul><div>💡 Consiglio pro: Inizia con la combinazione \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\"</div>",
|
75 |
+
"download_sources_tab": "⬇️ Scarica sorgenti",
|
76 |
+
"direct_links": "🌐 Link diretti",
|
77 |
+
"audio_file_url": "URL file audio",
|
78 |
+
"download_from_url": "⬇️ Scarica da URL",
|
79 |
+
"download_status": "Stato download",
|
80 |
+
"downloaded_file": "File scaricato",
|
81 |
+
"cookie_management": "🍪 Gestione cookie",
|
82 |
+
"upload_cookies_txt": "Carica Cookies.txt",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 Perché è necessario?**<br>- Accesso a contenuti con restrizione d'età<br>- Download di video privati/non elencati<br>- Superamento delle restrizioni regionali<br>- Evitare i limiti di download di YouTube<br><br>**⚠️ Note importanti**<br>- NON CONDIVIDERE MAI i tuoi file cookie!<br>- Aggiorna i cookie quando:<br> • Ricevi errori \"403 Vietato\"<br> • I download si interrompono improvvisamente<br> • Vedi il messaggio \"Sessione scaduta\"<br><br>**🔄 Passaggi per l'aggiornamento**<br>1. Installa questa <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">estensione Chrome</a><br>2. Accedi a YouTube su Chrome<br>3. Clicca sull'icona dell'estensione → \"Esporta\"<br>4. Carica il file scaricato qui<br><br>**⏳ Durata dei cookie**<br>- Sessioni normali: 24 ore<br>- Operazioni sensibili: 1 ora<br>- Cambio password: Invalidità immediata</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ Ensemble manuale",
|
85 |
+
"input_sources": "📂 Sorgenti di input",
|
86 |
+
"refresh": "🔄 Aggiorna",
|
87 |
+
"ensemble_algorithm": "Algoritmo ensemble",
|
88 |
+
"select_audio_files": "Seleziona file audio",
|
89 |
+
"available_files": "File disponibili",
|
90 |
+
"custom_weights": "Pesi personalizzati (separati da virgole)",
|
91 |
+
"custom_weights_placeholder": "Esempio: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "Lascia vuoto per pesi uguali",
|
93 |
+
"result_preview_tab": "🎧 Anteprima risultato",
|
94 |
+
"ensembled_output": "Output ensemble",
|
95 |
+
"processing_log_tab": "📋 Log di elaborazione",
|
96 |
+
"processing_details": "Dettagli elaborazione",
|
97 |
+
"process_ensemble": "⚡ Elabora ensemble",
|
98 |
+
"languages_tab": "🌐 Lingue",
|
99 |
+
"Vocal Models": "Modelli vocali",
|
100 |
+
"Instrumental Models": "Modelli strumentali",
|
101 |
+
"4-Stem Models": "Modelli a 4 stem",
|
102 |
+
"Denoise Models": "Modelli di denoising",
|
103 |
+
"Dereverb Models": "Modelli di rimozione riverbero",
|
104 |
+
"Other Models": "Altri modelli",
|
105 |
+
"ensemble_files_description": "Combina più file audio in un unico output utilizzando metodi di ensemble specificati.",
|
106 |
+
"ensemble_files_help": "Percorso a tutti i file audio per l'ensemble",
|
107 |
+
"ensemble_type_help": "Uno tra: avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "Pesi per creare l'ensemble. Il numero di pesi deve corrispondere al numero di file",
|
109 |
+
"ensemble_output_help": "Percorso al file WAV dove verrà salvato il risultato dell'ensemble",
|
110 |
+
"ensemble_type_print": "Tipo ensemble: {}",
|
111 |
+
"num_input_files_print": "Numero file input: {}",
|
112 |
+
"weights_print": "Pesi: {}",
|
113 |
+
"output_file_print": "File output: {}",
|
114 |
+
"duration_mismatch_error": "Tutti i file devono avere la stessa durata",
|
115 |
+
"file_not_found_error": "Errore. File non trovato: {}. Controlla i percorsi.",
|
116 |
+
"reading_chunk_print": "Lettura frammento dal file: {} (inizio: {}s, durata: {}s)",
|
117 |
+
"chunk_result_shape_print": "Forma risultato frammento: {}",
|
118 |
+
"ensemble_completed_print": "Ensemble completato. Output salvato in: {}",
|
119 |
+
"file_deletion_error": "{} non può essere eliminato: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ La directory non esiste: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ Il percorso non è una directory: {}",
|
122 |
+
"item_deletion_error": "⚠️ Errore durante l'eliminazione di {}: {}",
|
123 |
+
"old_output_not_exist": "❌ La cartella output vecchia non esiste",
|
124 |
+
"old_outputs_cleared": "✅ Output vecchi eliminati con successo!",
|
125 |
+
"error": "🔥 Errore: {}",
|
126 |
+
"ffmpeg_error": "Errore FFmpeg ({}): {}",
|
127 |
+
"file_saved_successfully": "File salvato con successo: {}",
|
128 |
+
"total_files_found": "Totale file trovati: {}. Frequenza di campionamento usata: {}",
|
129 |
+
"total_progress": "Progresso totale",
|
130 |
+
"detailed_pbar_enabled": "Barra di progresso dettagliata abilitata: {}",
|
131 |
+
"loaded_audio": "Audio caricato: {}, forma: {}",
|
132 |
+
"cannot_read_track": "Impossibile leggere la traccia: {}",
|
133 |
+
"error_message": "Messaggio di errore: {}",
|
134 |
+
"demudding_track": "Pulizia traccia (remix fase - strumentale): {}",
|
135 |
+
"elapsed_time": "Tempo trascorso: {:.2f} secondi.",
|
136 |
+
"proc_folder_description": "Elabora i file audio in una cartella usando un modello specificato.",
|
137 |
+
"model_type_help": "Tipo di modello (bandit, bs_roformer, mdx23c, ecc.)",
|
138 |
+
"config_path_help": "Percorso al file di configurazione",
|
139 |
+
"demud_phaseremix_help": "Abilita remix fase per lo strumentale",
|
140 |
+
"start_checkpoint_help": "Punto di controllo iniziale per pesi validi",
|
141 |
+
"input_folder_help": "Cartella contenente i mix da elaborare",
|
142 |
+
"audio_path_help": "Percorso a un singolo file audio da elaborare",
|
143 |
+
"store_dir_help": "Percorso per salvare i risultati",
|
144 |
+
"device_ids_help": "Lista di ID GPU",
|
145 |
+
"extract_instrumental_help": "Inverti le vocali per ottenere lo strumentale, se fornito",
|
146 |
+
"disable_detailed_pbar_help": "Disabilita barra di progresso dettagliata nel demixing",
|
147 |
+
"force_cpu_help": "Forza l'uso della CPU anche se CUDA è disponibile",
|
148 |
+
"flac_file_help": "Genera un file FLAC invece di WAV",
|
149 |
+
"export_format_help": "Formato di esportazione e tipo PCM",
|
150 |
+
"pcm_type_help": "Tipo PCM per file FLAC",
|
151 |
+
"use_tta_help": "Abilita l'aumento del tempo di test",
|
152 |
+
"lora_checkpoint_help": "Punto di controllo iniziale per pesi LoRA",
|
153 |
+
"cuda_available": "CUDA disponibile, usa --force_cpu per disabilitarlo.",
|
154 |
+
"using_device": "Dispositivo in uso: {}",
|
155 |
+
"instruments_print": "Strumenti: {}",
|
156 |
+
"model_load_time": "Tempo di caricamento modello: {:.2f} sec",
|
157 |
+
"invalid_url": "❌ URL non valido",
|
158 |
+
"cookie_file_updated": "✅ File cookie aggiornato!",
|
159 |
+
"cookie_installation_error": "⚠️ Errore installazione cookie: {}",
|
160 |
+
"file_size_zero_error": "Dimensione file zero o file non creato",
|
161 |
+
"google_drive_error": "❌ Errore download Google Drive: {}",
|
162 |
+
"wav_conversion_failed": "Conversione WAV fallita",
|
163 |
+
"download_error": "❌ Errore download: {}",
|
164 |
+
"download_success": "🎉 Download completato con successo!",
|
165 |
+
"download_failed": "❌ Download fallito",
|
166 |
+
"no_output_files_found": "❌ Nessun file output trovato.",
|
167 |
+
"output_refreshed_successfully": "✅ Output aggiornato con successo!",
|
168 |
+
"error_refreshing_output": "❌ Errore durante aggiornamento output: {}",
|
169 |
+
"starting_audio_separation": "Inizio separazione audio...",
|
170 |
+
"processing_audio": "Elaborazione audio",
|
171 |
+
"separating_audio": "Separazione audio... ({:.1f}%)",
|
172 |
+
"separation_complete": "Separazione completata!",
|
173 |
+
"progress_parsing_error": "Errore analisi progresso: {}",
|
174 |
+
"error_occurred": "Si è verificato un errore: {}",
|
175 |
+
"separation_process_completed": "Processo di separazione completato!",
|
176 |
+
"no_audio_file_error": "❌ Nessun file audio fornito e nessun file esistente nella directory di input.",
|
177 |
+
"no_input_progress_label": "Errore: Nessun input fornito -- 0.0%",
|
178 |
+
"processing_audio_print": "Elaborazione audio da: {} usando il modello: {}",
|
179 |
+
"starting_audio_separation_progress_label": "Inizio separazione audio... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "Separazione audio... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "Elaborazione audio completata! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ Elaborazione audio completata!",
|
183 |
+
"error_occurred_progress_label": "Errore verificato -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ Richiesti minimo 2 file",
|
185 |
+
"valid_files_not_found": "❌ Nessun file valido trovato",
|
186 |
+
"starting_ensemble_process": "Inizio processo ensemble...",
|
187 |
+
"ensembling_progress": "Elaborazione ensemble... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "Finalizzazione output ensemble...",
|
189 |
+
"success_log": "✅ Successo!\n{}",
|
190 |
+
"error_log": "❌ Errore!\n{}",
|
191 |
+
"critical_error": "⛔ Errore critico: {}",
|
192 |
+
"ensemble_process_completed": "Processo ensemble completato!",
|
193 |
+
"no_models_selected": "❌ Nessun modello selezionato",
|
194 |
+
"no_input_audio_provided": "❌ Nessun audio input fornito",
|
195 |
+
"loading_model": "Caricamento modello {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "Caricamento modello {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "Modello completato {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "Modello completato {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "Esecuzione comando: {}",
|
200 |
+
"model_failed": "Modello {} fallito: {}",
|
201 |
+
"critical_error_with_model": "Errore critico con {}: {}",
|
202 |
+
"model_output_failed": "{} non è riuscito a produrre output",
|
203 |
+
"waiting_for_files": "In attesa che tutti i file siano pronti...",
|
204 |
+
"waiting_for_files_progress_label": "In attesa che tutti i file siano pronti... -- 90.0%",
|
205 |
+
"performing_ensemble": "Esecuzione ensemble...",
|
206 |
+
"performing_ensemble_progress_label": "Esecuzione ensemble... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "Uso memoria prima dell'ensemble: {}%",
|
208 |
+
"memory_usage_after_ensemble": "Uso memoria dopo l'ensemble: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "Finalizzazione output ensemble... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "Creazione file ensemble fallita: {}",
|
211 |
+
"ensemble_completed_progress_label": "Ensemble completato con successo! -- 100.0%",
|
212 |
+
"success_output_created": "✅ Successo! File output creato.",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive montato. Copia output ensemble...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive già montato. Copia output ensemble...",
|
215 |
+
"no_ensemble_output_files_found": "❌ Nessun file output ensemble trovato.",
|
216 |
+
"ensemble_output_copied": "✅ Output ensemble copiato in {}",
|
217 |
+
"error_copying_ensemble_output": "❌ Errore durante copia output ensemble: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive montato. Copia file...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive già montato. Copia file...",
|
220 |
+
"files_copied_to_drive": "✅ File copiati in {}",
|
221 |
+
"error_copying_files": "❌ Errore durante copia file: {}",
|
222 |
+
"mounting_drive": "Montaggio Google Drive...",
|
223 |
+
"settings_saved": "Impostazioni salvate in config.json: Lingua={lang}, Metodo={method}, Porta={port}",
|
224 |
+
"selected_language": "Lingua selezionata: {lang}",
|
225 |
+
"available_languages": "Lingue disponibili: {langs}",
|
226 |
+
"select_language_prompt": "Seleziona una lingua (default: {default}): ",
|
227 |
+
"invalid_language": "Selezione lingua non valida! Uso lingua default ({default}).",
|
228 |
+
"available_sharing_methods": "Metodi di condivisione disponibili: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "Scegli un metodo di condivisione (default: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "Inserisci il tuo token Ngrok (default: {default}): ",
|
231 |
+
"ngrok_token_required": "Errore: Token Ngrok richiesto per il metodo ngrok!",
|
232 |
+
"enter_port_prompt": "Inserisci il numero di porta (default: {default}): ",
|
233 |
+
"opening_previous_url": "Apertura URL precedente: {url}",
|
234 |
+
"open_url_manually": "Apri l'URL manualmente in Colab: {url}",
|
235 |
+
"invalid_previous_url": "URL precedente non valido: {url}, non aperto.",
|
236 |
+
"starting_method": "Avvio di {method} sulla porta {port}...",
|
237 |
+
"process_stopped": "\n🛑 Processo fermato dall'utente",
|
238 |
+
"selected_port": "Porta selezionata: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Avvio Gradio con condivisione integrata...",
|
240 |
+
"starting_localtunnel": "Avvio Localtunnel sulla porta {port}...",
|
241 |
+
"share_link": "Link di condivisione: {url}",
|
242 |
+
"password_ip": "Password IP: {ip}",
|
243 |
+
"starting_ngrok": "Avvio Ngrok sulla porta {port}...",
|
244 |
+
"ngrok_url": "URL Ngrok: {url}",
|
245 |
+
"ngrok_error": "Errore avvio Ngrok: {error}",
|
246 |
+
"apollo_chunk_size": "Dimensione frammento Apollo",
|
247 |
+
"apollo_chunk_size_info": "Dimensione frammento per miglioramento Apollo (consigliato: 19 per modello universale)",
|
248 |
+
"apollo_overlap": "Sovrapposizione Apollo",
|
249 |
+
"enhancing_with_apollo": "Miglioramento con Apollo ({}/{} file)...",
|
250 |
+
"apollo_processing_completed": "Elaborazione Apollo completata!",
|
251 |
+
"apollo_overlap_info": "Sovrapposizione per miglioramento Apollo (consigliato: 2)",
|
252 |
+
"invalid_method": "Errore: Metodo non valido! Usa 'gradio', 'localtunnel' o 'ngrok'.",
|
253 |
+
"apollo_enhancement_settings": "Impostazioni miglioramento Apollo",
|
254 |
+
"enhance_with_apollo": "Migliora con Apollo",
|
255 |
+
"enhance_with_apollo_info": "Abilita Apollo per migliorare l'audio dopo la separazione",
|
256 |
+
"apollo_method": "Metodo Apollo",
|
257 |
+
"apollo_method_info": "Seleziona il metodo di elaborazione per Apollo",
|
258 |
+
"normal_method": "Metodo normale",
|
259 |
+
"mid_side_method": "Metodo mid/side",
|
260 |
+
"apollo_normal_model": "Modello Apollo normale",
|
261 |
+
"apollo_normal_model_info": "Modello da usare per l'elaborazione Apollo normale",
|
262 |
+
"apollo_midside_model": "Modello Apollo mid/side",
|
263 |
+
"apollo_enhancement_info": "Miglioramento qualità audio",
|
264 |
+
"selected_models": "Modelli Selezionati",
|
265 |
+
"save_preset": "Salva Preimpostazione",
|
266 |
+
"delete_preset": "Elimina Preimpostazione",
|
267 |
+
"refresh_presets": "Aggiorna Preimpostazioni",
|
268 |
+
"preset_name": "Nome Preimpostazione",
|
269 |
+
"select_preset": "Seleziona Preimpostazione",
|
270 |
+
"add_favorite": "Aggiungi ai Preferiti",
|
271 |
+
"apollo_midside_model_info": "Modello da usare per l'elaborazione mid/side (opzionale)",
|
272 |
+
"language_changed_message": "Lingua cambiata. Riavvia la cella.",
|
273 |
+
"apply_matchering": "Applica Matchering",
|
274 |
+
"matchering_info": "Applica Matchering per migliorare il mastering e il bilanciamento dell'audio",
|
275 |
+
"matchering_passes": "Passaggi di Matchering",
|
276 |
+
"matchering_passes_info": "Numero di iterazioni di Matchering (1-5, valori più alti migliorano la qualità ma richiedono più tempo)",
|
277 |
+
"matchering_processing": "Applicazione di Matchering in corso... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ Elaborazione Matchering completata!",
|
279 |
+
"matchering_error": "❌ Errore durante Matchering: {}"
|
280 |
+
}
|
assets/i18n/languages/ja_jp.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "言語を選択",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "あなたの究極のオーディオ分離",
|
5 |
+
"presented_by": "Gecekondu Production © 2025 提供",
|
6 |
+
"audio_separation_tab": "🎙️ オーディオ分離",
|
7 |
+
"input_model": "📥 入力とモデル",
|
8 |
+
"upload": "🖥 アップロード",
|
9 |
+
"path": "📂 パス",
|
10 |
+
"path_placeholder": "/パス/オーディオ.wav",
|
11 |
+
"category": "カテゴリ",
|
12 |
+
"model": "モデル",
|
13 |
+
"settings": "⚙ 設定",
|
14 |
+
"format": "フォーマット",
|
15 |
+
"chunk_size": "チャンクサイズ",
|
16 |
+
"chunk_size_info": "特別な要件がない限り変更しないでください",
|
17 |
+
"overlap": "オーバーラップ",
|
18 |
+
"overlap_info": "推奨: 2-10 (高い値は品質を向上させますが、より多くのVRAMが必要です)",
|
19 |
+
"tta_boost": "TTAブースト",
|
20 |
+
"tta_info": "品質を向上させますが、処理速度が遅くなります",
|
21 |
+
"phase_fix": "位相補正",
|
22 |
+
"phase_fix_info": "インストゥルメンタルトラックのための高度な位相補正",
|
23 |
+
"instrumental": "インストゥルメンタル",
|
24 |
+
"instrumental_info": "通常2つの出力が得られますが、時には1つの出力だけの場合もあります。試してみてください :)",
|
25 |
+
"process": "🚀 処理",
|
26 |
+
"reset": "🧹 リセット",
|
27 |
+
"status": "ステータス",
|
28 |
+
"main_tab": "🎧 メイン",
|
29 |
+
"original": "オリジナル",
|
30 |
+
"vocals": "ボーカル",
|
31 |
+
"instrumental_output": "インストゥルメンタル",
|
32 |
+
"other": "その他",
|
33 |
+
"details_tab": "🔍 詳細",
|
34 |
+
"male": "男性",
|
35 |
+
"female": "女性",
|
36 |
+
"speech": "スピーチ",
|
37 |
+
"drums": "ドラム",
|
38 |
+
"bass": "ベース",
|
39 |
+
"effects": "エフェクト",
|
40 |
+
"advanced_tab": "⚙ 高度",
|
41 |
+
"phase_remix": "位相リミックス",
|
42 |
+
"dry": "ドライ",
|
43 |
+
"music": "音楽",
|
44 |
+
"karaoke": "カラオケ",
|
45 |
+
"bleed": "ブリード",
|
46 |
+
"copy_to_drive": "📂 ドライブにコピー",
|
47 |
+
"copy_status": "コピーステータス",
|
48 |
+
"files_will_be_copied": "ファイルはここにコピーされます...",
|
49 |
+
"processing_tip": "<b>🔈 処理のヒント:</b> ノイズの多い結果の場合、<i>\"ノイズとエフェクトの除去\"</i> カテゴリ内の <code>bleed_suppressor_v1</code> または <code>denoisedebleed</code> モデルを使用して出力をクリーンアップしてください",
|
50 |
+
"waiting_for_processing": "処理待ち...",
|
51 |
+
"auto_ensemble_tab": "🤖 自動アンサンブル",
|
52 |
+
"upload_file": "ファイルをアップロード",
|
53 |
+
"enter_file_path": "またはファイルパスを入力",
|
54 |
+
"file_path_placeholder": "オーディオファイルのフルパスを入力",
|
55 |
+
"advanced_settings": "⚙️ 高度な設定",
|
56 |
+
"use_tta": "TTAを使用",
|
57 |
+
"instrumental_only": "インストゥルメンタルのみ",
|
58 |
+
"auto_overlap": "オーバーラップ",
|
59 |
+
"auto_chunk_size": "チャンクサイズ",
|
60 |
+
"output_format": "出力フォーマット",
|
61 |
+
"model_selection": "🧠 モデル選択",
|
62 |
+
"model_category": "モデルカテゴリ",
|
63 |
+
"select_models": "カテゴリからモデルを選択",
|
64 |
+
"ensemble_settings": "⚡ アンサンブル設定",
|
65 |
+
"method": "メソッド",
|
66 |
+
"recommendation": "**推奨:** avg_wave と max_fft が最高の結果をもたらします",
|
67 |
+
"start_processing": "🚀 処理開始",
|
68 |
+
"original_audio_tab": "🔊 オリジナルオーディオ",
|
69 |
+
"original_audio": "オリジナルオーディオ",
|
70 |
+
"ensemble_result_tab": "🎚️ アンサンブル結果",
|
71 |
+
"output_preview": "出力プレビュー",
|
72 |
+
"refresh_output": "🔄 出力を更新",
|
73 |
+
"ensemble_copy_status": "アンサンブル出力はここにコピーされます...",
|
74 |
+
"guidelines": "<h4>モデル選択ガイドライン</h4><ul><li><strong>カテゴリの混在を避ける:</strong> ボーカルとインストゥルメンタルモデルを組み合わせると望ましくないミックスが生じる可能性があります</li><li><strong>特別なモデルに関する注意:</strong><ul><li>デュアリティモデル (v1/v2) - 両方のステムを出力</li><li>MDX23Cセパレーター - ハイブリッド結果</li></ul></li><li><strong>ベストプラクティス:</strong> 同じカテゴリから3〜5つの類似モデルを使用</li></ul><div>💡 プロのヒント: \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\" の組み合わせから始めてください</div>",
|
75 |
+
"download_sources_tab": "⬇️ ソースをダウンロード",
|
76 |
+
"direct_links": "🌐 ダイレクトリンク",
|
77 |
+
"audio_file_url": "オーディオファイルURL",
|
78 |
+
"download_from_url": "⬇️ URLからダウンロード",
|
79 |
+
"download_status": "ダウンロードステータス",
|
80 |
+
"downloaded_file": "ダウンロードされたファイル",
|
81 |
+
"cookie_management": "🍪 クッキー管理",
|
82 |
+
"upload_cookies_txt": "Cookies.txtをアップロード",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 なぜ必要か?**<br>- 年齢制���付きコンテンツへのアクセス<br>- プライベート/非公開ビデオのダウンロード<br>- 地域制限の回避<br>- YouTubeのダウンロード制限の回避<br><br>**⚠️ 重要な注意**<br>- クッキーファイルを決して共有しないでください!<br>- クッキーを更新するタイミング:<br> • \"403 Forbidden\" エラーが出た場合<br> • ダウンロードが突然停止した場合<br> • \"セッションが期限切れ\" メッセージが表示された場合<br><br>**🔄 更新手順**<br>1. この <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">Chrome拡張機能</a> をインストール<br>2. ChromeでYouTubeにログイン<br>3. 拡張機能アイコンをクリック → \"エクスポート\"<br>4. ダウンロードしたファイルをここにアップロード<br><br>**⏳ クッキーの寿命**<br>- 通常セッション: 24時間<br>- 機密操作: 1時間<br>- パスワード変更: 即時無効化</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ 手動アンサンブル",
|
85 |
+
"input_sources": "📂 入力ソース",
|
86 |
+
"refresh": "🔄 更新",
|
87 |
+
"ensemble_algorithm": "アンサンブルアルゴリズム",
|
88 |
+
"select_audio_files": "オーディオファイルを選択",
|
89 |
+
"available_files": "利用可能なファイル",
|
90 |
+
"custom_weights": "カスタムウェイト (カンマで区切り)",
|
91 |
+
"custom_weights_placeholder": "例: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "均等なウェイトの場合は空白のまま",
|
93 |
+
"result_preview_tab": "🎧 結果プレビュー",
|
94 |
+
"ensembled_output": "アンサンブル出力",
|
95 |
+
"processing_log_tab": "📋 処理ログ",
|
96 |
+
"processing_details": "処理詳細",
|
97 |
+
"process_ensemble": "⚡ アンサンブルを処理",
|
98 |
+
"languages_tab": "🌐 言語",
|
99 |
+
"Vocal Models": "ボーカルモデル",
|
100 |
+
"Instrumental Models": "インストゥルメンタルモデル",
|
101 |
+
"4-Stem Models": "4ステムモデル",
|
102 |
+
"Denoise Models": "ノイズ除去モデル",
|
103 |
+
"Dereverb Models": "リバーブ除去モデル",
|
104 |
+
"Other Models": "その他のモデル",
|
105 |
+
"ensemble_files_description": "指定されたアンサンブル手法を使用して複数のオーディオファイルを1つの出力に統合します。",
|
106 |
+
"ensemble_files_help": "アンサンブル用のすべてのオーディオファイルへのパス",
|
107 |
+
"ensemble_type_help": "avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft のいずれか",
|
108 |
+
"ensemble_weights_help": "アンサンブルを作成するためのウェイト。ウェイト数はファイル数と一致する必要があります",
|
109 |
+
"ensemble_output_help": "アンサンブル結果を保存するWAVファイルへのパス",
|
110 |
+
"ensemble_type_print": "アンサンブルタイプ: {}",
|
111 |
+
"num_input_files_print": "入力ファイル数: {}",
|
112 |
+
"weights_print": "ウェイト: {}",
|
113 |
+
"output_file_print": "出力ファイル: {}",
|
114 |
+
"duration_mismatch_error": "すべてのファイルは同じ長さでなければなりません",
|
115 |
+
"file_not_found_error": "エラー。ファイルが見つかりません: {}。パスを確認してください。",
|
116 |
+
"reading_chunk_print": "ファイルからチャンクを読み込み: {} (開始: {}秒, 長さ: {}秒)",
|
117 |
+
"chunk_result_shape_print": "チャンク結果の形状: {}",
|
118 |
+
"ensemble_completed_print": "アンサンブル完了。出力は以下に保存: {}",
|
119 |
+
"file_deletion_error": "{} を削除できませんでした: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ ディレクトリが存在しません: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ パスはディレクトリではありません: {}",
|
122 |
+
"item_deletion_error": "⚠️ {} の削除エラー: {}",
|
123 |
+
"old_output_not_exist": "❌ 古い出力フォルダが存在しません",
|
124 |
+
"old_outputs_cleared": "✅ 古い出力が正常に削除されました!",
|
125 |
+
"error": "🔥 エラー: {}",
|
126 |
+
"ffmpeg_error": "FFmpegエラー ({}): {}",
|
127 |
+
"file_saved_successfully": "ファイルが正常に保存されました: {}",
|
128 |
+
"total_files_found": "見つかったファイルの総数: {}。使用サンプルレート: {}",
|
129 |
+
"total_progress": "総進捗",
|
130 |
+
"detailed_pbar_enabled": "詳細プログレスバー有効: {}",
|
131 |
+
"loaded_audio": "ロードされたオーディオ: {}, 形状: {}",
|
132 |
+
"cannot_read_track": "トラックを読み込めません: {}",
|
133 |
+
"error_message": "エラーメッセージ: {}",
|
134 |
+
"demudding_track": "トラックのデマッディング (位相リミックス - インストゥルメンタル): {}",
|
135 |
+
"elapsed_time": "経過時間: {:.2f} 秒。",
|
136 |
+
"proc_folder_description": "指定されたモデルを使用してフォルダ内のオーディオファイルを処理します。",
|
137 |
+
"model_type_help": "モデルタイプ (bandit, bs_roformer, mdx23c など)",
|
138 |
+
"config_path_help": "設定ファイルへのパス",
|
139 |
+
"demud_phaseremix_help": "インストゥルメンタルの位相リミックスを有効���",
|
140 |
+
"start_checkpoint_help": "有効なウェイトの初期チェックポイント",
|
141 |
+
"input_folder_help": "処理するミックスを含むフォルダ",
|
142 |
+
"audio_path_help": "処理する単一のオーディオファイルへのパス",
|
143 |
+
"store_dir_help": "結果を保存するパス",
|
144 |
+
"device_ids_help": "GPU IDのリスト",
|
145 |
+
"extract_instrumental_help": "提供されている場合、ボーカルを反転してインストゥルメンタルを取得",
|
146 |
+
"disable_detailed_pbar_help": "デミックスで詳細プログレスバーを無効化",
|
147 |
+
"force_cpu_help": "CUDAが利用可能でもCPUを強制使用",
|
148 |
+
"flac_file_help": "WAVの代わりにFLACファイルを出力",
|
149 |
+
"export_format_help": "エクスポートフォーマットとPCMタイプ",
|
150 |
+
"pcm_type_help": "FLACファイルのPCMタイプ",
|
151 |
+
"use_tta_help": "テスト時間増強を有効化",
|
152 |
+
"lora_checkpoint_help": "LoRAウェイトの初期チェックポイント",
|
153 |
+
"cuda_available": "CUDAが利用可能です。無効化するには --force_cpu を使用してください。",
|
154 |
+
"using_device": "使用デバイス: {}",
|
155 |
+
"instruments_print": "楽器: {}",
|
156 |
+
"model_load_time": "モデルロード時間: {:.2f} 秒",
|
157 |
+
"invalid_url": "❌ 無効なURL",
|
158 |
+
"cookie_file_updated": "✅ クッキーファイルが更新されました!",
|
159 |
+
"cookie_installation_error": "⚠️ クッキーインストールエラー: {}",
|
160 |
+
"file_size_zero_error": "ファイルサイズがゼロまたはファイルが作成されていません",
|
161 |
+
"google_drive_error": "❌ Google Driveダウンロードエラー: {}",
|
162 |
+
"wav_conversion_failed": "WAV変換に失敗",
|
163 |
+
"download_error": "❌ ダウンロードエラー: {}",
|
164 |
+
"download_success": "🎉 ダウンロード成功!",
|
165 |
+
"download_failed": "❌ ダウンロード失敗",
|
166 |
+
"no_output_files_found": "❌ 出力ファイルが見つかりません。",
|
167 |
+
"output_refreshed_successfully": "✅ 出力が正常に更新されました!",
|
168 |
+
"error_refreshing_output": "❌ 出力更新エラー: {}",
|
169 |
+
"starting_audio_separation": "オーディオ分離を開始...",
|
170 |
+
"processing_audio": "オーディオ処理中",
|
171 |
+
"separating_audio": "オーディオ分離中... ({:.1f}%)",
|
172 |
+
"separation_complete": "分離完了!",
|
173 |
+
"progress_parsing_error": "進捗解析エラー: {}",
|
174 |
+
"error_occurred": "エラーが発生しました: {}",
|
175 |
+
"separation_process_completed": "分離プロセス完了!",
|
176 |
+
"no_audio_file_error": "❌ オーディオファイルが提供されておらず、入力ディレクトリに既存のファイルもありません。",
|
177 |
+
"no_input_progress_label": "エラー: 入力が提供されていません -- 0.0%",
|
178 |
+
"processing_audio_print": "{} からオーディオを処理中、モデル使用: {}",
|
179 |
+
"starting_audio_separation_progress_label": "オーディオ分離を開始... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "オーディオ分離中... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "オーディオ処理完了! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ オーディオ処理完了!",
|
183 |
+
"error_occurred_progress_label": "エラーが発生しました -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ 最低2ファイル必要",
|
185 |
+
"valid_files_not_found": "❌ 有効なファイルが見つかりません",
|
186 |
+
"starting_ensemble_process": "アンサンブルプロセスを開始...",
|
187 |
+
"ensembling_progress": "アンサンブル中... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "アンサンブル出力を最終処理中...",
|
189 |
+
"success_log": "✅ 成功!\n{}",
|
190 |
+
"error_log": "❌ エラー!\n{}",
|
191 |
+
"critical_error": "⛔ 重大なエラー: {}",
|
192 |
+
"ensemble_process_completed": "アンサンブルプロセス完了!",
|
193 |
+
"no_models_selected": "❌ モデルが選択されていません",
|
194 |
+
"no_input_audio_provided": "❌ 入力オーディオが提供されていません",
|
195 |
+
"loading_model": "モデル {}/{} をロード中: {}...",
|
196 |
+
"loading_model_progress_label": "モデル {}/{} をロード中: {}... -- {}.0%",
|
197 |
+
"completed_model": "モデル {}/{} 完了: {}",
|
198 |
+
"completed_model_progress_label": "モデル {}/{} 完了: {} -- {}.0%",
|
199 |
+
"running_command": "コマンド実行中: {}",
|
200 |
+
"model_failed": "モデル {} が失敗: {}",
|
201 |
+
"critical_error_with_model": "{} で重大なエラー: {}",
|
202 |
+
"model_output_failed": "{} が出力を生成できませんでした",
|
203 |
+
"waiting_for_files": "すべてのファイルの準備を待機中...",
|
204 |
+
"waiting_for_files_progress_label": "すべてのファイルの準備を待機中... -- 90.0%",
|
205 |
+
"performing_ensemble": "アンサンブル実行中...",
|
206 |
+
"performing_ensemble_progress_label": "アンサンブル実行中... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "アンサンブル前のメモリ使用量: {}%",
|
208 |
+
"memory_usage_after_ensemble": "アンサンブル後のメモリ使用量: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "アンサンブル出力を最終処理中... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "アンサンブルファイルの作成に失敗: {}",
|
211 |
+
"ensemble_completed_progress_label": "アンサンブルが正常に完了しました! -- 100.0%",
|
212 |
+
"success_output_created": "✅ 成功! 出力ファイルが作成されました。",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Driveがマウントされました。アンサンブル出力をコピー中...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Driveはすでにマウントされています。アンサンブル出力をコピー中...",
|
215 |
+
"no_ensemble_output_files_found": "❌ アンサンブル出力ファイルが見つかりません。",
|
216 |
+
"ensemble_output_copied": "✅ アンサンブル出力が {} にコピーされました",
|
217 |
+
"error_copying_ensemble_output": "❌ アンサンブル出力のコピーにエラー: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Driveがマウントされました。ファイルをコピー中...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Driveはすでにマウントされています。ファイルをコピー中...",
|
220 |
+
"files_copied_to_drive": "✅ ファイルが {} にコピーされました",
|
221 |
+
"error_copying_files": "❌ ファイルのコピーにエラー: {}",
|
222 |
+
"mounting_drive": "Google Driveをマウント中...",
|
223 |
+
"settings_saved": "設定が config.json に保存されました: 言語={lang}, メソッド={method}, ポート={port}",
|
224 |
+
"selected_language": "選択された言語: {lang}",
|
225 |
+
"available_languages": "利用可能な言語: {langs}",
|
226 |
+
"select_language_prompt": "言語を選択 (デフォルト: {default}): ",
|
227 |
+
"invalid_language": "無効な言語選択! デフォルト言語 ({default}) を使用します。",
|
228 |
+
"available_sharing_methods": "利用可能な共有方法: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "共有方法を選択 (デフォルト: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "Ngrokトークンを入力 (デフォルト: {default}): ",
|
231 |
+
"ngrok_token_required": "エラー: ngrokメソッドにはNgrokトークンが必要です!",
|
232 |
+
"enter_port_prompt": "ポート番号を入力 (デフォルト: {default}): ",
|
233 |
+
"opening_previous_url": "前のURLを開く: {url}",
|
234 |
+
"open_url_manually": "ColabでURLを手動で開く: {url}",
|
235 |
+
"invalid_previous_url": "無効な前のURL: {url}, 開かれませんでした。",
|
236 |
+
"starting_method": "{method} をポート {port} で開始...",
|
237 |
+
"process_stopped": "\n🛑 ユーザーによってプロセスが停止されました",
|
238 |
+
"selected_port": "選択されたポート: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Gradioを共有機能付きで開始...",
|
240 |
+
"starting_localtunnel": "Localtunnelをポート {port} で開始...",
|
241 |
+
"share_link": "共有リンク: {url}",
|
242 |
+
"password_ip": "パスワードIP: {ip}",
|
243 |
+
"starting_ngrok": "Ngrokをポート {port} で開始...",
|
244 |
+
"ngrok_url": "Ngrok URL: {url}",
|
245 |
+
"ngrok_error": "Ngrok開始エラー: {error}",
|
246 |
+
"apollo_chunk_size": "Apolloチャンクサイズ",
|
247 |
+
"apollo_chunk_size_info": "Apollo改善のためのチャンクサイズ (ユニバーサルモデル推奨: 19)",
|
248 |
+
"apollo_overlap": "Apolloオーバーラップ",
|
249 |
+
"enhancing_with_apollo": "Apolloで改善中 ({}/{} ファイル)...",
|
250 |
+
"apollo_processing_completed": "Apollo処理完了!",
|
251 |
+
"apollo_overlap_info": "Apollo改善のためのオーバーラップ (推奨: 2)",
|
252 |
+
"invalid_method": "エラー: 無効なメソッド! 'gradio', 'localtunnel', または 'ngrok' を使用してください。",
|
253 |
+
"apollo_enhancement_settings": "Apollo改善設定",
|
254 |
+
"enhance_with_apollo": "Apolloで改善",
|
255 |
+
"enhance_with_apollo_info": "分離後のオーディオ改善のためにApolloを有効化",
|
256 |
+
"apollo_method": "Apolloメソッド",
|
257 |
+
"apollo_method_info": "Apolloの処理メソッドを選択",
|
258 |
+
"normal_method": "通常メソッド",
|
259 |
+
"mid_side_method": "ミッド/サイドメソッド",
|
260 |
+
"apollo_normal_model": "Apollo通常モデル",
|
261 |
+
"apollo_normal_model_info": "通常Apollo処理に使用するモデル",
|
262 |
+
"apollo_midside_model": "Apolloミッド/サイドモデル",
|
263 |
+
"apollo_enhancement_info": "音質の改善",
|
264 |
+
"selected_models": "選択されたモデル",
|
265 |
+
"save_preset": "プリセットを保存",
|
266 |
+
"delete_preset": "プリセットを削除",
|
267 |
+
"refresh_presets": "プリセットを更新",
|
268 |
+
"preset_name": "プリセット名",
|
269 |
+
"select_preset": "プリセットを選択",
|
270 |
+
"add_favorite": "お気に入りに追加",
|
271 |
+
"apollo_midside_model_info": "ミッド/サイド処理に使用するモデル (オプション)",
|
272 |
+
"language_changed_message": "言語が変更されました。セルを再起動してください。",
|
273 |
+
"apply_matchering": "Matcheringを適用",
|
274 |
+
"matchering_info": "オーディオのマスタリングとバランスを向上させるためにMatcheringを適用",
|
275 |
+
"matchering_passes": "Matcheringの反復回数",
|
276 |
+
"matchering_passes_info": "Matcheringの反復回数(1-5、高い値は品質を向上させますが時間がかかります)",
|
277 |
+
"matchering_processing": "Matcheringを適用中... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ Matchering処理が完了しました!",
|
279 |
+
"matchering_error": "❌ Matchering中にエラーが発生しました:{}"
|
280 |
+
}
|
assets/i18n/languages/ru_ru.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Выберите язык",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "Ваше идеальное разделение аудио",
|
5 |
+
"presented_by": "Представлено Gecekondu Production © 2025",
|
6 |
+
"audio_separation_tab": "🎙️ Разделение аудио",
|
7 |
+
"input_model": "📥 Ввод и модель",
|
8 |
+
"upload": "🖥 Загрузить",
|
9 |
+
"path": "📂 Путь",
|
10 |
+
"path_placeholder": "/путь/к/аудио.wav",
|
11 |
+
"category": "Категория",
|
12 |
+
"model": "Модель",
|
13 |
+
"settings": "⚙ Настройки",
|
14 |
+
"format": "Формат",
|
15 |
+
"chunk_size": "Размер фрагмента",
|
16 |
+
"chunk_size_info": "Не изменяйте, если у вас нет особых требований",
|
17 |
+
"overlap": "Перекрытие",
|
18 |
+
"overlap_info": "Рекомендуется: 2-10 (более высокие значения улучшают качество, но требуют больше VRAM)",
|
19 |
+
"tta_boost": "Усиление TTA",
|
20 |
+
"tta_info": "Улучшает качество, но замедляет скорость обработки",
|
21 |
+
"phase_fix": "Коррекция фазы",
|
22 |
+
"phase_fix_info": "Расширенная коррекция фазы для инструментальных треков",
|
23 |
+
"instrumental": "Инструментал",
|
24 |
+
"instrumental_info": "Обычно дает 2 выхода, но иногда только один, нужно экспериментировать :)",
|
25 |
+
"process": "🚀 Обработать",
|
26 |
+
"reset": "🧹 Сбросить",
|
27 |
+
"status": "Статус",
|
28 |
+
"main_tab": "🎧 Главная",
|
29 |
+
"original": "Оригинал",
|
30 |
+
"vocals": "Вокал",
|
31 |
+
"instrumental_output": "Инструментал",
|
32 |
+
"other": "Прочее",
|
33 |
+
"details_tab": "🔍 Подробности",
|
34 |
+
"male": "Мужской",
|
35 |
+
"female": "Женский",
|
36 |
+
"speech": "Речь",
|
37 |
+
"drums": "Барабаны",
|
38 |
+
"bass": "Бас",
|
39 |
+
"effects": "Эффекты",
|
40 |
+
"advanced_tab": "⚙ Расширенные",
|
41 |
+
"phase_remix": "Ремикс фазы",
|
42 |
+
"dry": "Сухой",
|
43 |
+
"music": "Музыка",
|
44 |
+
"karaoke": "Караоке",
|
45 |
+
"bleed": "Просачивание",
|
46 |
+
"copy_to_drive": "📂 Копировать на Диск",
|
47 |
+
"copy_status": "Статус копирования",
|
48 |
+
"files_will_be_copied": "Файлы будут скопированы сюда...",
|
49 |
+
"processing_tip": "<b>🔈 Совет по обработке:</b> Для шумных результатов используйте модели <code>bleed_suppressor_v1</code> или <code>denoisedebleed</code> в категории <i>\"Удаление шума и эффектов\"</i>, чтобы очистить выходные данные",
|
50 |
+
"waiting_for_processing": "Ожидание обработки...",
|
51 |
+
"auto_ensemble_tab": "🤖 Автоматический ансамбль",
|
52 |
+
"upload_file": "Загрузить файл",
|
53 |
+
"enter_file_path": "Или введите путь к файлу",
|
54 |
+
"file_path_placeholder": "Введите полный путь к аудиофайлу",
|
55 |
+
"advanced_settings": "⚙️ Расширенные настройки",
|
56 |
+
"use_tta": "Использовать TTA",
|
57 |
+
"instrumental_only": "Только инструментал",
|
58 |
+
"auto_overlap": "Перекрытие",
|
59 |
+
"auto_chunk_size": "Размер фрагмента",
|
60 |
+
"output_format": "Формат вывода",
|
61 |
+
"model_selection": "🧠 Выбор модели",
|
62 |
+
"model_category": "Категория модели",
|
63 |
+
"select_models": "Выберите модели из категории",
|
64 |
+
"ensemble_settings": "⚡ Настройки ансамбля",
|
65 |
+
"method": "Метод",
|
66 |
+
"recommendation": "**Рекомендация:** avg_wave и max_fft дают лучшие результаты",
|
67 |
+
"start_processing": "🚀 Начать обработку",
|
68 |
+
"original_audio_tab": "🔊 Оригинальное аудио",
|
69 |
+
"original_audio": "Оригинальное аудио",
|
70 |
+
"ensemble_result_tab": "🎚️ Результат ансамбля",
|
71 |
+
"output_preview": "Предпросмотр вывода",
|
72 |
+
"refresh_output": "🔄 Обновить вывод",
|
73 |
+
"ensemble_copy_status": "Вывод ансамбля будет скопирован сюда...",
|
74 |
+
"guidelines": "<h4>Руководство по выбору моделей</h4><ul><li><strong>Избегайте смешивания категорий:</strong> Сочетание вокальных и инструментальных моделей может привести к нежелательным смешиваниям</li><li><strong>Заметки о специальных моделях:</strong><ul><li>Модели дуальности (v1/v2) - выдают оба стема</li><li>Сепаратор MDX23C - гибридные результаты</li></ul></li><li><strong>Лучшая практика:</strong> Используйте 3-5 схожих моделей из одной категории</li></ul><div>💡 Профессиональный совет: Начните с комбинации \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\"</div>",
|
75 |
+
"download_sources_tab": "⬇️ Скачать источники",
|
76 |
+
"direct_links": "🌐 Прямые ссылки",
|
77 |
+
"audio_file_url": "URL аудиофайла",
|
78 |
+
"download_from_url": "⬇️ Скачать по URL",
|
79 |
+
"download_status": "Статус загрузки",
|
80 |
+
"downloaded_file": "Скачанный файл",
|
81 |
+
"cookie_management": "🍪 Управление cookies",
|
82 |
+
"upload_cookies_txt": "Загрузить Cookies.txt",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 Зачем это нужно?**<br>- Доступ к контенту с возрастными ограничениями<br>- Скачивание приватных/неопубликованных видео<br>- Обход региональных ограничений<br>- Избежание лимитов скачивания YouTube<br><br>**⚠️ Важные заметки**<br>- НИКОГДА не делитесь своими файлами cookies!<br>- Обновляйте cookies, если:<br> • Появляются ошибки \"403 Запрещено\"<br> • Загрузки внезапно останавливаются<br> • Появляется сообщение \"Сессия истекла\"<br><br>**🔄 Шаги обновления**<br>1. Установите это <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">расширение Chrome</a><br>2. Войдите в YouTube в Chrome<br>3. Нажмите на иконку расширения → \"Экспорт\"<br>4. Загрузите скачанный файл сюда<br><br>**⏳ Срок действия cookies**<br>- Обычные сессии: 24 часа<br>- Чувствительные операции: 1 час<br>- Смена пароля: мгновенная недействительность</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ Ручной ансамбль",
|
85 |
+
"input_sources": "📂 Источники ввода",
|
86 |
+
"refresh": "🔄 Обновить",
|
87 |
+
"ensemble_algorithm": "Алгоритм ансамбля",
|
88 |
+
"select_audio_files": "Выберите аудиофайлы",
|
89 |
+
"available_files": "Доступные файлы",
|
90 |
+
"custom_weights": "Пользовательские веса (разделены запятыми)",
|
91 |
+
"custom_weights_placeholder": "Пример: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "Оставьте пустым для равных весов",
|
93 |
+
"result_preview_tab": "🎧 Предпросмотр результата",
|
94 |
+
"ensembled_output": "Результат ансамбля",
|
95 |
+
"processing_log_tab": "📋 Журнал обработки",
|
96 |
+
"processing_details": "Детали обработки",
|
97 |
+
"process_ensemble": "⚡ Обработать ансамбль",
|
98 |
+
"languages_tab": "🌐 Языки",
|
99 |
+
"Vocal Models": "Вокальные модели",
|
100 |
+
"Instrumental Models": "Инструментальные модели",
|
101 |
+
"4-Stem Models": "Модели с 4 стемами",
|
102 |
+
"Denoise Models": "Модели шумоподавления",
|
103 |
+
"Dereverb Models": "Модели удаления реверберации",
|
104 |
+
"Other Models": "Другие модели",
|
105 |
+
"ensemble_files_description": "Объединяет несколько аудиофайлов в один выход с использованием указанных методов ансамбля.",
|
106 |
+
"ensemble_files_help": "Путь ко всем аудиофайлам для ансамбля",
|
107 |
+
"ensemble_type_help": "Один из: avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "Веса для создания ансамбля. Количество весов должно совпадать с количеством файлов",
|
109 |
+
"ensemble_output_help": "Путь к WAV-файлу, куда будет сохранен результат ансамбля",
|
110 |
+
"ensemble_type_print": "Тип ансамбля: {}",
|
111 |
+
"num_input_files_print": "Количество входных файлов: {}",
|
112 |
+
"weights_print": "Веса: {}",
|
113 |
+
"output_file_print": "Выходной файл: {}",
|
114 |
+
"duration_mismatch_error": "Все файлы должны иметь одинаковую длительность",
|
115 |
+
"file_not_found_error": "Ошибка. Файл не найден: {}. Проверьте пути.",
|
116 |
+
"reading_chunk_print": "Чтение фрагмента из файла: {} (начало: {} сек, длительность: {} сек)",
|
117 |
+
"chunk_result_shape_print": "Форма результата фрагмента: {}",
|
118 |
+
"ensemble_completed_print": "Ансамбль завершен. Выход сохранен в: {}",
|
119 |
+
"file_deletion_error": "Не удалось удалить {}: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ Директория не существует: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ Путь не является директорией: {}",
|
122 |
+
"item_deletion_error": "⚠️ Ошибка удаления {}: {}",
|
123 |
+
"old_output_not_exist": "❌ Старая папка вывода не существует",
|
124 |
+
"old_outputs_cleared": "✅ Старые выходные данные успешно удалены!",
|
125 |
+
"error": "🔥 Ошибка: {}",
|
126 |
+
"ffmpeg_error": "Ошибка FFmpeg ({}): {}",
|
127 |
+
"file_saved_successfully": "Файл успешно сохранен: {}",
|
128 |
+
"total_files_found": "Всего найдено файлов: {}. Используемая частота дискретизации: {}",
|
129 |
+
"total_progress": "Общий прогресс",
|
130 |
+
"detailed_pbar_enabled": "Подробная шкала прогресса включена: {}",
|
131 |
+
"loaded_audio": "Загруженное аудио: {}, форма: {}",
|
132 |
+
"cannot_read_track": "Не удается прочитать трек: {}",
|
133 |
+
"error_message": "Сообщение об ошибке: {}",
|
134 |
+
"demudding_track": "Очистка трека (ремикс фазы - инструментал): {}",
|
135 |
+
"elapsed_time": "Прошедшее время: {:.2f} сек.",
|
136 |
+
"proc_folder_description": "Обрабатывает аудиофайлы в папке с использованием указанной модели.",
|
137 |
+
"model_type_help": "Тип модели (bandit, bs_roformer, mdx23c и т.д.)",
|
138 |
+
"config_path_help": "Путь к файлу конфигурации",
|
139 |
+
"demud_phaseremix_help": "Включить ремикс фазы для инструментала",
|
140 |
+
"start_checkpoint_help": "Начальная контрольная точка для действительных весов",
|
141 |
+
"input_folder_help": "Папка с миксами для обработки",
|
142 |
+
"audio_path_help": "Путь к одному аудиофайлу для обработки",
|
143 |
+
"store_dir_help": "Путь для хранения результатов",
|
144 |
+
"device_ids_help": "Список идентификаторов GPU",
|
145 |
+
"extract_instrumental_help": "Инвертировать вокал для получения инструментала, если предоставлено",
|
146 |
+
"disable_detailed_pbar_help": "Отключить подробную шкалу прогресса при демиксе",
|
147 |
+
"force_cpu_help": "Принудительно использовать CPU, даже если CUDA доступен",
|
148 |
+
"flac_file_help": "Выводить файл FLAC вместо WAV",
|
149 |
+
"export_format_help": "Формат экспорта и тип PCM",
|
150 |
+
"pcm_type_help": "Тип PCM для файлов FLAC",
|
151 |
+
"use_tta_help": "Включить увеличение времени теста",
|
152 |
+
"lora_checkpoint_help": "Начальная контрольная точка для весов LoRA",
|
153 |
+
"cuda_available": "CUDA доступен, используйте --force_cpu для отключения.",
|
154 |
+
"using_device": "Используемое устройство: {}",
|
155 |
+
"instruments_print": "Инструменты: {}",
|
156 |
+
"model_load_time": "Время загрузки модели: {:.2f} сек",
|
157 |
+
"invalid_url": "❌ Неверный URL",
|
158 |
+
"cookie_file_updated": "✅ Файл cookies обновлен!",
|
159 |
+
"cookie_installation_error": "⚠️ Ошибка установки cookies: {}",
|
160 |
+
"file_size_zero_error": "Размер файла нулевой или файл не создан",
|
161 |
+
"google_drive_error": "❌ Ошибка загрузки с Google Drive: {}",
|
162 |
+
"wav_conversion_failed": "Не удалось конвертировать в WAV",
|
163 |
+
"download_error": "❌ Ошибка загрузки: {}",
|
164 |
+
"download_success": "🎉 Загрузка успешно завершена!",
|
165 |
+
"download_failed": "❌ Загрузка не удалась",
|
166 |
+
"no_output_files_found": "❌ Выходные файлы не найдены.",
|
167 |
+
"output_refreshed_successfully": "✅ Вывод успешно обновлен!",
|
168 |
+
"error_refreshing_output": "❌ Ошибка при обновлении вывода: {}",
|
169 |
+
"starting_audio_separation": "Запуск разделения аудио...",
|
170 |
+
"processing_audio": "Обработка аудио",
|
171 |
+
"separating_audio": "Разделение аудио... ({:.1f}%)",
|
172 |
+
"separation_complete": "Разделение завершено!",
|
173 |
+
"progress_parsing_error": "Ошибка разбора прогресса: {}",
|
174 |
+
"error_occurred": "Произошла ошибка: {}",
|
175 |
+
"separation_process_completed": "Процесс разделения завершен!",
|
176 |
+
"no_audio_file_error": "❌ Аудиофайл не предоставлен, и в директори�� ввода нет существующего файла.",
|
177 |
+
"no_input_progress_label": "Ошибка: Ввод не предоставлен -- 0.0%",
|
178 |
+
"processing_audio_print": "Обработка аудио из: {} с использованием модели: {}",
|
179 |
+
"starting_audio_separation_progress_label": "Запуск разделения аудио... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "Разделение аудио... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "Обработка аудио завершена! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ Обработка аудио завершена!",
|
183 |
+
"error_occurred_progress_label": "Произошла ошибка -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ Требуется минимум 2 файла",
|
185 |
+
"valid_files_not_found": "❌ Валидные файлы не найдены",
|
186 |
+
"starting_ensemble_process": "Запуск процесса ансамбля...",
|
187 |
+
"ensembling_progress": "Создание ансамбля... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "Завершение вывода ансамбля...",
|
189 |
+
"success_log": "✅ Успех!\n{}",
|
190 |
+
"error_log": "❌ Ошибка!\n{}",
|
191 |
+
"critical_error": "⛔ Критическая ошибка: {}",
|
192 |
+
"ensemble_process_completed": "Процесс ансамбля завершен!",
|
193 |
+
"no_models_selected": "❌ Модели не выбраны",
|
194 |
+
"no_input_audio_provided": "❌ Входное аудио не предоставлено",
|
195 |
+
"loading_model": "Загрузка модели {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "Загрузка модели {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "Модель завершена {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "Модель завершена {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "Выполнение команды: {}",
|
200 |
+
"model_failed": "Модель {} не удалась: {}",
|
201 |
+
"critical_error_with_model": "Критическая ошибка с {}: {}",
|
202 |
+
"model_output_failed": "{} не удалось создать вывод",
|
203 |
+
"waiting_for_files": "Ожидание готовности всех файлов...",
|
204 |
+
"waiting_for_files_progress_label": "Ожидание готовности всех файлов... -- 90.0%",
|
205 |
+
"performing_ensemble": "Выполнение ансамбля...",
|
206 |
+
"performing_ensemble_progress_label": "Выполнение ансамбля... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "Использование памяти перед ансамблем: {}%",
|
208 |
+
"memory_usage_after_ensemble": "Использование памяти после ансамбля: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "Завершение вывода ансамбля... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "Не удалось создать файл ансамбля: {}",
|
211 |
+
"ensemble_completed_progress_label": "Ансамбль успешно завершен! -- 100.0%",
|
212 |
+
"success_output_created": "✅ Успех! Выходной файл создан.",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive подключен. Копирование вывода ансамбля...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive уже подключен. Копирование вывода ансамбля...",
|
215 |
+
"no_ensemble_output_files_found": "❌ Файлы вывода ансамбля не найдены.",
|
216 |
+
"ensemble_output_copied": "✅ Вывод ансамбля скопирован в {}",
|
217 |
+
"error_copying_ensemble_output": "❌ Ошибка копирования вывода ансамбля: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive подключен. Копирование файлов...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive уже подключен. Копирование файлов...",
|
220 |
+
"files_copied_to_drive": "✅ Файлы скопированы в {}",
|
221 |
+
"error_copying_files": "❌ Ошибка копирования файлов: {}",
|
222 |
+
"mounting_drive": "Подключение Google Drive...",
|
223 |
+
"settings_saved": "Настройки сохранены в config.json: Язык={lang}, Метод={method}, Порт={port}",
|
224 |
+
"selected_language": "Выбранный язык: {lang}",
|
225 |
+
"available_languages": "Доступные языки: {langs}",
|
226 |
+
"select_language_prompt": "Выберите язык (по умолчанию: {default}): ",
|
227 |
+
"invalid_language": "Неверный выбор языка! Используется язык по умолчанию ({default}).",
|
228 |
+
"available_sharing_methods": "Доступные методы совместного доступа: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "Выберите метод совместного доступа (по умолчанию: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "Введите ваш токен Ngrok (по умолчанию: {default}): ",
|
231 |
+
"ngrok_token_required": "Ошибка: Для метода ngrok требуется токен Ngrok!",
|
232 |
+
"enter_port_prompt": "Введите номер порта (по умолчанию: {default}): ",
|
233 |
+
"opening_previous_url": "Открытие предыдущего URL: {url}",
|
234 |
+
"open_url_manually": "Откройте URL вручную в Colab: {url}",
|
235 |
+
"invalid_previous_url": "Неверный предыдущий URL: {url}, не открыт.",
|
236 |
+
"starting_method": "Запуск {method} на порту {port}...",
|
237 |
+
"process_stopped": "\n🛑 Процесс остановлен пользователем",
|
238 |
+
"selected_port": "Выбранный порт: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Запуск Gradio с встроенным совместным доступом...",
|
240 |
+
"starting_localtunnel": "Запуск Localtunnel на порту {port}...",
|
241 |
+
"share_link": "Ссылка для совместного доступа: {url}",
|
242 |
+
"password_ip": "Пароль IP: {ip}",
|
243 |
+
"starting_ngrok": "Запуск Ngrok на порту {port}...",
|
244 |
+
"ngrok_url": "URL Ngrok: {url}",
|
245 |
+
"ngrok_error": "Ошибка запуска Ngrok: {error}",
|
246 |
+
"apollo_chunk_size": "Размер фрагмента Apollo",
|
247 |
+
"apollo_chunk_size_info": "Размер фрагмента для улучшения Apollo (рекомендуется: 19 для универсальной модели)",
|
248 |
+
"apollo_overlap": "Перекрытие Apollo",
|
249 |
+
"enhancing_with_apollo": "Улучшение с Apollo ({}/{} файлов)...",
|
250 |
+
"apollo_processing_completed": "Обработка Apollo завершена!",
|
251 |
+
"apollo_overlap_info": "Перекрытие для улучшения Apollo (рекомендуется: 2)",
|
252 |
+
"invalid_method": "Ошибка: Неверный метод! Используйте 'gradio', 'localtunnel' или 'ngrok'.",
|
253 |
+
"apollo_enhancement_settings": "Настройки улучшения Apollo",
|
254 |
+
"enhance_with_apollo": "Улучшить с Apollo",
|
255 |
+
"enhance_with_apollo_info": "Включить Apollo для улучшения аудио после разделения",
|
256 |
+
"apollo_method": "Метод Apollo",
|
257 |
+
"apollo_method_info": "Выберите метод обработки для Apollo",
|
258 |
+
"normal_method": "Обычный метод",
|
259 |
+
"mid_side_method": "Метод середины/сторон",
|
260 |
+
"apollo_normal_model": "Обычная модель Apollo",
|
261 |
+
"apollo_normal_model_info": "Модель, используемая для обычной обработки Apollo",
|
262 |
+
"apollo_midside_model": "Модель Apollo середины/сторон",
|
263 |
+
"apollo_enhancement_info": "Улучшение качества звука",
|
264 |
+
"selected_models": "Выбранные модели",
|
265 |
+
"save_preset": "Сохранить пресет",
|
266 |
+
"delete_preset": "Удалить пресет",
|
267 |
+
"refresh_presets": "Обновить пресеты",
|
268 |
+
"preset_name": "Имя пресета",
|
269 |
+
"select_preset": "Выбрать пресет",
|
270 |
+
"add_favorite": "Добавить в избранное",
|
271 |
+
"apollo_midside_model_info": "Модель, используемая для обработки середины/сторон (опционально)",
|
272 |
+
"language_changed_message": "Язык изменен. Пожалуйста, перезапустите ячейку.",
|
273 |
+
"apply_matchering": "Применить Matchering",
|
274 |
+
"matchering_info": "Применить Matchering для улучшения мастеринга и баланса звука",
|
275 |
+
"matchering_passes": "Проходы Matchering",
|
276 |
+
"matchering_passes_info": "Количество итераций Matchering (1-5, более высокие значения улучшают качество, но занимают больше времени)",
|
277 |
+
"matchering_processing": "Применение Matchering... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ Обработка Matchering завершена!",
|
279 |
+
"matchering_error": "❌ Ошибка во время Matchering: {}"
|
280 |
+
}
|
assets/i18n/languages/tr_tr.json
ADDED
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "Dil Seç",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "Senin Nihai Ses Ayrıştırman",
|
5 |
+
"presented_by": "Gecekondu Production © 2025 Tarafından Sunulmuştur",
|
6 |
+
"audio_separation_tab": "🎙️ Ses Ayrıştırma",
|
7 |
+
"input_model": "📥 Giriş ve Model",
|
8 |
+
"upload": "🖥 Yükle",
|
9 |
+
"path": "📂 Yol",
|
10 |
+
"path_placeholder": "/yol/ses.wav",
|
11 |
+
"category": "Kategori",
|
12 |
+
"model": "Model",
|
13 |
+
"settings": "⚙ Ayarlar",
|
14 |
+
"format": "Biçim",
|
15 |
+
"chunk_size": "Parça Boyutu",
|
16 |
+
"chunk_size_info": "Özel gereksinimleriniz yoksa değiştirmeyin",
|
17 |
+
"overlap": "Çakışma",
|
18 |
+
"overlap_info": "Önerilen: 2-10 (yüksek değerler kaliteyi artırır ancak daha fazla VRAM gerektirir)",
|
19 |
+
"tta_boost": "TTA Güçlendirme",
|
20 |
+
"tta_info": "Kaliteyi artırır ancak işlem hızını yavaşlatır",
|
21 |
+
"phase_fix": "Faz Düzeltme",
|
22 |
+
"phase_fix_info": "Enstrümantal parçalar için gelişmiş faz düzeltme",
|
23 |
+
"instrumental": "Enstrümantal",
|
24 |
+
"instrumental_info": "Genellikle 2 çıktı verir, ama bazen tek çıktı olabilir, denemen lazım! :)",
|
25 |
+
"process": "🚀 İşle",
|
26 |
+
"reset": "🧹 Sıfırla",
|
27 |
+
"status": "Durum",
|
28 |
+
"main_tab": "🎧 Ana",
|
29 |
+
"original": "Orijinal",
|
30 |
+
"vocals": "Vokal",
|
31 |
+
"instrumental_output": "Enstrümantal",
|
32 |
+
"other": "Diğer",
|
33 |
+
"details_tab": "🔍 Ayrıntılar",
|
34 |
+
"male": "Erkek",
|
35 |
+
"female": "Kadın",
|
36 |
+
"speech": "Konuşma",
|
37 |
+
"drums": "Davul",
|
38 |
+
"bass": "Bas",
|
39 |
+
"effects": "Efektler",
|
40 |
+
"advanced_tab": "⚙ Gelişmiş",
|
41 |
+
"phase_remix": "Faz Remiks",
|
42 |
+
"dry": "Kuru",
|
43 |
+
"music": "Müzik",
|
44 |
+
"karaoke": "Karaoke",
|
45 |
+
"bleed": "Sızıntı",
|
46 |
+
"copy_to_drive": "📂 Drive'a Kopyala",
|
47 |
+
"copy_status": "Kopyalama Durumu",
|
48 |
+
"files_will_be_copied": "Dosyalar buraya kopyalanacak...",
|
49 |
+
"processing_tip": "<b>🔈 İşleme İpucu:</b> Gürültülü sonuçlar için <i>\"Gürültü ve Efekt Kaldırma\"</i> kategorisindeki <code>bleed_suppressor_v1</code> veya <code>denoisedebleed</code> modellerini kullanarak çıkışı temizleyin",
|
50 |
+
"waiting_for_processing": "İşleme Bekleniyor...",
|
51 |
+
"auto_ensemble_tab": "🤖 Otomatik birleştirme",
|
52 |
+
"upload_file": "Dosya Yükle",
|
53 |
+
"enter_file_path": "Veya Dosya Yolunu Gir",
|
54 |
+
"file_path_placeholder": "Ses dosyasının tam yolunu gir",
|
55 |
+
"advanced_settings": "⚙️ Gelişmiş Ayarlar",
|
56 |
+
"use_tta": "TTA Kullan",
|
57 |
+
"instrumental_only": "Sadece Enstrümantal",
|
58 |
+
"auto_overlap": "Çakışma",
|
59 |
+
"auto_chunk_size": "Parça Boyutu",
|
60 |
+
"output_format": "Çıktı Biçimi",
|
61 |
+
"model_selection": "🧠 Model Seçimi",
|
62 |
+
"model_category": "Model Kategorisi",
|
63 |
+
"select_models": "Kategoriden Model Seç",
|
64 |
+
"ensemble_settings": "⚡ birleştirme Ayarları",
|
65 |
+
"method": "Yöntem",
|
66 |
+
"recommendation": "**Öneri:** avg_wave ve max_fft en iyi sonuçları verir",
|
67 |
+
"start_processing": "🚀 İşlemi Başlat",
|
68 |
+
"original_audio_tab": "🔊 Orijinal Ses",
|
69 |
+
"original_audio": "Orijinal Ses",
|
70 |
+
"ensemble_result_tab": "🎚️ birleştirme Sonucu",
|
71 |
+
"output_preview": "Çıktı Önizlemesi",
|
72 |
+
"refresh_output": "🔄 Çıktıyı Yenile",
|
73 |
+
"ensemble_copy_status": "birleştirme çıktısı buraya kopyalanacak...",
|
74 |
+
"guidelines": "<h4>Model Seçim Kılavuzu</h4><ul><li><strong>Kategorileri Karıştırmaktan Kaçının:</strong> Vokal ve enstrümantal modellerin birleşimi istenmeyen karışımlara yol açabilir</li><li><strong>Özel Modeller Hakkında Notlar:</strong><ul><li>İkili modeller (v1/v2) - Her iki stemi de üretir</li><li>MDX23C Ayırıcı - Hibrit sonuçlar</li></ul></li><li><strong>En İyi Uygulama:</strong> Aynı kategoriden 3-5 benzer model kullanın</li></ul><div>💡 Profesyonel İpucu: \"VOCALS-MelBand-Roformer BigBeta5e\" + \"VOCALS-BS-Roformer_1297\" kombinasyonuyla başlayın</div>",
|
75 |
+
"download_sources_tab": "⬇️ Kaynakları İndir",
|
76 |
+
"direct_links": "🌐 Doğrudan Bağlantılar",
|
77 |
+
"audio_file_url": "Ses Dosyası URL'si",
|
78 |
+
"download_from_url": "⬇️ URL'den İndir",
|
79 |
+
"download_status": "İndirme Durumu",
|
80 |
+
"downloaded_file": "İndirilen Dosya",
|
81 |
+
"cookie_management": "🍪 Çerez Yönetimi",
|
82 |
+
"upload_cookies_txt": "Cookies.txt Yükle",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 Neden Gerekli?**<br>- Yaş sınırlı içeriklere erişim<br>- Özel/listelenmemiş videoları indirme<br>- Bölgesel kısıtlamaları aşma<br>- YouTube indirme limitlerini geçme<br><br>**⚠️ Önemli Notlar**<br>- Çerez dosyalarınızı ASLA paylaşmayın!<br>- Çerezleri şu durumlarda yenileyin:<br> • \"403 Yasak\" hataları alırsanız<br> • İndirmeler aniden durursa<br> • \"Oturum Süresi Doldu\" mesajı görürseniz<br><br>**🔄 Yenileme Adımları**<br>1. Bu <a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">Chrome uzantısını</a> yükleyin<br>2. Chrome'da YouTube'a giriş yapın<br>3. Uzantı simgesine tıklayın → \"Dışa Aktar\"<br>4. İndirilen dosyayı buraya yükleyin<br><br>**⏳ Çerez Ömrü**<br>- Normal oturumlar: 24 saat<br>- Hassas işlemler: 1 saat<br>- Şifre değişikliği: Anında geçersizlik</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ Manuel birleştirme",
|
85 |
+
"input_sources": "📂 Giriş Kaynakları",
|
86 |
+
"refresh": "🔄 Yenile",
|
87 |
+
"ensemble_algorithm": "birleştirme Algoritması",
|
88 |
+
"select_audio_files": "Ses Dosyalarını Seç",
|
89 |
+
"available_files": "Mevcut Dosyalar",
|
90 |
+
"custom_weights": "Özel Ağırlıklar (virgülle ayrılmış)",
|
91 |
+
"custom_weights_placeholder": "Örnek: 0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "Eşit ağırlıklar için boş bırakın",
|
93 |
+
"result_preview_tab": "🎧 Sonuç Önizlemesi",
|
94 |
+
"ensembled_output": "birleştirme Çıktısı",
|
95 |
+
"processing_log_tab": "📋 İşlem Günlüğü",
|
96 |
+
"processing_details": "İşlem Ayrıntıları",
|
97 |
+
"process_ensemble": "⚡ birleştirmeyi İşle",
|
98 |
+
"languages_tab": "🌐 Diller",
|
99 |
+
"Vocal Models": "Vokal Modeller",
|
100 |
+
"Instrumental Models": "Enstrümantal Modeller",
|
101 |
+
"4-Stem Models": "4-Stem Modeller",
|
102 |
+
"Denoise Models": "Gürültü Giderme Modelleri",
|
103 |
+
"Dereverb Models": "Yankı Giderme Modelleri",
|
104 |
+
"Other Models": "Diğer Modeller",
|
105 |
+
"ensemble_files_description": "Belirtilen birleştirme yöntemlerini kullanarak birden fazla ses dosyasını tek bir çıktıda birleştirir.",
|
106 |
+
"ensemble_files_help": "birleştirme için tüm ses dosyalarına giden yol",
|
107 |
+
"ensemble_type_help": "Şunlardan biri: avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "birleştirme oluşturmak için ağırlıklar. Ağırlık sayısı dosya sayısına eşit olmalı",
|
109 |
+
"ensemble_output_help": "birleştirme sonucunun kaydedileceği WAV dosyasının yolu",
|
110 |
+
"ensemble_type_print": "birleştirme türü: {}",
|
111 |
+
"num_input_files_print": "Giriş dosyası sayısı: {}",
|
112 |
+
"weights_print": "Ağırlıklar: {}",
|
113 |
+
"output_file_print": "Çıktı dosyası: {}",
|
114 |
+
"duration_mismatch_error": "Tüm dosyalar aynı süreye sahip olmalı",
|
115 |
+
"file_not_found_error": "Hata. Dosya bulunamadı: {}. Yolları kontrol et.",
|
116 |
+
"reading_chunk_print": "Dosyadan parça okunuyor: {} (başlangıç: {}s, süre: {}s)",
|
117 |
+
"chunk_result_shape_print": "Parça sonucu şekli: {}",
|
118 |
+
"ensemble_completed_print": "birleştirme tamamlandı. Çıktı şuraya kaydedildi: {}",
|
119 |
+
"file_deletion_error": "{} silinemedi: {}",
|
120 |
+
"directory_not_exist_warning": "⚠️ Dizin mevcut değil: {}",
|
121 |
+
"not_a_directory_warning": "⚠️ Yol bir dizin değil: {}",
|
122 |
+
"item_deletion_error": "⚠️ {} silinirken hata: {}",
|
123 |
+
"old_output_not_exist": "❌ Eski çıktı klasörü mevcut değil",
|
124 |
+
"old_outputs_cleared": "✅ Eski çıktılar başarıyla silindi!",
|
125 |
+
"error": "🔥 Hata: {}",
|
126 |
+
"ffmpeg_error": "FFmpeg hatası ({}): {}",
|
127 |
+
"file_saved_successfully": "Dosya başarıyla kaydedildi: {}",
|
128 |
+
"total_files_found": "Bulunan toplam dosya: {}. Kullanılan örnekleme oranı: {}",
|
129 |
+
"total_progress": "Toplam İlerleme",
|
130 |
+
"detailed_pbar_enabled": "Ayrıntılı ilerleme çubuğu etkin: {}",
|
131 |
+
"loaded_audio": "Yüklenen ses: {}, şekil: {}",
|
132 |
+
"cannot_read_track": "Parça okunamıyor: {}",
|
133 |
+
"error_message": "Hata mesajı: {}",
|
134 |
+
"demudding_track": "Parça temizleniyor (faz remiks - enstrümantal): {}",
|
135 |
+
"elapsed_time": "Geçen süre: {:.2f} saniye.",
|
136 |
+
"proc_folder_description": "Belirtilen bir model kullanarak bir klasördeki ses dosyalarını işler.",
|
137 |
+
"model_type_help": "Model türü (bandit, bs_roformer, mdx23c vb.)",
|
138 |
+
"config_path_help": "Yapılandırma dosyasının yolu",
|
139 |
+
"demud_phaseremix_help": "Enstrümantal için faz remiksini etkinleştir",
|
140 |
+
"start_checkpoint_help": "Geçerli ağırlıklar için başlangıç kontrol noktası",
|
141 |
+
"input_folder_help": "İşlenecek mikslerin bulunduğu klasör",
|
142 |
+
"audio_path_help": "İşlenecek tek bir ses dosyasının yolu",
|
143 |
+
"store_dir_help": "Sonuçların saklanacağı yol",
|
144 |
+
"device_ids_help": "GPU kimlikleri listesi",
|
145 |
+
"extract_instrumental_help": "Eğer sağlanmışsa, vokali tersine çevirerek enstrümantal elde et",
|
146 |
+
"disable_detailed_pbar_help": "Ayrıştırmada ayrıntılı ilerleme çubuğunu devre dışı bırak",
|
147 |
+
"force_cpu_help": "CUDA mevcut olsa bile CPU'yu zorla kullan",
|
148 |
+
"flac_file_help": "WAV yerine FLAC dosyası oluştur",
|
149 |
+
"export_format_help": "Dışa aktarma biçimi ve PCM türü",
|
150 |
+
"pcm_type_help": "FLAC dosyaları için PCM türü",
|
151 |
+
"use_tta_help": "Test zamanı artırmayı etkinleştir",
|
152 |
+
"lora_checkpoint_help": "LoRA ağırlıkları için başlangıç kontrol noktası",
|
153 |
+
"cuda_available": "CUDA mevcut, devre dışı bırakmak için --force_cpu kullan.",
|
154 |
+
"using_device": "Kullanılan cihaz: {}",
|
155 |
+
"instruments_print": "Enstrümanlar: {}",
|
156 |
+
"model_load_time": "Model yükleme süresi: {:.2f} saniye",
|
157 |
+
"invalid_url": "❌ Geçersiz URL",
|
158 |
+
"cookie_file_updated": "✅ Çerez dosyası güncellendi!",
|
159 |
+
"cookie_installation_error": "⚠️ Çerez yükleme hatası: {}",
|
160 |
+
"file_size_zero_error": "Dosya boyutu sıfır veya dosya oluşturulmadı",
|
161 |
+
"google_drive_error": "❌ Google Drive indirme hatası: {}",
|
162 |
+
"wav_conversion_failed": "WAV dönüşümü başarısız",
|
163 |
+
"download_error": "❌ İndirme hatası: {}",
|
164 |
+
"download_success": "🎉 Başarıyla indirildi!",
|
165 |
+
"download_failed": "❌ İndirme başarısız",
|
166 |
+
"no_output_files_found": "❌ Çıktı dosyaları bulunamadı.",
|
167 |
+
"output_refreshed_successfully": "✅ Çıktı başarıyla yenilendi!",
|
168 |
+
"error_refreshing_output": "❌ Çıktı yenilenirken hata: {}",
|
169 |
+
"starting_audio_separation": "Ses ayrıştırma başlıyor...",
|
170 |
+
"processing_audio": "Ses işleniyor",
|
171 |
+
"separating_audio": "Ses ayrıştırılıyor... ({:.1f}%)",
|
172 |
+
"separation_complete": "Ayrıştırma tamamlandı!",
|
173 |
+
"progress_parsing_error": "İlerleme çözümleme hatası: {}",
|
174 |
+
"error_occurred": "Bir hata oluştu: {}",
|
175 |
+
"separation_process_completed": "Ayrıştırma işlemi tamamlandı!",
|
176 |
+
"no_audio_file_error": "❌ Ses dosyası sağlanmadı ve giriş dizininde mevcut dosya yok.",
|
177 |
+
"no_input_progress_label": "Hata: Giriş sağlanmadı -- 0.0%",
|
178 |
+
"processing_audio_print": "Ses işleniyor: {} üzerinden, kullanılan model: {}",
|
179 |
+
"starting_audio_separation_progress_label": "Ses ayrıştırma başlıyor... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "Ses ayrıştırılıyor... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "Ses işleme tamamlandı! -- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ Ses işleme tamamlandı!",
|
183 |
+
"error_occurred_progress_label": "Hata oluştu -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ En az 2 dosya gerekli",
|
185 |
+
"valid_files_not_found": "❌ Geçerli dosya bulunamadı",
|
186 |
+
"starting_ensemble_process": "birleştirme işlemi başlıyor...",
|
187 |
+
"ensembling_progress": "birleştirme yapılıyor... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "birleştirme çıktısı tamamlanıyor...",
|
189 |
+
"success_log": "✅ Başarılı!\n{}",
|
190 |
+
"error_log": "❌ Hata!\n{}",
|
191 |
+
"critical_error": "⛔ Kritik hata: {}",
|
192 |
+
"ensemble_process_completed": "birleştirme işlemi tamamlandı!",
|
193 |
+
"no_models_selected": "❌ Model seçilmedi",
|
194 |
+
"no_input_audio_provided": "❌ Giriş sesi sağlanmadı",
|
195 |
+
"loading_model": "Model yükleniyor {}/{}: {}...",
|
196 |
+
"loading_model_progress_label": "Model yükleniyor {}/{}: {}... -- {}.0%",
|
197 |
+
"completed_model": "Model tamamlandı {}/{}: {}",
|
198 |
+
"completed_model_progress_label": "Model tamamlandı {}/{}: {} -- {}.0%",
|
199 |
+
"running_command": "Komut çalıştırılıyor: {}",
|
200 |
+
"model_failed": "Model {} başarısız: {}",
|
201 |
+
"critical_error_with_model": "{} ile kritik hata: {}",
|
202 |
+
"model_output_failed": "{} çıktı üretemedi",
|
203 |
+
"waiting_for_files": "Tüm dosyaların hazır olması bekleniyor...",
|
204 |
+
"waiting_for_files_progress_label": "Tüm dosyaların hazır olması bekleniyor... -- 90.0%",
|
205 |
+
"performing_ensemble": "birleştirme gerçekleştiriliyor...",
|
206 |
+
"performing_ensemble_progress_label": "birleştirme gerçekleştiriliyor... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "birleştirme öncesi bellek kullanımı: {}%",
|
208 |
+
"memory_usage_after_ensemble": "birleştirme sonrası bellek kullanımı: {}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "birleştirme çıktısı tamamlanıyor... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "birleştirme dosyası oluşturulamadı: {}",
|
211 |
+
"ensemble_completed_progress_label": "birleştirme başarıyla tamamlandı! -- 100.0%",
|
212 |
+
"success_output_created": "✅ Başarılı! Çıktı dosyası oluşturuldu.",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive bağlandı. birleştirme çıktısı kopyalanıyor...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive zaten bağlı. birleştirme çıktısı kopyalanıyor...",
|
215 |
+
"no_ensemble_output_files_found": "❌ birleştirme çıktı dosyaları bulunamadı.",
|
216 |
+
"ensemble_output_copied": "✅ birleştirme çıktısı {}'e kopyalandı",
|
217 |
+
"error_copying_ensemble_output": "❌ birleştirme çıktısı kopyalanırken hata: {}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive bağlandı. Dosyalar kopyalanıyor...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive zaten bağlı. Dosyalar kopyalanıyor...",
|
220 |
+
"files_copied_to_drive": "✅ Dosyalar {}'e kopyalandı",
|
221 |
+
"error_copying_files": "❌ Dosyalar kopyalanırken hata: {}",
|
222 |
+
"mounting_drive": "Google Drive bağlanıyor...",
|
223 |
+
"settings_saved": "Ayarlar config.json'a kaydedildi: Dil={lang}, Yöntem={method}, Port={port}",
|
224 |
+
"selected_language": "Seçilen dil: {lang}",
|
225 |
+
"availa ble_languages": "Kullanılabilir diller: {langs}",
|
226 |
+
"select_language_prompt": "Bir dil seç (varsayılan: {default}): ",
|
227 |
+
"invalid_language": "Geçersiz dil seçimi! Varsayılan dil kullanılıyor ({default}).",
|
228 |
+
"available_sharing_methods": "Kullanılabilir paylaşım yöntemleri: gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "Bir paylaşım yöntemi seç (varsayılan: {default}): ",
|
230 |
+
"enter_ngrok_token_prompt": "Ngrok token'ını gir (varsayılan: {default}): ",
|
231 |
+
"ngrok_token_required": "Hata: ngrok yöntemi için Ngrok token'ı gerekli!",
|
232 |
+
"enter_port_prompt": "Port numarasını gir (varsayılan: {default}): ",
|
233 |
+
"opening_previous_url": "Önceki URL açılıyor: {url}",
|
234 |
+
"open_url_manually": "URL'yi Colab'da manuel olarak aç: {url}",
|
235 |
+
"invalid_previous_url": "Geçersiz önceki URL: {url}, açılmadı.",
|
236 |
+
"starting_method": "{method} port {port} üzerinde başlatılıyor...",
|
237 |
+
"process_stopped": "\n🛑 Kullanıcı tarafından işlem durduruldu",
|
238 |
+
"selected_port": "Seçilen port: {port}",
|
239 |
+
"starting_gradio_with_sharing": "Gradio dahili paylaşım ile başlatılıyor...",
|
240 |
+
"starting_localtunnel": "Localtunnel port {port} üzerinde başlatılıyor...",
|
241 |
+
"share_link": "Paylaşım bağlantısı: {url}",
|
242 |
+
"password_ip": "Parola IP: {ip}",
|
243 |
+
"starting_ngrok": "Ngrok port {port} üzerinde başlatılıyor...",
|
244 |
+
"ngrok_url": "Ngrok URL: {url}",
|
245 |
+
"ngrok_error": "Ngrok başlatma hatası: {error}",
|
246 |
+
"auto_apollo_chunk_size": "Apollo Parça Boyutu",
|
247 |
+
"auto_apollo_chunk_size_info": "Apollo iyileştirme için parça boyutu (evrensel model için önerilen: 19)",
|
248 |
+
"auto_apollo_overlap": "Apollo Çakışması",
|
249 |
+
"auto_enhancing_with_apollo": "Apollo ile iyileştiriliyor ({}/{} dosya)...",
|
250 |
+
"auto_apollo_processing_completed": "Apollo işleme tamamlandı!",
|
251 |
+
"autoapollo_overlap_info": "Apollo iyileştirme için çakışma (önerilen: 2)",
|
252 |
+
"auto_invalid_method": "Hata: Geçersiz yöntem! 'gradio', 'localtunnel' veya 'ngrok' kullan.",
|
253 |
+
"auto_apollo_enhancement_settings": "Apollo İyileştirme Ayarları",
|
254 |
+
"auto_enhance_with_apollo": "Apollo ile İyileştir",
|
255 |
+
"auto_enhance_with_apollo_info": "Ayrıştırmadan sonra ses iyileştirme için Apollo'yu etkinleştir",
|
256 |
+
"auto_apollo_method": "Apollo Yöntemi",
|
257 |
+
"auto_apollo_method_info": "Apollo için işlem yöntemini seç",
|
258 |
+
"auto_normal_method": "Normal Yöntem",
|
259 |
+
"auto_mid_side_method": "Orta/Yan Yöntem",
|
260 |
+
"auto_apollo_normal_model": "Apollo Normal Model",
|
261 |
+
"auto_apollo_normal_model_info": "Normal Apollo işleme için kullanılacak model",
|
262 |
+
"auto_apollo_midside_model": "Apollo Orta/Yan Model",
|
263 |
+
"auto_apollo_enhancement_info": "Ses kalitesi iyileştirme",
|
264 |
+
"auto_apollo_midside_model_info": "Orta/yan işleme için kullanılacak model (isteğe bağlı)",
|
265 |
+
"apollo_chunk_size": "Apollo Parça Boyutu",
|
266 |
+
"apollo_chunk_size_info": "Apollo iyileştirme için parça boyutu (evrensel model için önerilen: 19)",
|
267 |
+
"apollo_overlap": "Apollo Çakışması",
|
268 |
+
"enhancing_with_apollo": "Apollo ile iyileştiriliyor ({}/{} dosya)...",
|
269 |
+
"apollo_processing_completed": "Apollo işleme tamamlandı!",
|
270 |
+
"apollo_overlap_info": "Apollo iyileştirme için çakışma (önerilen: 2)",
|
271 |
+
"invalid_method": "Hata: Geçersiz yöntem! 'gradio', 'localtunnel' veya 'ngrok' kullan.",
|
272 |
+
"apollo_enhancement_settings": "Apollo İyileştirme Ayarları",
|
273 |
+
"enhance_with_apollo": "Apollo ile İyileştir",
|
274 |
+
"enhance_with_apollo_info": "Ayrıştırmadan sonra ses iyileştirme için Apollo'yu etkinleştir",
|
275 |
+
"apollo_method": "Apollo Yöntemi",
|
276 |
+
"apollo_method_info": "Apollo için işlem yöntemini seç",
|
277 |
+
"normal_method": "Normal Yöntem",
|
278 |
+
"mid_side_method": "Orta/Yan Yöntem",
|
279 |
+
"apollo_normal_model": "Apollo Normal için Model",
|
280 |
+
"apollo_normal_model_info": "Normal Apollo işleme için kullanılacak model",
|
281 |
+
"apollo_midside_model": "Apollo Orta/Yan Model",
|
282 |
+
"apollo_enhancement_info": "Ses kalitesi iyileştirme",
|
283 |
+
"apollo_processing_method": "Apollo işlem metodu",
|
284 |
+
"apollo_mid_side_model": "Apollo orta/yan için modeller",
|
285 |
+
"selected_models": "Seçilecek modeller",
|
286 |
+
"save_preset": "Ön ayarı kaydet",
|
287 |
+
"delete_preset": "Ön ayyarı sil",
|
288 |
+
"refresh_presets": "Ön ayarları güncelle",
|
289 |
+
"preset_name": "ön ayar ismi",
|
290 |
+
"select_preset": "Ön ayarlar",
|
291 |
+
"add_favorite": "favorilere ekle",
|
292 |
+
"apollo_midside_model_info": "Orta/yan işleme için kullanılacak model (isteğe bağlı)",
|
293 |
+
"language_changed_message": "Dil değiştirildi. Lütfen hücreyi yeniden başlat.",
|
294 |
+
"apply_matchering": "Matchering Uygula",
|
295 |
+
"matchering_info": "Ses masteringini ve dengesini iyileştirmek için Matchering uygula",
|
296 |
+
"matchering_passes": "Matchering Geçişleri",
|
297 |
+
"matchering_passes_info": "Matchering yineleme sayısı (1-5, yüksek değerler kaliteyi artırır ancak daha uzun sürer)",
|
298 |
+
"matchering_processing": "Matchering uygulanıyor... ({:.1f}%)",
|
299 |
+
"matchering_completed": "✅ Matchering işlemi tamamlandı!",
|
300 |
+
"matchering_error": "❌ Matchering sırasında hata: {}"
|
301 |
+
}
|
assets/i18n/languages/zn_cn.json
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"select_language": "选择语言",
|
3 |
+
"gecekondu_production": "Gecekondu Production",
|
4 |
+
"ultimate_audio_separation": "您的终极音频分离",
|
5 |
+
"presented_by": "由 Gecekondu Production © 2025 提供",
|
6 |
+
"audio_separation_tab": "🎙️ 音频分离",
|
7 |
+
"input_model": "📥 输入和模型",
|
8 |
+
"upload": "🖥 上传",
|
9 |
+
"path": "📂 路径",
|
10 |
+
"path_placeholder": "/路径/至/音频.wav",
|
11 |
+
"category": "类别",
|
12 |
+
"model": "模型",
|
13 |
+
"settings": "⚙ 设置",
|
14 |
+
"format": "格式",
|
15 |
+
"chunk_size": "分块大小",
|
16 |
+
"chunk_size_info": "除非有特殊需求,否则不要更改",
|
17 |
+
"overlap": "重叠",
|
18 |
+
"overlap_info": "推荐:2-10(更高的值提升质量,但需要更多VRAM)",
|
19 |
+
"tta_boost": "TTA增强",
|
20 |
+
"tta_info": "提高质量,但会减慢处理速度",
|
21 |
+
"phase_fix": "相位修正",
|
22 |
+
"phase_fix_info": "用于乐器轨的高级相位修正",
|
23 |
+
"instrumental": "乐器",
|
24 |
+
"instrumental_info": "通常输出2个结果,但有时只有一个,试试看吧!:)",
|
25 |
+
"process": "🚀 处理",
|
26 |
+
"reset": "🧹 重置",
|
27 |
+
"status": "状态",
|
28 |
+
"main_tab": "🎧 主页",
|
29 |
+
"original": "原始",
|
30 |
+
"vocals": "人声",
|
31 |
+
"instrumental_output": "乐器",
|
32 |
+
"other": "其他",
|
33 |
+
"details_tab": "🔍 详情",
|
34 |
+
"male": "男声",
|
35 |
+
"female": "女声",
|
36 |
+
"speech": "语音",
|
37 |
+
"drums": "鼓",
|
38 |
+
"bass": "低音",
|
39 |
+
"effects": "效果",
|
40 |
+
"advanced_tab": "⚙ 高级",
|
41 |
+
"phase_remix": "相位混音",
|
42 |
+
"dry": "干声",
|
43 |
+
"music": "音乐",
|
44 |
+
"karaoke": "卡拉OK",
|
45 |
+
"bleed": "渗漏",
|
46 |
+
"copy_to_drive": "📂 复制到云盘",
|
47 |
+
"copy_status": "复制状态",
|
48 |
+
"files_will_be_copied": "文件将复制到此处...",
|
49 |
+
"processing_tip": "<b>🔈 处理提示:</b> 对于有噪声的结果,使用<i>“去除噪声和效果”</i>类别中的<code>bleed_suppressor_v1</code>或<code>denoisedebleed</code>模型来清理输出",
|
50 |
+
"waiting_for_processing": "等待处理...",
|
51 |
+
"auto_ensemble_tab": "🤖 自动集成",
|
52 |
+
"upload_file": "上传文件",
|
53 |
+
"enter_file_path": "或输入文件路径",
|
54 |
+
"file_path_placeholder": "输入音频文件的完整路径",
|
55 |
+
"advanced_settings": "⚙️ 高级设置",
|
56 |
+
"use_tta": "使用TTA",
|
57 |
+
"instrumental_only": "仅乐器",
|
58 |
+
"auto_overlap": "重叠",
|
59 |
+
"auto_chunk_size": "分块大小",
|
60 |
+
"output_format": "输出格式",
|
61 |
+
"model_selection": "🧠 模型选择",
|
62 |
+
"model_category": "模型类别",
|
63 |
+
"select_models": "从类别中选择模型",
|
64 |
+
"ensemble_settings": "⚡ 集成设置",
|
65 |
+
"method": "方法",
|
66 |
+
"recommendation": "**推荐:** avg_wave 和 max_fft 提供最佳结果",
|
67 |
+
"start_processing": "🚀 开始处理",
|
68 |
+
"original_audio_tab": "🔊 原始音频",
|
69 |
+
"original_audio": "原始音频",
|
70 |
+
"ensemble_result_tab": "🎚️ 集成结果",
|
71 |
+
"output_preview": "输出预览",
|
72 |
+
"refresh_output": "🔄 刷新输出",
|
73 |
+
"ensemble_copy_status": "集成输出将复制到此处...",
|
74 |
+
"guidelines": "<h4>模型选择指南</h4><ul><li><strong>避免混合类别:</strong> 混合人声和乐器模型可能导致意外混合</li><li><strong>特殊模型说明:</strong><ul><li>双重模型 (v1/v2) - 输出两个声道</li><li>MDX23C分离器 - 混合结果</li></ul></li><li><strong>最佳实践:</strong> 使用同一类别中的3-5个相似模型</li></ul><div>💡 专业提示:从“VOCALS-MelBand-Roformer BigBeta5e” + “VOCALS-BS-Roformer_1297”组合开始</div>",
|
75 |
+
"download_sources_tab": "⬇️ 下载来源",
|
76 |
+
"direct_links": "🌐 直接链接",
|
77 |
+
"audio_file_url": "音频文件URL",
|
78 |
+
"download_from_url": "⬇️ 从URL下载",
|
79 |
+
"download_status": "下载状态",
|
80 |
+
"downloaded_file": "已下载文件",
|
81 |
+
"cookie_management": "🍪 Cookie管理",
|
82 |
+
"upload_cookies_txt": "上传Cookies.txt",
|
83 |
+
"cookie_info": "<div style=\"margin-left:15px; font-size:0.95em\">**📌 为什么需要?**<br>- 访问年龄限制内容<br>- 下载私人/未列出的视频<br>- 绕过地区限制<br>- 避免YouTube下载限制<br><br>**⚠️ 重要提示**<br>- 切勿分享您的cookie文件!<br>- 在以下情况更新cookie:<br> • 出现“403禁止”错误<br> • 下载突然停止<br> • 看到“会话过期”消息<br><br>**🔄 更新步骤**<br>1. 安装此<a href=\"https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie\" target=\"_blank\">Chrome扩展</a><br>2. 在Chrome中登录YouTube<br>3. 点击扩展图标 → “导出”<br>4. 将下载的文件上传到此处<br><br>**⏳ Cookie寿命**<br>- 普通会话:24小时<br>- 敏感操作:1小时<br>- 密码更改:立即失效</div>",
|
84 |
+
"manual_ensemble_tab": "🎚️ 手动集成",
|
85 |
+
"input_sources": "📂 输入来源",
|
86 |
+
"refresh": "🔄 刷新",
|
87 |
+
"ensemble_algorithm": "集成算法",
|
88 |
+
"select_audio_files": "选择音频文件",
|
89 |
+
"available_files": "可用文件",
|
90 |
+
"custom_weights": "自定义权重(用逗号分隔)",
|
91 |
+
"custom_weights_placeholder": "示例��0.8, 1.2, 1.0, ...",
|
92 |
+
"custom_weights_info": "留空表示相等权重",
|
93 |
+
"result_preview_tab": "🎧 结果预览",
|
94 |
+
"ensembled_output": "集成输出",
|
95 |
+
"processing_log_tab": "📋 处理日志",
|
96 |
+
"processing_details": "处理详情",
|
97 |
+
"process_ensemble": "⚡ 处理集成",
|
98 |
+
"languages_tab": "🌐 语言",
|
99 |
+
"Vocal Models": "人声模型",
|
100 |
+
"Instrumental Models": "乐器模型",
|
101 |
+
"4-Stem Models": "4声道模型",
|
102 |
+
"Denoise Models": "去噪模型",
|
103 |
+
"Dereverb Models": "去混响模型",
|
104 |
+
"Other Models": "其他模型",
|
105 |
+
"ensemble_files_description": "使用指定的集成方法将多个音频文件合并为一个输出。",
|
106 |
+
"ensemble_files_help": "所有用于集成的音频文件的路径",
|
107 |
+
"ensemble_type_help": "以下之一:avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft",
|
108 |
+
"ensemble_weights_help": "创建集成所需的权重。权重数量必须与文件数量匹配",
|
109 |
+
"ensemble_output_help": "保存集成结果的WAV文件路径",
|
110 |
+
"ensemble_type_print": "集成类型:{}",
|
111 |
+
"num_input_files_print": "输入文件数量:{}",
|
112 |
+
"weights_print": "权重:{}",
|
113 |
+
"output_file_print": "输出文件:{}",
|
114 |
+
"duration_mismatch_error": "所有文件必须具有相同的时长",
|
115 |
+
"file_not_found_error": "错误。找不到文件:{}。请检查路径。",
|
116 |
+
"reading_chunk_print": "读取文件分块:{}(开始:{}秒,时长:{}秒)",
|
117 |
+
"chunk_result_shape_print": "分块结果形状:{}",
|
118 |
+
"ensemble_completed_print": "集成完成。输出保存至:{}",
|
119 |
+
"file_deletion_error": "{}无法删除:{}",
|
120 |
+
"directory_not_exist_warning": "⚠️ 目录不存在:{}",
|
121 |
+
"not_a_directory_warning": "⚠️ 路径不是目录:{}",
|
122 |
+
"item_deletion_error": "⚠️ 删除{}时出错:{}",
|
123 |
+
"old_output_not_exist": "❌ 旧输出文件夹不存在",
|
124 |
+
"old_outputs_cleared": "✅ 旧输出已成功清除!",
|
125 |
+
"error": "🔥 错误:{}",
|
126 |
+
"ffmpeg_error": "FFmpeg错误({}):{}",
|
127 |
+
"file_saved_successfully": "文件保存成功:{}",
|
128 |
+
"total_files_found": "找到的文件总数:{}。使用的采样率:{}",
|
129 |
+
"total_progress": "总进度",
|
130 |
+
"detailed_pbar_enabled": "详细进度条已启用:{}",
|
131 |
+
"loaded_audio": "已加载音频:{},形状:{}",
|
132 |
+
"cannot_read_track": "无法读取轨道:{}",
|
133 |
+
"error_message": "错误消息:{}",
|
134 |
+
"demudding_track": "清理轨道(相位混音 - 乐器):{}",
|
135 |
+
"elapsed_time": "已用时间:{:.2f}秒。",
|
136 |
+
"proc_folder_description": "使用指定模型处理文件夹中的音频文件。",
|
137 |
+
"model_type_help": "模型类型(bandit, bs_roformer, mdx23c 等)",
|
138 |
+
"config_path_help": "配置文件路径",
|
139 |
+
"demud_phaseremix_help": "为乐器启用相位混音",
|
140 |
+
"start_checkpoint_help": "有效权重的初始检查点",
|
141 |
+
"input_folder_help": "包含待处理混合音频的文件夹",
|
142 |
+
"audio_path_help": "单个待处理音频文件的路径",
|
143 |
+
"store_dir_help": "存储结果的路径",
|
144 |
+
"device_ids_help": "GPU ID列表",
|
145 |
+
"extract_instrumental_help": "如提供,则反转人声以获取乐器",
|
146 |
+
"disable_detailed_pbar_help": "在分离中禁用详细进度条",
|
147 |
+
"force_cpu_help": "即使CUDA可用,也强制使用CPU",
|
148 |
+
"flac_file_help": "生成FLAC文件而非WAV",
|
149 |
+
"export_format_help": "导出格式和PCM类型",
|
150 |
+
"pcm_type_help": "FLAC文件的PCM类型",
|
151 |
+
"use_tta_help": "启用测试时间增强",
|
152 |
+
"lora_checkpoint_help": "LoRA权重的初始检查点",
|
153 |
+
"cuda_available": "CUDA可用,使用 --force_cpu 禁用。",
|
154 |
+
"using_device": "使用的设备:{}",
|
155 |
+
"instruments_print": "乐器:{}",
|
156 |
+
"model_load_time": "模型加载时间:{:.2f}秒",
|
157 |
+
"invalid_url": "❌ 无效URL",
|
158 |
+
"cookie_file_updated": "✅ Cookie文件已更新!",
|
159 |
+
"cookie_installation_error": "⚠️ Cookie安装错误:{}",
|
160 |
+
"file_size_zero_error": "文件大小为零或文件未创建",
|
161 |
+
"google_drive_error": "❌ Google Drive下载错误:{}",
|
162 |
+
"wav_conversion_failed": "WAV转换失败",
|
163 |
+
"download_error": "❌ 下载错误:{}",
|
164 |
+
"download_success": "🎉 下载成功!",
|
165 |
+
"download_failed": "❌ 下载失败",
|
166 |
+
"no_output_files_found": "❌ 未找到输出文件。",
|
167 |
+
"output_refreshed_successfully": "✅ 输出刷新成功!",
|
168 |
+
"error_refreshing_output": "❌ 刷新输出时出错:{}",
|
169 |
+
"starting_audio_separation": "开始音频分离...",
|
170 |
+
"processing_audio": "处理音频",
|
171 |
+
"separating_audio": "分离音频... ({:.1f}%)",
|
172 |
+
"separation_complete": "分离完成!",
|
173 |
+
"progress_parsing_error": "进度解析错误:{}",
|
174 |
+
"error_occurred": "发生错误:{}",
|
175 |
+
"separation_process_completed": "分离过程完成!",
|
176 |
+
"no_audio_file_error": "❌ 未提供音频文件,且输入目录中没有现有文件。",
|
177 |
+
"no_input_progress_label": "错误:未提供输入 -- 0.0%",
|
178 |
+
"processing_audio_print": "正在处理音频:{},使用模型:{}",
|
179 |
+
"starting_audio_separation_progress_label": "开始音频分离... -- 0.0%",
|
180 |
+
"separating_audio_progress_label": "分离音频... -- {}.0%",
|
181 |
+
"audio_processing_completed_progress_label": "音频处理完成!-- 100.0%",
|
182 |
+
"audio_processing_completed": "✅ 音频处理完成!",
|
183 |
+
"error_occurred_progress_label": "发生错误 -- 0.0%",
|
184 |
+
"minimum_files_required": "⚠️ 至少需要2个文件",
|
185 |
+
"valid_files_not_found": "❌ 未找到有效文件",
|
186 |
+
"starting_ensemble_process": "开始集成过程...",
|
187 |
+
"ensembling_progress": "集成中... ({:.1f}%)",
|
188 |
+
"finalizing_ensemble_output": "完成集成输出...",
|
189 |
+
"success_log": "✅ 成功!\n{}",
|
190 |
+
"error_log": "❌ 错误!\n{}",
|
191 |
+
"critical_error": "⛔ 严重错误:{}",
|
192 |
+
"ensemble_process_completed": "集成过程完成!",
|
193 |
+
"no_models_selected": "❌ 未选择模型",
|
194 |
+
"no_input_audio_provided": "❌ 未提供输入音频",
|
195 |
+
"loading_model": "加载模型 {}/{}:{}...",
|
196 |
+
"loading_model_progress_label": "加载模型 {}/{}:{}... -- {}.0%",
|
197 |
+
"completed_model": "模型完成 {}/{}:{}",
|
198 |
+
"completed_model_progress_label": "模型完成 {}/{}:{} -- {}.0%",
|
199 |
+
"running_command": "执行命令:{}",
|
200 |
+
"model_failed": "模型 {} 失败:{}",
|
201 |
+
"critical_error_with_model": "{} 出现严重错误:{}",
|
202 |
+
"model_output_failed": "{} 未能生成输出",
|
203 |
+
"waiting_for_files": "等待所有文件准备就绪...",
|
204 |
+
"waiting_for_files_progress_label": "等待所有文件准备就绪... -- 90.0%",
|
205 |
+
"performing_ensemble": "执行集成...",
|
206 |
+
"performing_ensemble_progress_label": "执行集成... -- 92.0%",
|
207 |
+
"memory_usage_before_ensemble": "集成前内存使用:{}%",
|
208 |
+
"memory_usage_after_ensemble": "集成后内存使用:{}%",
|
209 |
+
"finalizing_ensemble_output_progress_label": "完成集成输出... -- 98.0%",
|
210 |
+
"ensemble_file_creation_failed": "集成文件创建失败:{}",
|
211 |
+
"ensemble_completed_progress_label": "集成成功完成!-- 100.0%",
|
212 |
+
"success_output_created": "✅ 成功!输出文件已创建。",
|
213 |
+
"drive_mounted_copying_ensemble": "Google Drive已挂载。正在复制集成输出...",
|
214 |
+
"drive_already_mounted_copying_ensemble": "Google Drive已挂载。正在复制集成输出...",
|
215 |
+
"no_ensemble_output_files_found": "❌ 未找到集成输出文件。",
|
216 |
+
"ensemble_output_copied": "✅ 集成输出已复制到 {}",
|
217 |
+
"error_copying_ensemble_output": "❌ 复制集成输出时出错:{}",
|
218 |
+
"drive_mounted_copying_files": "Google Drive已挂载。正在复制文件...",
|
219 |
+
"drive_already_mounted_copying_files": "Google Drive已挂载。正在复制文件...",
|
220 |
+
"files_copied_to_drive": "✅ 文件已复制到 {}",
|
221 |
+
"error_copying_files": "❌ 复制文件时出错:{}",
|
222 |
+
"mounting_drive": "挂载Google Drive...",
|
223 |
+
"settings_saved": "设置已保存至 config.json:语言={lang},方法={method},端口={port}",
|
224 |
+
"selected_language": "所选语言:{lang}",
|
225 |
+
"available_languages": "可用语言:{langs}",
|
226 |
+
"select_language_prompt": "选择语言(默认:{default}):",
|
227 |
+
"invalid_language": "无效的语言选择!使用默认语言({default})。",
|
228 |
+
"available_sharing_methods": "可用共享方法:gradio, localtunnel, ngrok",
|
229 |
+
"select_sharing_method_prompt": "选择共享方法(默认:{default}):",
|
230 |
+
"enter_ngrok_token_prompt": "输入您的Ngrok令牌(默认:{default}):",
|
231 |
+
"ngrok_token_required": "错误:ngrok方法需要Ngrok令牌!",
|
232 |
+
"enter_port_prompt": "输入端口号(默认:{default}):",
|
233 |
+
"opening_previous_url": "打开上一个URL:{url}",
|
234 |
+
"open_url_manually": "在Colab中手动打开URL:{url}",
|
235 |
+
"invalid_previous_url": "无效的上一个URL:{url},未打开。",
|
236 |
+
"starting_method": "在端口 {port} 上启动 {method}...",
|
237 |
+
"process_stopped": "\n🛑 用户停止了进程",
|
238 |
+
"selected_port": "所选端口:{port}",
|
239 |
+
"starting_gradio_with_sharing": "启动带有内置共享的Gradio...",
|
240 |
+
"starting_localtunnel": "在端口 {port} 上启动Localtunnel...",
|
241 |
+
"share_link": "共享链接:{url}",
|
242 |
+
"password_ip": "密码IP:{ip}",
|
243 |
+
"starting_ngrok": "在端口 {port} 上启动Ngrok...",
|
244 |
+
"ngrok_url": "Ngrok URL:{url}",
|
245 |
+
"ngrok_error": "启动Ngrok时出错:{error}",
|
246 |
+
"apollo_chunk_size": "Apollo分块大小",
|
247 |
+
"apollo_chunk_size_info": "Apollo改进的分块大小(通用模型推荐:19)",
|
248 |
+
"apollo_overlap": "Apollo重叠",
|
249 |
+
"enhancing_with_apollo": "使用Apollo增强({}/{} 文件)...",
|
250 |
+
"apollo_processing_completed": "Apollo处理完成!",
|
251 |
+
"apollo_overlap_info": "Apollo改进的重叠(推荐:2)",
|
252 |
+
"invalid_method": "错误:无效方法!使用 'gradio'、'localtunnel' 或 'ngrok'。",
|
253 |
+
"apollo_enhancement_settings": "Apollo增强设置",
|
254 |
+
"enhance_with_apollo": "使用Apollo增强",
|
255 |
+
"enhance_with_apollo_info": "分离后启用Apollo以增强音频",
|
256 |
+
"apollo_method": "Apollo方法",
|
257 |
+
"apollo_method_info": "选择Apollo的处理方法",
|
258 |
+
"normal_method": "普通方法",
|
259 |
+
"mid_side_method": "中/侧方法",
|
260 |
+
"apollo_normal_model": "Apollo普通模型",
|
261 |
+
"apollo_normal_model_info": "用于普通Apollo处理的模型",
|
262 |
+
"apollo_midside_model": "Apollo中/侧模型",
|
263 |
+
"apollo_enhancement_info": "音质增强",
|
264 |
+
"selected_models": "选定模型",
|
265 |
+
"save_preset": "保存预设",
|
266 |
+
"delete_preset": "删除预设",
|
267 |
+
"refresh_presets": "刷新预设",
|
268 |
+
"preset_name": "预设名称",
|
269 |
+
"select_preset": "选择预设",
|
270 |
+
"add_favorite": "添加到收藏",
|
271 |
+
"apollo_midside_model_info": "用于中/侧处理的模型(可选)",
|
272 |
+
"language_changed_message": "语言已更改。请重新启动单元。",
|
273 |
+
"apply_matchering": "应用 Matchering",
|
274 |
+
"matchering_info": "应用 Matchering 以提升音频母带处理和平衡",
|
275 |
+
"matchering_passes": "Matchering 迭代次数",
|
276 |
+
"matchering_passes_info": "Matchering 迭代次数(1-5,值越高质量越好,但耗时更长)",
|
277 |
+
"matchering_processing": "正在应用 Matchering... ({:.1f}%)",
|
278 |
+
"matchering_completed": "✅ Matchering 处理完成!",
|
279 |
+
"matchering_error": "❌ Matchering 过程中发生错误:{}"
|
280 |
+
}
|
config_manager.py
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
from pathlib import Path
|
4 |
+
|
5 |
+
# Define config directory in Google Drive
|
6 |
+
CONFIG_DIR = "/content/drive/MyDrive/SESA-Config"
|
7 |
+
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
|
8 |
+
|
9 |
+
def load_config():
|
10 |
+
"""Load configuration from config.json."""
|
11 |
+
default_config = {
|
12 |
+
"favorites": [],
|
13 |
+
"settings": {
|
14 |
+
"chunk_size": 352800,
|
15 |
+
"overlap": 2,
|
16 |
+
"export_format": "wav FLOAT",
|
17 |
+
"auto_use_tta": False,
|
18 |
+
"use_tta": False,
|
19 |
+
"use_demud_phaseremix_inst": False,
|
20 |
+
"auto_extract_instrumental": False,
|
21 |
+
"extract_instrumental": False,
|
22 |
+
"use_apollo": False,
|
23 |
+
"auto_use_apollo": False,
|
24 |
+
"auto_apollo_chunk_size": 19,
|
25 |
+
"auto_apollo_overlap": 2,
|
26 |
+
"auto_apollo_method": "normal_method",
|
27 |
+
"auto_apollo_normal_model": "Apollo Universal Model",
|
28 |
+
"auto_apollo_midside_model": "Apollo Universal Model",
|
29 |
+
"apollo_chunk_size": 19,
|
30 |
+
"apollo_overlap": 2,
|
31 |
+
"apollo_method": "normal_method",
|
32 |
+
"apollo_normal_model": "Apollo Universal Model",
|
33 |
+
"apollo_midside_model": "Apollo Universal Model",
|
34 |
+
"use_matchering": False,
|
35 |
+
"auto_use_matchering": False,
|
36 |
+
"matchering_passes": 1,
|
37 |
+
"auto_matchering_passes": 1,
|
38 |
+
"model_category": "Vocal Models",
|
39 |
+
"selected_model": None,
|
40 |
+
"auto_category": "Vocal Models",
|
41 |
+
"selected_models": [],
|
42 |
+
"auto_ensemble_type": "avg_wave",
|
43 |
+
"manual_ensemble_type": "avg_wave",
|
44 |
+
"auto_category_dropdown": "Vocal Models",
|
45 |
+
"manual_weights": ""
|
46 |
+
},
|
47 |
+
"presets": {}
|
48 |
+
}
|
49 |
+
|
50 |
+
os.makedirs(CONFIG_DIR, exist_ok=True)
|
51 |
+
if not os.path.exists(CONFIG_FILE):
|
52 |
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
53 |
+
json.dump(default_config, f, indent=2)
|
54 |
+
return default_config
|
55 |
+
|
56 |
+
try:
|
57 |
+
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
|
58 |
+
config = json.load(f)
|
59 |
+
# Merge with default config to ensure all keys exist
|
60 |
+
for key, value in default_config.items():
|
61 |
+
if key not in config:
|
62 |
+
config[key] = value
|
63 |
+
elif isinstance(value, dict):
|
64 |
+
for subkey, subvalue in value.items():
|
65 |
+
if subkey not in config[key]:
|
66 |
+
config[key][subkey] = subvalue
|
67 |
+
return config
|
68 |
+
except json.JSONDecodeError:
|
69 |
+
print("Warning: config.json is corrupted. Creating a new one.")
|
70 |
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
71 |
+
json.dump(default_config, f, indent=2)
|
72 |
+
return default_config
|
73 |
+
|
74 |
+
def save_config(favorites, settings, presets):
|
75 |
+
"""Save configuration to config.json."""
|
76 |
+
config = {
|
77 |
+
"favorites": favorites,
|
78 |
+
"settings": settings,
|
79 |
+
"presets": presets
|
80 |
+
}
|
81 |
+
os.makedirs(CONFIG_DIR, exist_ok=True)
|
82 |
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
83 |
+
json.dump(config, f, indent=2)
|
84 |
+
|
85 |
+
def update_favorites(favorites, model, add=True):
|
86 |
+
"""Update favorites list."""
|
87 |
+
cleaned_model = model
|
88 |
+
new_favorites = favorites.copy()
|
89 |
+
if add and cleaned_model not in new_favorites:
|
90 |
+
new_favorites.append(cleaned_model)
|
91 |
+
elif not add and cleaned_model in new_favorites:
|
92 |
+
new_favorites.remove(cleaned_model)
|
93 |
+
return new_favorites
|
94 |
+
|
95 |
+
def save_preset(presets, preset_name, models, ensemble_method, **kwargs):
|
96 |
+
"""Save a preset."""
|
97 |
+
new_presets = presets.copy()
|
98 |
+
cleaned_models = [clean_model(model) for model in models]
|
99 |
+
new_presets[preset_name] = {
|
100 |
+
"models": cleaned_models,
|
101 |
+
"ensemble_method": ensemble_method,
|
102 |
+
"chunk_size": kwargs.get("chunk_size", load_config()["settings"]["chunk_size"]),
|
103 |
+
"overlap": kwargs.get("overlap", load_config()["settings"]["overlap"]),
|
104 |
+
"auto_use_tta": kwargs.get("auto_use_tta", load_config()["settings"]["auto_use_tta"]),
|
105 |
+
"auto_extract_instrumental": kwargs.get("auto_extract_instrumental", load_config()["settings"]["auto_extract_instrumental"]),
|
106 |
+
"use_apollo": kwargs.get("use_apollo", load_config()["settings"]["use_apollo"]),
|
107 |
+
"auto_apollo_chunk_size": kwargs.get("auto_apollo_chunk_size", load_config()["settings"]["auto_apollo_chunk_size"]),
|
108 |
+
"auto_category_dropdown": kwargs.get("auto_category_dropdown", load_config()["settings"]["auto_category_dropdown"]), # Save category
|
109 |
+
"auto_apollo_overlap": kwargs.get("auto_apollo_overlap", load_config()["settings"]["auto_apollo_overlap"]),
|
110 |
+
"auto_apollo_method": kwargs.get("auto_apollo_method", load_config()["settings"]["auto_apollo_method"]),
|
111 |
+
"auto_apollo_normal_model": kwargs.get("auto_apollo_normal_model", load_config()["settings"]["auto_apollo_normal_model"]),
|
112 |
+
"auto_apollo_midside_model": kwargs.get("auto_apollo_midside_model", load_config()["settings"]["auto_apollo_midside_model"]),
|
113 |
+
"auto_use_matchering": kwargs.get("use_matchering", load_config()["settings"]["use_matchering"]),
|
114 |
+
"auto_matchering_passes": kwargs.get("matchering_passes", load_config()["settings"]["matchering_passes"]),
|
115 |
+
"auto_category": kwargs.get("auto_category", load_config()["settings"]["auto_category"])
|
116 |
+
}
|
117 |
+
return new_presets
|
118 |
+
|
119 |
+
def delete_preset(presets, preset_name):
|
120 |
+
"""Delete a preset."""
|
121 |
+
new_presets = presets.copy()
|
122 |
+
if preset_name in new_presets:
|
123 |
+
del new_presets[preset_name]
|
124 |
+
return new_presets
|
125 |
+
|
126 |
+
def clean_model(model):
|
127 |
+
"""Remove ⭐ from model name if present."""
|
128 |
+
return model.replace(" ⭐", "") if isinstance(model, str) else model
|
download.py
CHANGED
@@ -2,46 +2,116 @@ import os
|
|
2 |
import re
|
3 |
import validators
|
4 |
import yt_dlp
|
5 |
-
import
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
from helpers import INPUT_DIR, COOKIE_PATH, clear_directory, clear_temp_folder, BASE_DIR
|
8 |
import yaml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
def download_callback(url, download_type='direct', cookie_file=None):
|
|
|
11 |
clear_temp_folder("/tmp", exclude_items=["gradio", "config.json"])
|
12 |
clear_directory(INPUT_DIR)
|
13 |
os.makedirs(INPUT_DIR, exist_ok=True)
|
14 |
|
15 |
-
|
16 |
-
|
|
|
17 |
|
|
|
18 |
if cookie_file is not None:
|
19 |
try:
|
20 |
with open(cookie_file.name, "rb") as f:
|
21 |
cookie_content = f.read()
|
22 |
with open(COOKIE_PATH, "wb") as f:
|
23 |
f.write(cookie_content)
|
24 |
-
print("
|
25 |
except Exception as e:
|
26 |
-
print(
|
27 |
|
28 |
wav_path = None
|
29 |
download_success = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
-
|
|
|
32 |
try:
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
output_path = os.path.join(INPUT_DIR, "drive_download.wav")
|
35 |
gdown.download(f'https://drive.google.com/uc?id={file_id}', output_path, quiet=True)
|
36 |
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
37 |
-
|
|
|
|
|
|
|
38 |
download_success = True
|
39 |
else:
|
40 |
-
raise Exception("
|
41 |
except Exception as e:
|
42 |
-
error_msg =
|
43 |
print(error_msg)
|
44 |
return None, error_msg, None, None, None, None
|
|
|
|
|
45 |
else:
|
46 |
ydl_opts = {
|
47 |
'format': 'bestaudio/best',
|
@@ -60,26 +130,43 @@ def download_callback(url, download_type='direct', cookie_file=None):
|
|
60 |
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
61 |
info_dict = ydl.extract_info(url, download=True)
|
62 |
temp_path = ydl.prepare_filename(info_dict)
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
65 |
download_success = True
|
66 |
else:
|
67 |
-
raise Exception("
|
68 |
except Exception as e:
|
69 |
-
error_msg =
|
70 |
print(error_msg)
|
71 |
return None, error_msg, None, None, None, None
|
72 |
|
|
|
73 |
if download_success and wav_path:
|
74 |
for f in os.listdir(INPUT_DIR):
|
75 |
if f != os.path.basename(wav_path):
|
76 |
os.remove(os.path.join(INPUT_DIR, f))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
return (
|
78 |
wav_path,
|
79 |
-
"
|
80 |
wav_path,
|
81 |
wav_path,
|
82 |
wav_path,
|
83 |
wav_path
|
84 |
)
|
85 |
-
|
|
|
|
2 |
import re
|
3 |
import validators
|
4 |
import yt_dlp
|
5 |
+
import requests
|
6 |
+
import shutil
|
7 |
+
try:
|
8 |
+
import gdown
|
9 |
+
except ImportError:
|
10 |
+
os.system('pip install gdown')
|
11 |
+
import gdown
|
12 |
+
try:
|
13 |
+
from google.colab import drive
|
14 |
+
except ImportError:
|
15 |
+
drive = None
|
16 |
from helpers import INPUT_DIR, COOKIE_PATH, clear_directory, clear_temp_folder, BASE_DIR
|
17 |
import yaml
|
18 |
+
from assets.i18n.i18n import I18nAuto
|
19 |
+
|
20 |
+
i18n = I18nAuto()
|
21 |
+
|
22 |
+
def sanitize_filename(filename):
|
23 |
+
sanitized = re.sub(r'[^a-zA-Z0-9_-]', '_', filename)
|
24 |
+
sanitized = re.sub(r'_+', '_', sanitized)
|
25 |
+
sanitized = sanitized.strip('_')
|
26 |
+
return sanitized
|
27 |
|
28 |
def download_callback(url, download_type='direct', cookie_file=None):
|
29 |
+
# Clear temporary and input directories
|
30 |
clear_temp_folder("/tmp", exclude_items=["gradio", "config.json"])
|
31 |
clear_directory(INPUT_DIR)
|
32 |
os.makedirs(INPUT_DIR, exist_ok=True)
|
33 |
|
34 |
+
# Validate URL
|
35 |
+
if not url or not isinstance(url, str) or not (url.startswith('http://') or url.startswith('https://')):
|
36 |
+
return None, i18n("invalid_url"), None, None, None, None
|
37 |
|
38 |
+
# Load cookie file
|
39 |
if cookie_file is not None:
|
40 |
try:
|
41 |
with open(cookie_file.name, "rb") as f:
|
42 |
cookie_content = f.read()
|
43 |
with open(COOKIE_PATH, "wb") as f:
|
44 |
f.write(cookie_content)
|
45 |
+
print(i18n("cookie_file_updated"))
|
46 |
except Exception as e:
|
47 |
+
print(i18n("cookie_installation_error").format(str(e)))
|
48 |
|
49 |
wav_path = None
|
50 |
download_success = False
|
51 |
+
drive_mounted = False
|
52 |
+
|
53 |
+
# Mount Google Drive (optional)
|
54 |
+
if drive is not None:
|
55 |
+
try:
|
56 |
+
drive.mount('/content/drive', force_remount=True)
|
57 |
+
drive_mounted = True
|
58 |
+
except Exception as e:
|
59 |
+
print(i18n("google_drive_mount_error").format(str(e)))
|
60 |
+
print(i18n("continuing_without_google_drive"))
|
61 |
|
62 |
+
# 1. Direct file links
|
63 |
+
if any(url.endswith(ext) for ext in ['.wav', '.mp3', '.m4a', '.ogg', '.flac']):
|
64 |
try:
|
65 |
+
file_name = os.path.basename(url.split('?')[0])
|
66 |
+
sanitized_base_name = sanitize_filename(os.path.splitext(file_name)[0])
|
67 |
+
output_path = os.path.join(INPUT_DIR, f"{sanitized_base_name}{os.path.splitext(file_name)[1]}")
|
68 |
+
response = requests.get(url, stream=True)
|
69 |
+
if response.status_code == 200:
|
70 |
+
with open(output_path, 'wb') as f:
|
71 |
+
for chunk in response.iter_content(chunk_size=8192):
|
72 |
+
if chunk:
|
73 |
+
f.write(chunk)
|
74 |
+
if not file_name.endswith('.wav'):
|
75 |
+
wav_output = os.path.splitext(output_path)[0] + '.wav'
|
76 |
+
os.system(f'ffmpeg -i "{output_path}" -acodec pcm_s16le -ar 44100 "{wav_output}"')
|
77 |
+
if os.path.exists(wav_output):
|
78 |
+
os.remove(output_path)
|
79 |
+
output_path = wav_output
|
80 |
+
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
81 |
+
wav_path = output_path
|
82 |
+
download_success = True
|
83 |
+
else:
|
84 |
+
raise Exception(i18n("file_size_zero_error"))
|
85 |
+
else:
|
86 |
+
raise Exception(i18n("direct_download_failed"))
|
87 |
+
except Exception as e:
|
88 |
+
error_msg = i18n("direct_download_error").format(str(e))
|
89 |
+
print(error_msg)
|
90 |
+
return None, error_msg, None, None, None, None
|
91 |
+
|
92 |
+
# 2. Google Drive links
|
93 |
+
elif 'drive.google.com' in url:
|
94 |
+
try:
|
95 |
+
file_id = re.search(r'/d/([^/]+)', url) or re.search(r'id=([^&]+)', url)
|
96 |
+
if not file_id:
|
97 |
+
raise ValueError(i18n("invalid_google_drive_url"))
|
98 |
+
file_id = file_id.group(1)
|
99 |
output_path = os.path.join(INPUT_DIR, "drive_download.wav")
|
100 |
gdown.download(f'https://drive.google.com/uc?id={file_id}', output_path, quiet=True)
|
101 |
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
102 |
+
sanitized_base_name = sanitize_filename("drive_download")
|
103 |
+
sanitized_output_path = os.path.join(INPUT_DIR, f"{sanitized_base_name}.wav")
|
104 |
+
os.rename(output_path, sanitized_output_path)
|
105 |
+
wav_path = sanitized_output_path
|
106 |
download_success = True
|
107 |
else:
|
108 |
+
raise Exception(i18n("file_size_zero_error"))
|
109 |
except Exception as e:
|
110 |
+
error_msg = i18n("google_drive_error").format(str(e))
|
111 |
print(error_msg)
|
112 |
return None, error_msg, None, None, None, None
|
113 |
+
|
114 |
+
# 3. YouTube and other media links
|
115 |
else:
|
116 |
ydl_opts = {
|
117 |
'format': 'bestaudio/best',
|
|
|
130 |
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
131 |
info_dict = ydl.extract_info(url, download=True)
|
132 |
temp_path = ydl.prepare_filename(info_dict)
|
133 |
+
base_name = os.path.splitext(os.path.basename(temp_path))[0]
|
134 |
+
sanitized_base_name = sanitize_filename(base_name)
|
135 |
+
wav_path = os.path.join(INPUT_DIR, f"{sanitized_base_name}.wav")
|
136 |
+
temp_wav = os.path.splitext(temp_path)[0] + '.wav'
|
137 |
+
if os.path.exists(temp_wav):
|
138 |
+
os.rename(temp_wav, wav_path)
|
139 |
download_success = True
|
140 |
else:
|
141 |
+
raise Exception(i18n("wav_conversion_failed"))
|
142 |
except Exception as e:
|
143 |
+
error_msg = i18n("download_error").format(str(e))
|
144 |
print(error_msg)
|
145 |
return None, error_msg, None, None, None, None
|
146 |
|
147 |
+
# Post-download processing
|
148 |
if download_success and wav_path:
|
149 |
for f in os.listdir(INPUT_DIR):
|
150 |
if f != os.path.basename(wav_path):
|
151 |
os.remove(os.path.join(INPUT_DIR, f))
|
152 |
+
|
153 |
+
if drive_mounted:
|
154 |
+
try:
|
155 |
+
drive_path = os.path.join('/content/drive/My Drive', os.path.basename(wav_path))
|
156 |
+
shutil.copy(wav_path, drive_path)
|
157 |
+
print(i18n("file_copied_to_drive").format(drive_path))
|
158 |
+
except Exception as e:
|
159 |
+
print(i18n("copy_to_drive_error").format(str(e)))
|
160 |
+
else:
|
161 |
+
print(i18n("skipping_drive_copy_no_mount"))
|
162 |
+
|
163 |
return (
|
164 |
wav_path,
|
165 |
+
i18n("download_success"),
|
166 |
wav_path,
|
167 |
wav_path,
|
168 |
wav_path,
|
169 |
wav_path
|
170 |
)
|
171 |
+
|
172 |
+
return None, i18n("download_failed"), None, None, None, None
|
ensemble.py
CHANGED
@@ -1,164 +1,386 @@
|
|
|
|
1 |
# coding: utf-8
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
import os
|
5 |
-
import
|
6 |
-
import soundfile as sf
|
7 |
-
import numpy as np
|
8 |
import argparse
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
indices.insert(insert_pos, argmax)
|
36 |
-
return a[tuple(indices)]
|
37 |
-
|
38 |
-
|
39 |
-
def absmin(a, *, axis):
|
40 |
-
dims = list(a.shape)
|
41 |
-
dims.pop(axis)
|
42 |
-
indices = list(np.ogrid[tuple(slice(0, d) for d in dims)]) # Tuple yerine list
|
43 |
-
argmax = np.abs(a).argmin(axis=axis)
|
44 |
-
insert_pos = (len(a.shape) + axis) % len(a.shape)
|
45 |
-
indices.insert(insert_pos, argmax)
|
46 |
-
return a[tuple(indices)]
|
47 |
-
|
48 |
-
|
49 |
-
def lambda_max(arr, axis=None, key=None, keepdims=False):
|
50 |
-
idxs = np.argmax(key(arr), axis)
|
51 |
-
if axis is not None:
|
52 |
-
idxs = np.expand_dims(idxs, axis)
|
53 |
-
result = np.take_along_axis(arr, idxs, axis)
|
54 |
-
if not keepdims:
|
55 |
-
result = np.squeeze(result, axis=axis)
|
56 |
-
return result
|
57 |
-
else:
|
58 |
-
return arr.flatten()[idxs]
|
59 |
-
|
60 |
-
|
61 |
-
def lambda_min(arr, axis=None, key=None, keepdims=False):
|
62 |
-
idxs = np.argmin(key(arr), axis)
|
63 |
-
if axis is not None:
|
64 |
-
idxs = np.expand_dims(idxs, axis)
|
65 |
-
result = np.take_along_axis(arr, idxs, axis)
|
66 |
-
if not keepdims:
|
67 |
-
result = np.squeeze(result, axis=axis)
|
68 |
-
return result
|
69 |
-
else:
|
70 |
-
return arr.flatten()[idxs]
|
71 |
-
|
72 |
-
|
73 |
-
def average_waveforms(pred_track, weights, algorithm):
|
74 |
-
"""
|
75 |
-
:param pred_track: shape = (num, channels, length)
|
76 |
-
:param weights: shape = (num, )
|
77 |
-
:param algorithm: One of avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft
|
78 |
-
:return: averaged waveform in shape (channels, length)
|
79 |
-
"""
|
80 |
-
|
81 |
-
pred_track = np.array(pred_track)
|
82 |
-
final_length = pred_track.shape[-1]
|
83 |
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
else:
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
|
163 |
if __name__ == "__main__":
|
164 |
-
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
# coding: utf-8
|
3 |
+
"""
|
4 |
+
Ultimate Audio Ensemble Processor v4.0
|
5 |
+
- Tüm ensemble yöntemlerini destekler (avg_wave, median_wave, max_wave, min_wave, max_fft, min_fft, median_fft)
|
6 |
+
- Özel karakterli ve uzun dosya yollarını destekler
|
7 |
+
- Büyük dosyaları verimli şekilde işler
|
8 |
+
- Detaylı hata yönetimi ve loglama
|
9 |
+
"""
|
10 |
|
11 |
import os
|
12 |
+
import sys
|
|
|
|
|
13 |
import argparse
|
14 |
+
import numpy as np
|
15 |
+
import soundfile as sf
|
16 |
+
import librosa
|
17 |
+
import psutil
|
18 |
+
import gc
|
19 |
+
import traceback
|
20 |
+
from scipy.signal import stft, istft
|
21 |
+
from pathlib import Path
|
22 |
+
import tempfile
|
23 |
+
import shutil
|
24 |
+
import json
|
25 |
+
from tqdm import tqdm
|
26 |
+
import time
|
27 |
|
28 |
+
class AudioEnsembleEngine:
|
29 |
+
def __init__(self):
|
30 |
+
self.temp_dir = None
|
31 |
+
self.log_file = "ensemble_processor.log"
|
32 |
+
|
33 |
+
def __enter__(self):
|
34 |
+
self.temp_dir = tempfile.mkdtemp(prefix='audio_ensemble_')
|
35 |
+
self.setup_logging()
|
36 |
+
return self
|
37 |
+
|
38 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
39 |
+
if self.temp_dir and os.path.exists(self.temp_dir):
|
40 |
+
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
41 |
+
|
42 |
+
def setup_logging(self):
|
43 |
+
"""Initialize detailed logging system."""
|
44 |
+
with open(self.log_file, 'w') as f:
|
45 |
+
f.write("Audio Ensemble Processor Log\n")
|
46 |
+
f.write("="*50 + "\n")
|
47 |
+
f.write(f"System Memory: {psutil.virtual_memory().total/(1024**3):.2f} GB\n")
|
48 |
+
f.write(f"Python Version: {sys.version}\n\n")
|
49 |
+
|
50 |
+
def log_message(self, message):
|
51 |
+
"""Log messages with timestamp."""
|
52 |
+
with open(self.log_file, 'a') as f:
|
53 |
+
f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {message}\n")
|
54 |
+
|
55 |
+
def normalize_path(self, path):
|
56 |
+
"""Handle all path-related issues comprehensively."""
|
57 |
+
try:
|
58 |
+
# Convert to absolute path
|
59 |
+
path = str(Path(path).absolute().resolve())
|
60 |
+
|
61 |
+
# Handle problematic characters
|
62 |
+
if any(char in path for char in '[]()|&; '):
|
63 |
+
base, ext = os.path.splitext(path)
|
64 |
+
safe_name = f"{hash(base)}{ext}"
|
65 |
+
temp_path = os.path.join(self.temp_dir, safe_name)
|
66 |
+
|
67 |
+
if not os.path.exists(temp_path):
|
68 |
+
data, sr = librosa.load(path, sr=None, mono=False)
|
69 |
+
sf.write(temp_path, data.T, sr)
|
70 |
+
|
71 |
+
return temp_path
|
72 |
+
|
73 |
+
return path
|
74 |
+
except Exception as e:
|
75 |
+
self.log_message(f"Path normalization failed: {str(e)}")
|
76 |
+
return path
|
77 |
+
|
78 |
+
def validate_inputs(self, files, method, output_path):
|
79 |
+
"""Comprehensive input validation with detailed error reporting."""
|
80 |
+
errors = []
|
81 |
+
valid_methods = [
|
82 |
+
'avg_wave', 'median_wave', 'max_wave', 'min_wave',
|
83 |
+
'max_fft', 'min_fft', 'median_fft'
|
84 |
+
]
|
85 |
+
|
86 |
+
# Method validation
|
87 |
+
if method not in valid_methods:
|
88 |
+
errors.append(f"Invalid method '{method}'. Available: {valid_methods}")
|
89 |
+
|
90 |
+
# File validation
|
91 |
+
valid_files = []
|
92 |
+
sample_rates = set()
|
93 |
+
durations = []
|
94 |
+
channels_set = set()
|
95 |
+
|
96 |
+
for f in files:
|
97 |
+
try:
|
98 |
+
f_normalized = self.normalize_path(f)
|
99 |
+
|
100 |
+
# Basic checks
|
101 |
+
if not os.path.exists(f_normalized):
|
102 |
+
errors.append(f"File not found: {f_normalized}")
|
103 |
+
continue
|
104 |
+
|
105 |
+
if os.path.getsize(f_normalized) == 0:
|
106 |
+
errors.append(f"Empty file: {f_normalized}")
|
107 |
+
continue
|
108 |
+
|
109 |
+
# Audio file validation
|
110 |
+
try:
|
111 |
+
with sf.SoundFile(f_normalized) as sf_file:
|
112 |
+
sr = sf_file.samplerate
|
113 |
+
frames = sf_file.frames
|
114 |
+
channels = sf_file.channels
|
115 |
+
except Exception as e:
|
116 |
+
errors.append(f"Invalid audio file {f_normalized}: {str(e)}")
|
117 |
+
continue
|
118 |
+
|
119 |
+
# Audio characteristics
|
120 |
+
if channels != 2:
|
121 |
+
errors.append(f"File must be stereo (has {channels} channels): {f_normalized}")
|
122 |
+
continue
|
123 |
+
|
124 |
+
sample_rates.add(sr)
|
125 |
+
durations.append(frames / sr)
|
126 |
+
channels_set.add(channels)
|
127 |
+
valid_files.append(f_normalized)
|
128 |
+
|
129 |
+
except Exception as e:
|
130 |
+
errors.append(f"Error processing {f}: {str(e)}")
|
131 |
+
continue
|
132 |
+
|
133 |
+
# Final checks
|
134 |
+
if len(valid_files) < 2:
|
135 |
+
errors.append("At least 2 valid files required")
|
136 |
+
|
137 |
+
if len(sample_rates) > 1:
|
138 |
+
errors.append(f"Sample rate mismatch: {sample_rates}")
|
139 |
+
|
140 |
+
if len(channels_set) > 1:
|
141 |
+
errors.append(f"Channel count mismatch: {channels_set}")
|
142 |
+
|
143 |
+
# Output path validation
|
144 |
+
try:
|
145 |
+
output_path = self.normalize_path(output_path)
|
146 |
+
output_dir = os.path.dirname(output_path) or '.'
|
147 |
+
|
148 |
+
if not os.path.exists(output_dir):
|
149 |
+
os.makedirs(output_dir, exist_ok=True)
|
150 |
+
|
151 |
+
if not os.access(output_dir, os.W_OK):
|
152 |
+
errors.append(f"No write permission for output directory: {output_dir}")
|
153 |
+
except Exception as e:
|
154 |
+
errors.append(f"Output path error: {str(e)}")
|
155 |
+
|
156 |
+
if errors:
|
157 |
+
error_msg = "\n".join(errors)
|
158 |
+
self.log_message(f"Validation failed:\n{error_msg}")
|
159 |
+
raise ValueError(error_msg)
|
160 |
+
|
161 |
+
target_sr = sample_rates.pop() if sample_rates else 44100
|
162 |
+
return valid_files, target_sr, min(durations) if durations else None
|
163 |
+
|
164 |
+
def process_waveform(self, chunks, method, weights=None):
|
165 |
+
"""All waveform domain processing methods."""
|
166 |
+
if method == 'avg_wave':
|
167 |
+
if weights is not None:
|
168 |
+
return np.average(chunks, axis=0, weights=weights)
|
169 |
+
return np.mean(chunks, axis=0)
|
170 |
+
elif method == 'median_wave':
|
171 |
+
return np.median(chunks, axis=0)
|
172 |
+
elif method == 'max_wave':
|
173 |
+
return np.max(chunks, axis=0)
|
174 |
+
elif method == 'min_wave':
|
175 |
+
return np.min(chunks, axis=0)
|
176 |
+
|
177 |
+
def process_spectral(self, chunks, method):
|
178 |
+
"""All frequency domain processing methods."""
|
179 |
+
specs = []
|
180 |
+
min_samples = min(chunk.shape[1] for chunk in chunks)
|
181 |
+
nperseg = min(1024, min_samples) # Adjust nperseg to fit shortest chunk
|
182 |
+
noverlap = nperseg // 2
|
183 |
+
self.log_message(f"STFT parameters: nperseg={nperseg}, noverlap={noverlap}, min_samples={min_samples}")
|
184 |
|
185 |
+
for c in chunks:
|
186 |
+
# Truncate chunk to minimum length to ensure consistent STFT shapes
|
187 |
+
c = c[:, :min_samples]
|
188 |
+
channel_specs = []
|
189 |
+
for channel in range(c.shape[0]):
|
190 |
+
if c.shape[1] < 256: # Minimum reasonable length for STFT
|
191 |
+
self.log_message(f"Warning: Chunk too short ({c.shape[1]} samples) for STFT. Skipping.")
|
192 |
+
return None
|
193 |
+
try:
|
194 |
+
freqs, times, Zxx = stft(
|
195 |
+
c[channel],
|
196 |
+
nperseg=nperseg,
|
197 |
+
noverlap=noverlap,
|
198 |
+
window='hann'
|
199 |
+
)
|
200 |
+
channel_specs.append(Zxx)
|
201 |
+
except Exception as e:
|
202 |
+
self.log_message(f"STFT failed for channel: {str(e)}")
|
203 |
+
return None
|
204 |
+
specs.append(np.array(channel_specs))
|
205 |
+
|
206 |
+
if not specs:
|
207 |
+
self.log_message("No valid STFTs computed.")
|
208 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
+
specs = np.array(specs)
|
211 |
+
self.log_message(f"STFT shapes: {[spec.shape for spec in specs]}")
|
212 |
+
|
213 |
+
# Ensure all STFTs have the same shape
|
214 |
+
min_freqs = min(spec.shape[1] for spec in specs)
|
215 |
+
min_times = min(spec.shape[2] for spec in specs)
|
216 |
+
specs = np.array([spec[:, :min_freqs, :min_times] for spec in specs])
|
217 |
+
|
218 |
+
mag = np.abs(specs)
|
219 |
+
|
220 |
+
if method == 'max_fft':
|
221 |
+
combined_mag = np.max(mag, axis=0)
|
222 |
+
elif method == 'min_fft':
|
223 |
+
combined_mag = np.min(mag, axis=0)
|
224 |
+
elif method == 'median_fft':
|
225 |
+
combined_mag = np.median(mag, axis=0)
|
226 |
+
|
227 |
+
# Use phase from first file
|
228 |
+
combined_spec = combined_mag * np.exp(1j * np.angle(specs[0]))
|
229 |
+
|
230 |
+
# ISTFT reconstruction
|
231 |
+
reconstructed = np.zeros((combined_spec.shape[0], chunks[0].shape[1]))
|
232 |
+
for channel in range(combined_spec.shape[0]):
|
233 |
+
try:
|
234 |
+
_, xrec = istft(
|
235 |
+
combined_spec[channel],
|
236 |
+
nperseg=nperseg,
|
237 |
+
noverlap=noverlap,
|
238 |
+
window='hann'
|
239 |
+
)
|
240 |
+
# Truncate or pad to match original chunk length
|
241 |
+
if xrec.shape[0] < chunks[0].shape[1]:
|
242 |
+
xrec = np.pad(xrec, (0, chunks[0].shape[1] - xrec.shape[0]), mode='constant')
|
243 |
+
reconstructed[channel] = xrec[:chunks[0].shape[1]]
|
244 |
+
except Exception as e:
|
245 |
+
self.log_message(f"ISTFT failed for channel: {str(e)}")
|
246 |
+
return None
|
247 |
+
|
248 |
+
return reconstructed
|
249 |
+
|
250 |
+
def run_ensemble(self, files, method, output_path, weights=None, buffer_size=32768):
|
251 |
+
"""Core ensemble processing with maximum robustness."""
|
252 |
+
try:
|
253 |
+
# Validate and prepare inputs
|
254 |
+
valid_files, target_sr, duration = self.validate_inputs(files, method, output_path)
|
255 |
+
output_path = self.normalize_path(output_path)
|
256 |
+
|
257 |
+
self.log_message(f"Starting ensemble with method: {method}")
|
258 |
+
self.log_message(f"Input files: {json.dumps(valid_files, indent=2)}")
|
259 |
+
self.log_message(f"Target sample rate: {target_sr}Hz")
|
260 |
+
self.log_message(f"Output path: {output_path}")
|
261 |
+
|
262 |
+
# Ensure output directory exists
|
263 |
+
output_dir = os.path.dirname(output_path) or '.'
|
264 |
+
os.makedirs(output_dir, exist_ok=True)
|
265 |
+
self.log_message(f"Output directory created/verified: {output_dir}")
|
266 |
+
|
267 |
+
# Verify write permissions
|
268 |
+
try:
|
269 |
+
test_file = os.path.join(output_dir, "test_write.txt")
|
270 |
+
with open(test_file, "w") as f:
|
271 |
+
f.write("Test")
|
272 |
+
os.remove(test_file)
|
273 |
+
self.log_message(f"Write permissions verified for: {output_dir}")
|
274 |
+
except Exception as e:
|
275 |
+
self.log_message(f"Write permission error for {output_dir}: {str(e)}")
|
276 |
+
raise ValueError(f"Cannot write to output directory {output_dir}: {str(e)}")
|
277 |
+
|
278 |
+
# Prepare weights
|
279 |
+
if weights and len(weights) == len(valid_files):
|
280 |
+
weights = np.array(weights, dtype=np.float32)
|
281 |
+
weights /= weights.sum() # Normalize
|
282 |
+
self.log_message(f"Using weights: {weights}")
|
283 |
else:
|
284 |
+
weights = None
|
285 |
+
|
286 |
+
# Open all files
|
287 |
+
readers = []
|
288 |
+
try:
|
289 |
+
readers = [sf.SoundFile(f) for f in valid_files]
|
290 |
+
shortest_frames = min(int(duration * r.samplerate) for r in readers)
|
291 |
+
|
292 |
+
# Prepare output
|
293 |
+
self.log_message(f"Opening output file for writing: {output_path}")
|
294 |
+
with sf.SoundFile(output_path, 'w', target_sr, 2, 'PCM_24') as outfile:
|
295 |
+
# Process in chunks with progress bar
|
296 |
+
progress = tqdm(total=shortest_frames, unit='samples', desc='Processing')
|
297 |
+
|
298 |
+
for pos in range(0, shortest_frames, buffer_size):
|
299 |
+
chunk_size = min(buffer_size, shortest_frames - pos)
|
300 |
+
|
301 |
+
# Read aligned chunks from all files
|
302 |
+
chunks = []
|
303 |
+
for r in readers:
|
304 |
+
r.seek(pos)
|
305 |
+
data = r.read(chunk_size)
|
306 |
+
if data.size == 0:
|
307 |
+
data = np.zeros((chunk_size, 2))
|
308 |
+
chunks.append(data.T) # Transpose to (channels, samples)
|
309 |
+
|
310 |
+
chunks = np.array(chunks)
|
311 |
+
self.log_message(f"Chunk shape: {chunks.shape}, pos={pos}")
|
312 |
+
|
313 |
+
# Process based on method type
|
314 |
+
if method.endswith('_fft'):
|
315 |
+
result = self.process_spectral(chunks, method)
|
316 |
+
if result is None:
|
317 |
+
self.log_message("Spectral processing failed, falling back to avg_wave")
|
318 |
+
result = self.process_waveform(chunks, 'avg_wave', weights)
|
319 |
+
else:
|
320 |
+
result = self.process_waveform(chunks, method, weights)
|
321 |
+
|
322 |
+
# Write output
|
323 |
+
outfile.write(result.T) # Transpose back to (samples, channels)
|
324 |
+
|
325 |
+
# Clean up and update progress
|
326 |
+
del chunks, result
|
327 |
+
if pos % (5 * buffer_size) == 0:
|
328 |
+
gc.collect()
|
329 |
+
|
330 |
+
progress.update(chunk_size)
|
331 |
+
|
332 |
+
progress.close()
|
333 |
+
|
334 |
+
self.log_message(f"Successfully created output: {output_path}")
|
335 |
+
print(f"\nEnsemble completed successfully: {output_path}")
|
336 |
+
return True
|
337 |
+
|
338 |
+
except Exception as e:
|
339 |
+
self.log_message(f"Processing error: {str(e)}\n{traceback.format_exc()}")
|
340 |
+
raise
|
341 |
+
finally:
|
342 |
+
for r in readers:
|
343 |
+
try:
|
344 |
+
r.close()
|
345 |
+
except:
|
346 |
+
pass
|
347 |
+
|
348 |
+
except Exception as e:
|
349 |
+
self.log_message(f"Fatal error: {str(e)}\n{traceback.format_exc()}")
|
350 |
+
print(f"\nError during processing: {str(e)}", file=sys.stderr)
|
351 |
+
return False
|
352 |
|
353 |
+
def main():
|
354 |
+
parser = argparse.ArgumentParser(
|
355 |
+
description='Ultimate Audio Ensemble Processor - Supports all ensemble methods',
|
356 |
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter
|
357 |
+
)
|
358 |
+
parser.add_argument('--files', nargs='+', required=True,
|
359 |
+
help='Input audio files (supports special characters)')
|
360 |
+
parser.add_argument('--type', required=True,
|
361 |
+
choices=['avg_wave', 'median_wave', 'max_wave', 'min_wave',
|
362 |
+
'max_fft', 'min_fft', 'median_fft'],
|
363 |
+
help='Ensemble method to use')
|
364 |
+
parser.add_argument('--weights', nargs='+', type=float,
|
365 |
+
help='Relative weights for each input file')
|
366 |
+
parser.add_argument('--output', required=True,
|
367 |
+
help='Output file path')
|
368 |
+
parser.add_argument('--buffer', type=int, default=32768,
|
369 |
+
help='Buffer size in samples (larger=faster but uses more memory)')
|
370 |
+
|
371 |
+
args = parser.parse_args()
|
372 |
+
|
373 |
+
with AudioEnsembleEngine() as engine:
|
374 |
+
success = engine.run_ensemble(
|
375 |
+
files=args.files,
|
376 |
+
method=args.type,
|
377 |
+
output_path=args.output,
|
378 |
+
weights=args.weights,
|
379 |
+
buffer_size=args.buffer
|
380 |
+
)
|
381 |
+
|
382 |
+
sys.exit(0 if success else 1)
|
383 |
|
384 |
if __name__ == "__main__":
|
385 |
+
import time
|
386 |
+
main()
|
gui.py
CHANGED
@@ -4,128 +4,140 @@ import glob
|
|
4 |
import subprocess
|
5 |
from pathlib import Path
|
6 |
from datetime import datetime
|
7 |
-
|
|
|
|
|
|
|
|
|
8 |
from download import download_callback
|
9 |
from model import get_model_config, MODEL_CONFIGS
|
10 |
-
from processing import process_audio, auto_ensemble_process, ensemble_audio_fn
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
# BASE_DIR tanımı
|
13 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
# Arayüz oluşturma fonksiyonu
|
16 |
def create_interface():
|
17 |
-
# CSS tanımı
|
18 |
css = """
|
19 |
-
/* Genel Tema */
|
20 |
body {
|
21 |
-
background: url('/content/logo.jpg') no-repeat center center fixed;
|
22 |
background-size: cover;
|
23 |
-
background-color: #2d0b0b; /* Koyu kırmızı, dublaj stüdyosuna uygun */
|
24 |
min-height: 100vh;
|
25 |
margin: 0;
|
26 |
padding: 1rem;
|
27 |
font-family: 'Poppins', sans-serif;
|
28 |
-
color: #C0C0C0;
|
29 |
-
|
30 |
-
|
31 |
-
body::after {
|
32 |
-
content: '';
|
33 |
-
position: fixed;
|
34 |
-
top: 0;
|
35 |
-
left: 0;
|
36 |
-
width: 100%;
|
37 |
-
height: 100%;
|
38 |
-
background: rgba(45, 11, 11, 0.9); /* Daha koyu kırmızı overlay */
|
39 |
-
z-index: -1;
|
40 |
}
|
41 |
-
|
42 |
-
/* Logo Stilleri */
|
43 |
-
.logo-container {
|
44 |
-
position: absolute;
|
45 |
-
top: 1rem;
|
46 |
-
left: 50%;
|
47 |
-
transform: translateX(-50%);
|
48 |
-
display: flex;
|
49 |
-
align-items: center;
|
50 |
-
z-index: 2000; /* Diğer öğelerden üstte, mutlaka görünür */
|
51 |
-
}
|
52 |
-
|
53 |
-
.logo-img {
|
54 |
-
width: 120px;
|
55 |
-
height: auto;
|
56 |
-
}
|
57 |
-
|
58 |
-
/* Başlık Stilleri */
|
59 |
.header-text {
|
60 |
text-align: center;
|
61 |
-
padding:
|
62 |
-
color: #ff4040;
|
63 |
-
font-size:
|
64 |
-
font-weight: 900;
|
65 |
-
text-shadow: 0 0 10px rgba(255, 64, 64, 0.5);
|
66 |
-
z-index: 1500;
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
@keyframes metallic-red-shine {
|
71 |
-
0% { filter: brightness(1) saturate(1) drop-shadow(0 0 5px #ff4040); }
|
72 |
-
50% { filter: brightness(1.3) saturate(1.7) drop-shadow(0 0 15px #ff6b6b); }
|
73 |
-
100% { filter: brightness(1) saturate(1) drop-shadow(0 0 5px #ff4040); }
|
74 |
-
}
|
75 |
-
|
76 |
-
/* Dublaj temalı stil */
|
77 |
-
.dubbing-theme {
|
78 |
-
background: linear-gradient(to bottom, #800000, #2d0b0b); /* Koyu kırmızı gradyan */
|
79 |
-
border-radius: 15px;
|
80 |
-
padding: 1rem;
|
81 |
-
box-shadow: 0 10px 20px rgba(255, 64, 64, 0.3); /* Kırmızı gölge */
|
82 |
-
}
|
83 |
-
|
84 |
-
/* Footer Stilleri (Tablerin Üstünde, Şeffaf) */
|
85 |
-
.footer {
|
86 |
text-align: center;
|
87 |
-
|
88 |
-
|
89 |
-
font-
|
90 |
-
margin-top:
|
91 |
-
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
}
|
94 |
-
|
95 |
-
/* Düğme ve Yükleme Alanı Stilleri */
|
96 |
button {
|
97 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
98 |
-
background: #800000 !important;
|
99 |
-
border: 1px solid #ff4040 !important;
|
100 |
-
color: #C0C0C0 !important;
|
101 |
border-radius: 8px !important;
|
102 |
padding: 8px 16px !important;
|
103 |
-
|
104 |
-
overflow: hidden !important;
|
105 |
-
font-size: 0.9rem !important;
|
106 |
}
|
107 |
-
|
108 |
button:hover {
|
109 |
transform: scale(1.05) !important;
|
110 |
-
box-shadow: 0 10px 40px rgba(255, 64, 64, 0.7) !important;
|
111 |
-
background: #ff4040 !important;
|
112 |
-
}
|
113 |
-
|
114 |
-
button::before {
|
115 |
-
content: '';
|
116 |
-
position: absolute;
|
117 |
-
top: -50%;
|
118 |
-
left: -50%;
|
119 |
-
width: 200%;
|
120 |
-
height: 200%;
|
121 |
-
background: linear-gradient(45deg,
|
122 |
-
transparent 20%,
|
123 |
-
rgba(192, 192, 192, 0.3) 50%, /* Metalik gümüş ton */
|
124 |
-
transparent 80%);
|
125 |
-
animation: button-shine 3s infinite linear;
|
126 |
}
|
127 |
-
|
128 |
-
/* Resim ve Ses Yükleme Alanı Stili */
|
129 |
.compact-upload.horizontal {
|
130 |
display: inline-flex !important;
|
131 |
align-items: center !important;
|
@@ -133,620 +145,751 @@ def create_interface():
|
|
133 |
max-width: 400px !important;
|
134 |
height: 40px !important;
|
135 |
padding: 0 12px !important;
|
136 |
-
border: 1px solid #ff4040 !important;
|
137 |
-
background: rgba(128, 0, 0, 0.5) !important;
|
138 |
border-radius: 8px !important;
|
139 |
-
transition: all 0.2s ease !important;
|
140 |
-
color: #C0C0C0 !important; /* Metalik gümüş metin */
|
141 |
-
}
|
142 |
-
|
143 |
-
.compact-upload.horizontal:hover {
|
144 |
-
border-color: #ff6b6b !important; /* Daha açık kırmızı */
|
145 |
-
background: rgba(128, 0, 0, 0.7) !important; /* Daha koyu kırmızı hover */
|
146 |
-
}
|
147 |
-
|
148 |
-
.compact-upload.horizontal .w-full {
|
149 |
-
flex: 1 1 auto !important;
|
150 |
-
min-width: 120px !important;
|
151 |
-
margin: 0 !important;
|
152 |
-
color: #C0C0C0 !important; /* Metalik gümüş */
|
153 |
-
}
|
154 |
-
|
155 |
-
.compact-upload.horizontal button {
|
156 |
-
padding: 4px 12px !important;
|
157 |
-
font-size: 0.75em !important;
|
158 |
-
height: 28px !important;
|
159 |
-
min-width: 80px !important;
|
160 |
-
border-radius: 4px !important;
|
161 |
-
background: #800000 !important; /* Koyu kırmızı */
|
162 |
-
border: 1px solid #ff4040 !important; /* Kırmızı sınır */
|
163 |
-
color: #C0C0C0 !important; /* Metalik gümüş */
|
164 |
-
}
|
165 |
-
|
166 |
-
.compact-upload.horizontal .text-gray-500 {
|
167 |
-
font-size: 0.7em !important;
|
168 |
-
color: rgba(192, 192, 192, 0.6) !important; /* Şeffaf metalik gümüş */
|
169 |
-
white-space: nowrap !important;
|
170 |
-
overflow: hidden !important;
|
171 |
-
text-overflow: ellipsis !important;
|
172 |
-
max-width: 180px !important;
|
173 |
-
}
|
174 |
-
|
175 |
-
/* Ekstra Dar Versiyon */
|
176 |
-
.compact-upload.horizontal.x-narrow {
|
177 |
-
max-width: 320px !important;
|
178 |
-
height: 36px !important;
|
179 |
-
padding: 0 10px !important;
|
180 |
-
gap: 6px !important;
|
181 |
}
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
}
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
|
|
|
|
193 |
}
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
color: #C0C0C0 !important; /* Metalik gümüş */
|
201 |
-
border: 1px solid #ff4040 !important; /* Kırmızı sınır */
|
202 |
-
z-index: 1500; /* Logo’nun altında, diğer öğelerden üstte */
|
203 |
}
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
color: #ffffff !important; /* Beyaz metin (seçili sekme için kontrast) */
|
209 |
-
border: 1px solid #ff6b6b !important; /* Daha açık kırmızı */
|
210 |
}
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
|
|
|
|
217 |
}
|
218 |
-
|
219 |
-
|
220 |
-
gap: 0.4rem !important;
|
221 |
-
max-height: 50vh;
|
222 |
overflow-y: auto;
|
|
|
223 |
padding: 10px;
|
224 |
-
background: rgba(128, 0, 0, 0.3) !important; /* Koyu kırmızı, şeffaf */
|
225 |
-
border-radius: 12px;
|
226 |
-
border: 1px solid #ff4040 !important; /* Kırmızı sınır */
|
227 |
-
}
|
228 |
-
|
229 |
-
.compact-dropdown {
|
230 |
-
--padding: 8px 12px !important;
|
231 |
-
--radius: 10px !important;
|
232 |
-
border: 1px solid #ff4040 !important; /* Kırmızı sınır */
|
233 |
-
background: rgba(128, 0, 0, 0.5) !important; /* Koyu kırmızı, şeffaf */
|
234 |
-
color: #C0C0C0 !important; /* Metalik gümüş metin */
|
235 |
-
}
|
236 |
-
|
237 |
-
.tooltip-icon {
|
238 |
-
font-size: 1.4em !important;
|
239 |
-
color: #C0C0C0 !important; /* Metalik gümüş */
|
240 |
-
cursor: help;
|
241 |
-
margin-left: 0.5rem !important;
|
242 |
-
}
|
243 |
-
|
244 |
-
.log-box {
|
245 |
-
font-family: 'Fira Code', monospace !important;
|
246 |
-
font-size: 0.85em !important;
|
247 |
-
background-color: rgba(128, 0, 0, 0.3) !important; /* Koyu kırmızı, şeffaf */
|
248 |
-
border: 1px solid #ff4040 !important; /* Kırmızı sınır */
|
249 |
border-radius: 8px;
|
250 |
-
padding: 1rem !important;
|
251 |
-
color: #C0C0C0 !important; /* Metalik gümüş metin */
|
252 |
}
|
253 |
-
|
254 |
-
/* Animasyonlar */
|
255 |
@keyframes text-glow {
|
256 |
0% { text-shadow: 0 0 5px rgba(192, 192, 192, 0); }
|
257 |
50% { text-shadow: 0 0 15px rgba(192, 192, 192, 1); }
|
258 |
100% { text-shadow: 0 0 5px rgba(192, 192, 192, 0); }
|
259 |
}
|
260 |
-
|
261 |
-
@keyframes button-shine {
|
262 |
-
0% { transform: rotate(0deg) translateX(-50%); }
|
263 |
-
100% { transform: rotate(360deg) translateX(-50%); }
|
264 |
-
}
|
265 |
-
|
266 |
-
/* Responsive Ayarlar */
|
267 |
-
@media (max-width: 768px) {
|
268 |
-
.compact-grid {
|
269 |
-
max-height: 40vh;
|
270 |
-
}
|
271 |
-
|
272 |
-
.compact-upload.horizontal {
|
273 |
-
max-width: 100% !important;
|
274 |
-
width: 100% !important;
|
275 |
-
}
|
276 |
-
|
277 |
-
.compact-upload.horizontal .text-gray-500 {
|
278 |
-
max-width: 100px !important;
|
279 |
-
}
|
280 |
-
|
281 |
-
.compact-upload.horizontal.x-narrow {
|
282 |
-
height: 40px !important;
|
283 |
-
padding: 0 8px !important;
|
284 |
-
}
|
285 |
-
|
286 |
-
.logo-container {
|
287 |
-
width: 80px; /* Mobil cihazlarda daha küçük logo */
|
288 |
-
top: 1rem;
|
289 |
-
left: 50%;
|
290 |
-
transform: translateX(-50%);
|
291 |
-
}
|
292 |
-
|
293 |
-
.header-text {
|
294 |
-
padding: 60px 20px 20px; /* Mobil için daha az boşluk */
|
295 |
-
font-size: 1.8rem; /* Mobil için biraz daha küçük başlık */
|
296 |
-
}
|
297 |
-
}
|
298 |
-
|
299 |
-
/* Progress Bar Stilleri (Görseldeki tasarıma uygun) */
|
300 |
-
.gr-progress-bar {
|
301 |
-
background-color: #1a1a1a !important; /* Koyu arka plan */
|
302 |
-
border-radius: 5px !important;
|
303 |
-
border: 1px solid #333 !important; /* Hafif sınır */
|
304 |
-
height: 20px !important;
|
305 |
-
overflow: hidden !important;
|
306 |
-
position: relative !important;
|
307 |
-
}
|
308 |
-
.gr-progress-bar .progress {
|
309 |
-
background-color: #007bff !important; /* Mavi ilerleme çubuğu */
|
310 |
-
height: 100% !important;
|
311 |
-
border-radius: 5px !important;
|
312 |
-
transition: width 0.3s ease !important;
|
313 |
-
}
|
314 |
-
.gr-progress-bar .progress-text {
|
315 |
-
position: absolute !important;
|
316 |
-
top: 0 !important;
|
317 |
-
left: 0 !important;
|
318 |
-
width: 100% !important;
|
319 |
-
height: 100% !important;
|
320 |
-
display: flex !important;
|
321 |
-
align-items: center !important;
|
322 |
-
justify-content: center !important;
|
323 |
-
color: #ffffff !important; /* Beyaz metin */
|
324 |
-
font-size: 12px !important;
|
325 |
-
font-weight: bold !important;
|
326 |
-
text-shadow: 0 0 2px rgba(0, 0, 0, 0.5) !important; /* Hafif gölge */
|
327 |
-
}
|
328 |
-
.gr-progress-bar .progress-stats {
|
329 |
-
position: absolute !important;
|
330 |
-
bottom: -20px !important; /* Altında adım ve süre bilgisi */
|
331 |
-
left: 0 !important;
|
332 |
-
width: 100% !important;
|
333 |
-
text-align: center !important;
|
334 |
-
color: #007bff !important; /* Mavi metin */
|
335 |
-
font-size: 10px !important;
|
336 |
-
font-weight: normal !important;
|
337 |
-
}
|
338 |
"""
|
339 |
|
340 |
-
#
|
|
|
|
|
|
|
|
|
|
|
341 |
with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
|
|
|
|
348 |
"""
|
349 |
-
|
350 |
-
|
351 |
-
# Başlık (Etkileyici ve dublaj temalı)
|
352 |
-
gr.HTML("""
|
353 |
-
<div class="header-text">
|
354 |
-
Gecekondu Dubbing Production
|
355 |
-
</div>
|
356 |
-
""")
|
357 |
|
358 |
with gr.Tabs():
|
359 |
-
with gr.Tab("
|
360 |
with gr.Row(equal_height=True):
|
361 |
-
# Sol Panel - Kontroller
|
362 |
with gr.Column(scale=1, min_width=380):
|
363 |
-
with gr.Accordion("
|
364 |
with gr.Tabs():
|
365 |
-
with gr.Tab("
|
366 |
input_audio_file = gr.File(
|
367 |
file_types=[".wav", ".mp3", ".m4a", ".mp4", ".mkv", ".flac"],
|
368 |
elem_classes=["compact-upload", "horizontal", "x-narrow"],
|
369 |
label=""
|
370 |
)
|
371 |
-
|
372 |
-
|
373 |
-
file_path_input = gr.Textbox(placeholder="/path/to/audio.wav")
|
374 |
|
375 |
with gr.Row():
|
376 |
model_category = gr.Dropdown(
|
377 |
-
label="
|
378 |
-
choices=
|
379 |
-
value="
|
380 |
-
)
|
381 |
-
model_dropdown = gr.Dropdown(
|
382 |
-
label="Model",
|
383 |
-
choices=list(MODEL_CONFIGS["Vocal Models"].keys())
|
384 |
)
|
|
|
385 |
|
386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
with gr.Row():
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
|
|
|
|
399 |
|
400 |
with gr.Row():
|
401 |
-
|
402 |
-
|
403 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
|
405 |
with gr.Row():
|
406 |
-
|
407 |
-
|
408 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
409 |
|
410 |
with gr.Row():
|
411 |
-
process_btn = gr.Button("
|
412 |
-
clear_old_output_btn = gr.Button("
|
413 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
414 |
|
415 |
-
# Sağ Panel - Sonuçlar
|
416 |
with gr.Column(scale=2, min_width=800):
|
417 |
with gr.Tabs():
|
418 |
-
with gr.Tab("
|
419 |
with gr.Column():
|
420 |
-
original_audio = gr.Audio(label="
|
421 |
with gr.Row():
|
422 |
-
vocals_audio = gr.Audio(label="
|
423 |
-
instrumental_audio = gr.Audio(label="
|
|
|
424 |
|
425 |
-
with gr.Tab("
|
426 |
with gr.Column():
|
427 |
with gr.Row():
|
428 |
-
male_audio = gr.Audio(label="
|
429 |
-
female_audio = gr.Audio(label="
|
430 |
-
speech_audio = gr.Audio(label="
|
431 |
with gr.Row():
|
432 |
-
drum_audio = gr.Audio(label="
|
433 |
-
bass_audio = gr.Audio(label="
|
434 |
with gr.Row():
|
435 |
-
|
436 |
-
effects_audio = gr.Audio(label="Effects")
|
437 |
|
438 |
-
with gr.Tab("
|
439 |
with gr.Column():
|
440 |
with gr.Row():
|
441 |
-
phaseremix_audio = gr.Audio(label="
|
442 |
-
dry_audio = gr.Audio(label="
|
443 |
with gr.Row():
|
444 |
-
music_audio = gr.Audio(label="
|
445 |
-
karaoke_audio = gr.Audio(label="
|
446 |
-
bleed_audio = gr.Audio(label="
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
border-left: 3px solid #6c757d;
|
455 |
-
margin: 1rem 0 1.5rem 0;
|
456 |
-
">
|
457 |
-
<b>🔈 Processing Tip:</b> For noisy results, use <code>bleed_suppressor_v1</code>
|
458 |
-
or <code>denoisedebleed</code> models in the <i>"Denoise & Effect Removal"</i>
|
459 |
-
category to clean the output
|
460 |
</div>
|
461 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
|
463 |
-
|
464 |
-
with gr.Tab("Auto Ensemble"):
|
465 |
with gr.Row():
|
466 |
with gr.Column():
|
467 |
with gr.Group():
|
468 |
-
auto_input_audio_file = gr.File(
|
|
|
|
|
|
|
469 |
auto_file_path_input = gr.Textbox(
|
470 |
-
label="
|
471 |
-
placeholder="
|
472 |
interactive=True
|
473 |
)
|
474 |
|
475 |
-
with gr.Accordion("
|
476 |
with gr.Row():
|
477 |
-
auto_use_tta = gr.Checkbox(label="
|
478 |
-
auto_extract_instrumental = gr.Checkbox(label="
|
479 |
|
480 |
with gr.Row():
|
481 |
auto_overlap = gr.Slider(
|
482 |
-
label="
|
483 |
minimum=2,
|
484 |
maximum=50,
|
485 |
value=2,
|
486 |
step=1
|
487 |
)
|
488 |
auto_chunk_size = gr.Dropdown(
|
489 |
-
label="
|
490 |
choices=[352800, 485100],
|
491 |
value=352800
|
492 |
)
|
493 |
export_format2 = gr.Dropdown(
|
494 |
-
label="
|
495 |
choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
|
496 |
value='wav FLOAT'
|
497 |
)
|
498 |
|
499 |
-
# Model Seçim Bölümü
|
500 |
-
with gr.Group():
|
501 |
-
gr.Markdown("### 🧠 Model Selection")
|
502 |
with gr.Row():
|
503 |
-
|
504 |
-
label="
|
505 |
-
|
506 |
-
|
507 |
)
|
508 |
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
517 |
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
525 |
|
526 |
with gr.Row():
|
527 |
-
|
528 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
529 |
|
530 |
-
# Ensemble Ayarları
|
531 |
with gr.Group():
|
532 |
-
gr.Markdown("###
|
533 |
with gr.Row():
|
534 |
auto_ensemble_type = gr.Dropdown(
|
535 |
-
label="
|
536 |
choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
|
537 |
-
|
538 |
-
value=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
540 |
|
541 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
542 |
|
543 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
|
545 |
with gr.Column():
|
546 |
with gr.Tabs():
|
547 |
-
with gr.Tab("
|
548 |
original_audio2 = gr.Audio(
|
549 |
-
label="
|
550 |
interactive=False,
|
551 |
every=1,
|
552 |
elem_id="original_audio_player"
|
553 |
)
|
554 |
-
with gr.Tab("
|
555 |
auto_output_audio = gr.Audio(
|
556 |
-
label="
|
557 |
show_download_button=True,
|
558 |
interactive=False
|
559 |
)
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
gr.Markdown("""
|
569 |
-
<div style="
|
570 |
-
background: rgba(110, 142, 251, 0.1);
|
571 |
-
padding: 1.2rem;
|
572 |
-
border-radius: 12px;
|
573 |
-
border-left: 4px solid #6e8efb;
|
574 |
-
margin: 1rem 0;
|
575 |
-
backdrop-filter: blur(3px);
|
576 |
-
border: 1px solid rgba(255,255,255,0.2);
|
577 |
-
">
|
578 |
-
<div style="display: flex; align-items: start; gap: 1rem;">
|
579 |
-
<div style="
|
580 |
-
font-size: 1.4em;
|
581 |
-
color: #6e8efb;
|
582 |
-
margin-top: -2px;
|
583 |
-
">⚠️</div>
|
584 |
-
<div style="color: #2d3748;">
|
585 |
-
<h4 style="
|
586 |
-
margin: 0 0 0.8rem 0;
|
587 |
-
color: #4a5568;
|
588 |
-
font-weight: 600;
|
589 |
-
font-size: 1.1rem;
|
590 |
-
">
|
591 |
-
Model Selection Guidelines
|
592 |
-
</h4>
|
593 |
-
<ul style="
|
594 |
-
margin: 0;
|
595 |
-
padding-left: 1.2rem;
|
596 |
-
color: #4a5568;
|
597 |
-
line-height: 1.6;
|
598 |
-
">
|
599 |
-
<li><strong>Avoid cross-category mixing:</strong> Combining vocal and instrumental models may create unwanted blends</li>
|
600 |
-
<li><strong>Special model notes:</strong>
|
601 |
-
<ul style="padding-left: 1.2rem; margin: 0.5rem 0;">
|
602 |
-
<li>Duality models (v1/v2) - Output both stems</li>
|
603 |
-
<li>MDX23C Separator - Hybrid results</li>
|
604 |
-
</ul>
|
605 |
-
</li>
|
606 |
-
<li><strong>Best practice:</strong> Use 3-5 similar models from same category</li>
|
607 |
-
</ul>
|
608 |
-
<div style="
|
609 |
-
margin-top: 1rem;
|
610 |
-
padding: 0.8rem;
|
611 |
-
background: rgba(167, 119, 227, 0.1);
|
612 |
-
border-radius: 8px;
|
613 |
-
color: #6e8efb;
|
614 |
-
font-size: 0.9rem;
|
615 |
-
">
|
616 |
-
💡 Pro Tip: Start with "VOCALS-MelBand-Roformer BigBeta5e" + "VOCALS-BS-Roformer_1297" combination
|
617 |
-
</div>
|
618 |
-
</div>
|
619 |
</div>
|
620 |
</div>
|
621 |
-
"""
|
622 |
-
|
623 |
-
|
624 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
625 |
with gr.Row():
|
626 |
with gr.Column():
|
627 |
-
gr.Markdown("###
|
628 |
-
direct_url_input = gr.Textbox(label="
|
629 |
-
direct_download_btn = gr.Button("
|
630 |
-
direct_download_status = gr.Textbox(label="
|
631 |
-
direct_download_output = gr.File(label="
|
632 |
|
633 |
with gr.Column():
|
634 |
-
gr.Markdown("###
|
635 |
cookie_file = gr.File(
|
636 |
-
label="
|
637 |
file_types=[".txt"],
|
638 |
interactive=True,
|
639 |
elem_id="cookie_upload"
|
640 |
)
|
641 |
-
gr.Markdown(""
|
642 |
-
|
643 |
-
|
644 |
-
- Access age-restricted content
|
645 |
-
- Download private/unlisted videos
|
646 |
-
- Bypass regional restrictions
|
647 |
-
- Avoid YouTube download limits
|
648 |
-
|
649 |
-
**⚠️ Important Notes**
|
650 |
-
- NEVER share your cookie files!
|
651 |
-
- Refresh cookies when:
|
652 |
-
• Getting "403 Forbidden" errors
|
653 |
-
• Downloads suddenly stop
|
654 |
-
• Seeing "Session expired" messages
|
655 |
-
|
656 |
-
**🔄 Renewal Steps**
|
657 |
-
1. Install this <a href="https://chromewebstore.google.com/detail/get-cookiestxt-clean/ahmnmhfbokciafffnknlekllgcnafnie" target="_blank">Chrome extension</a>
|
658 |
-
2. Login to YouTube in Chrome
|
659 |
-
3. Click extension icon → "Export"
|
660 |
-
4. Upload the downloaded file here
|
661 |
-
|
662 |
-
**⏳ Cookie Lifespan**
|
663 |
-
- Normal sessions: 24 hours
|
664 |
-
- Sensitive operations: 1 hour
|
665 |
-
- Password changes: Immediate invalidation
|
666 |
-
</div>
|
667 |
-
""")
|
668 |
-
|
669 |
-
# Manuel Ensemble Sekmesi
|
670 |
-
with gr.Tab("🎚️ Manuel Ensemble"):
|
671 |
with gr.Row(equal_height=True):
|
672 |
with gr.Column(scale=1, min_width=400):
|
673 |
-
with gr.Accordion("
|
674 |
with gr.Row():
|
675 |
-
refresh_btn = gr.Button("
|
676 |
ensemble_type = gr.Dropdown(
|
677 |
-
label="
|
678 |
choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
|
679 |
-
|
680 |
value='avg_wave'
|
681 |
)
|
682 |
|
683 |
-
|
684 |
file_path = os.path.join(Path.home(), 'Music-Source-Separation', 'output')
|
685 |
initial_files = glob.glob(f"{file_path}/*.wav") + glob.glob(os.path.join(BASE_DIR, 'Music-Source-Separation-Training', 'old_output', '*.wav'))
|
686 |
-
|
687 |
-
gr.Markdown("### Select Audio Files")
|
688 |
file_dropdown = gr.Dropdown(
|
689 |
choices=initial_files,
|
690 |
-
label="
|
691 |
multiselect=True,
|
692 |
interactive=True,
|
693 |
elem_id="file-dropdown"
|
694 |
)
|
695 |
-
|
696 |
weights_input = gr.Textbox(
|
697 |
-
label="
|
698 |
-
placeholder="
|
699 |
-
info="
|
700 |
)
|
701 |
|
702 |
-
# Sağ Panel - Sonuçlar
|
703 |
with gr.Column(scale=2, min_width=800):
|
704 |
with gr.Tabs():
|
705 |
-
with gr.Tab("
|
706 |
ensemble_output_audio = gr.Audio(
|
707 |
-
label="
|
708 |
interactive=False,
|
709 |
show_download_button=True,
|
710 |
elem_id="output-audio"
|
711 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
712 |
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
747 |
|
748 |
-
# Event handlers
|
749 |
-
model_category.change(fn=update_model_dropdown, inputs=model_category, outputs=model_dropdown)
|
750 |
clear_old_output_btn.click(fn=clear_old_output, outputs=clear_old_output_status)
|
751 |
|
752 |
input_audio_file.upload(
|
@@ -771,30 +914,66 @@ def create_interface():
|
|
771 |
outputs=[auto_input_audio_file, original_audio2]
|
772 |
)
|
773 |
|
774 |
-
auto_category_dropdown.change(
|
775 |
-
|
776 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
777 |
|
778 |
process_btn.click(
|
779 |
-
fn=
|
780 |
inputs=[
|
781 |
input_audio_file, model_dropdown, chunk_size, overlap, export_format,
|
782 |
-
use_tta, use_demud_phaseremix_inst, extract_instrumental,
|
|
|
|
|
|
|
783 |
],
|
784 |
outputs=[
|
785 |
vocals_audio, instrumental_audio, phaseremix_audio, drum_audio, karaoke_audio,
|
786 |
-
|
787 |
-
dry_audio, male_audio, female_audio
|
|
|
788 |
]
|
789 |
)
|
790 |
|
791 |
auto_process_btn.click(
|
792 |
-
fn=
|
793 |
inputs=[
|
794 |
-
auto_input_audio_file,
|
795 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
796 |
],
|
797 |
-
outputs=[auto_output_audio,
|
798 |
)
|
799 |
|
800 |
direct_download_btn.click(
|
@@ -803,7 +982,13 @@ def create_interface():
|
|
803 |
outputs=[direct_download_output, direct_download_status, input_audio_file, auto_input_audio_file, original_audio, original_audio2]
|
804 |
)
|
805 |
|
|
|
|
|
|
|
|
|
|
|
|
|
806 |
refresh_btn.click(fn=update_file_list, outputs=file_dropdown)
|
807 |
ensemble_process_btn.click(fn=ensemble_audio_fn, inputs=[file_dropdown, ensemble_type, weights_input], outputs=[ensemble_output_audio, ensemble_status])
|
808 |
|
809 |
-
|
|
|
4 |
import subprocess
|
5 |
from pathlib import Path
|
6 |
from datetime import datetime
|
7 |
+
import json
|
8 |
+
import sys
|
9 |
+
import time
|
10 |
+
import random
|
11 |
+
from helpers import update_model_dropdown, handle_file_upload, clear_old_output, save_uploaded_file, update_file_list, clean_model
|
12 |
from download import download_callback
|
13 |
from model import get_model_config, MODEL_CONFIGS
|
14 |
+
from processing import process_audio, auto_ensemble_process, ensemble_audio_fn, refresh_auto_output
|
15 |
+
from assets.i18n.i18n import I18nAuto
|
16 |
+
from config_manager import load_config, save_config, update_favorites, save_preset, delete_preset
|
17 |
+
import logging
|
18 |
+
logging.basicConfig(filename='sesa_gui.log', level=logging.DEBUG)
|
19 |
|
20 |
+
# BASE_DIR tanımı
|
21 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
22 |
+
CONFIG_DIR = os.path.join(BASE_DIR, "assets")
|
23 |
+
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
|
24 |
+
URL_FILE = os.path.join(CONFIG_DIR, "last_url.txt")
|
25 |
+
|
26 |
+
# Load user config at startup
|
27 |
+
user_config = load_config()
|
28 |
+
initial_settings = user_config["settings"]
|
29 |
+
initial_favorites = user_config["favorites"]
|
30 |
+
initial_presets = user_config["presets"]
|
31 |
+
|
32 |
+
# Ensure auto_category is valid
|
33 |
+
if "auto_category" not in initial_settings or initial_settings["auto_category"] not in MODEL_CONFIGS:
|
34 |
+
initial_settings["auto_category"] = "Vocal Models"
|
35 |
+
|
36 |
+
# Config dosyası yoksa oluştur
|
37 |
+
if not os.path.exists(CONFIG_FILE):
|
38 |
+
default_config = {
|
39 |
+
"lang": {"override": False, "selected_lang": "auto"},
|
40 |
+
"sharing": {
|
41 |
+
"method": "gradio",
|
42 |
+
"ngrok_token": "",
|
43 |
+
"port": random.randint(1000, 9000) # Random port instead of fixed
|
44 |
+
}
|
45 |
+
}
|
46 |
+
os.makedirs(CONFIG_DIR, exist_ok=True)
|
47 |
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
48 |
+
json.dump(default_config, f, indent=2)
|
49 |
+
else: # If the file exists, load and update if necessary
|
50 |
+
try:
|
51 |
+
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
|
52 |
+
config = json.load(f)
|
53 |
+
# Ensure 'lang' key exists
|
54 |
+
if "lang" not in config:
|
55 |
+
config["lang"] = {"override": False, "selected_lang": "auto"}
|
56 |
+
# Add 'sharing' key if it doesn't exist
|
57 |
+
if "sharing" not in config:
|
58 |
+
config["sharing"] = {
|
59 |
+
"method": "gradio",
|
60 |
+
"ngrok_token": "",
|
61 |
+
"port": random.randint(1000, 9000) # Random port instead of fixed
|
62 |
+
}
|
63 |
+
# Save the updated configuration
|
64 |
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
65 |
+
json.dump(config, f, indent=2)
|
66 |
+
except json.JSONDecodeError: # Handle corrupted JSON
|
67 |
+
print("Warning: config.json is corrupted. Creating a new one.")
|
68 |
+
default_config = {
|
69 |
+
"lang": {"override": False, "selected_lang": "auto"},
|
70 |
+
"sharing": {
|
71 |
+
"method": "gradio",
|
72 |
+
"ngrok_token": "",
|
73 |
+
"port": random.randint(1000, 9000) # Random port instead of fixed
|
74 |
+
}
|
75 |
+
}
|
76 |
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
77 |
+
json.dump(default_config, f, indent=2)
|
78 |
+
|
79 |
+
# I18nAuto örneği (arayüz başlamadan önce dil yüklenir)
|
80 |
+
i18n = I18nAuto()
|
81 |
+
|
82 |
+
# Çıktı formatları
|
83 |
+
OUTPUT_FORMATS = ['wav', 'flac', 'mp3', 'ogg', 'opus', 'm4a', 'aiff', 'ac3']
|
84 |
|
85 |
# Arayüz oluşturma fonksiyonu
|
86 |
def create_interface():
|
|
|
87 |
css = """
|
|
|
88 |
body {
|
89 |
+
background: linear-gradient(to bottom, rgba(45, 11, 11, 0.9), rgba(0, 0, 0, 0.8)), url('/content/logo.jpg') no-repeat center center fixed;
|
90 |
background-size: cover;
|
|
|
91 |
min-height: 100vh;
|
92 |
margin: 0;
|
93 |
padding: 1rem;
|
94 |
font-family: 'Poppins', sans-serif;
|
95 |
+
color: #C0C0C0;
|
96 |
+
overflow-x: hidden;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
.header-text {
|
99 |
text-align: center;
|
100 |
+
padding: 100px 20px 20px;
|
101 |
+
color: #ff4040;
|
102 |
+
font-size: 3rem;
|
103 |
+
font-weight: 900;
|
104 |
+
text-shadow: 0 0 10px rgba(255, 64, 64, 0.5);
|
105 |
+
z-index: 1500;
|
106 |
+
animation: text-glow 2s infinite;
|
107 |
+
}
|
108 |
+
.header-subtitle {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
text-align: center;
|
110 |
+
color: #C0C0C0;
|
111 |
+
font-size: 1.2rem;
|
112 |
+
font-weight: 300;
|
113 |
+
margin-top: -10px;
|
114 |
+
text-shadow: 0 0 5px rgba(255, 64, 64, 0.3);
|
115 |
+
}
|
116 |
+
.gr-tab {
|
117 |
+
background: rgba(128, 0, 0, 0.5) !important;
|
118 |
+
border-radius: 12px 12px 0 0 !important;
|
119 |
+
margin: 0 5px !important;
|
120 |
+
color: #C0C0C0 !important;
|
121 |
+
border: 1px solid #ff4040 !important;
|
122 |
+
z-index: 1500;
|
123 |
+
transition: background 0.3s ease, color 0.3s ease;
|
124 |
+
padding: 10px 20px !important;
|
125 |
+
font-size: 1.1rem !important;
|
126 |
}
|
|
|
|
|
127 |
button {
|
128 |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
129 |
+
background: #800000 !important;
|
130 |
+
border: 1px solid #ff4040 !important;
|
131 |
+
color: #C0C0C0 !important;
|
132 |
border-radius: 8px !important;
|
133 |
padding: 8px 16px !important;
|
134 |
+
box-shadow: 0 2px 10px rgba(255, 64, 64, 0.3);
|
|
|
|
|
135 |
}
|
|
|
136 |
button:hover {
|
137 |
transform: scale(1.05) !important;
|
138 |
+
box-shadow: 0 10px 40px rgba(255, 64, 64, 0.7) !important;
|
139 |
+
background: #ff4040 !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
|
|
|
|
141 |
.compact-upload.horizontal {
|
142 |
display: inline-flex !important;
|
143 |
align-items: center !important;
|
|
|
145 |
max-width: 400px !important;
|
146 |
height: 40px !important;
|
147 |
padding: 0 12px !important;
|
148 |
+
border: 1px solid #ff4040 !important;
|
149 |
+
background: rgba(128, 0, 0, 0.5) !important;
|
150 |
border-radius: 8px !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
}
|
152 |
+
.compact-dropdown {
|
153 |
+
--padding: 8px 12px !important;
|
154 |
+
--radius: 10px !important;
|
155 |
+
border: 1px solid #ff4040 !important;
|
156 |
+
background: rgba(128, 0, 0, 0.5) !important;
|
157 |
+
color: #C0C0C0 !important;
|
158 |
}
|
159 |
+
#custom-progress {
|
160 |
+
margin-top: 10px;
|
161 |
+
padding: 10px;
|
162 |
+
background: rgba(128, 0, 0, 0.3);
|
163 |
+
border-radius: 8px;
|
164 |
+
border: 1px solid #ff4040;
|
165 |
}
|
166 |
+
#progress-bar {
|
167 |
+
height: 20px;
|
168 |
+
background: linear-gradient(to right, #6e8efb, #ff4040);
|
169 |
+
border-radius: 5px;
|
170 |
+
transition: width 0.5s ease-in-out;
|
171 |
+
max-width: 100% !important;
|
|
|
|
|
|
|
172 |
}
|
173 |
+
.gr-accordion {
|
174 |
+
background: rgba(128, 0, 0, 0.5) !important;
|
175 |
+
border-radius: 10px !important;
|
176 |
+
border: 1px solid #ff4040 !important;
|
|
|
|
|
177 |
}
|
178 |
+
.footer {
|
179 |
+
text-align: center;
|
180 |
+
padding: 20px;
|
181 |
+
color: #ff4040;
|
182 |
+
font-size: 14px;
|
183 |
+
margin-top: 40px;
|
184 |
+
background: rgba(128, 0, 0, 0.3);
|
185 |
+
border-top: 1px solid #ff4040;
|
186 |
}
|
187 |
+
#log-accordion {
|
188 |
+
max-height: 400px;
|
|
|
|
|
189 |
overflow-y: auto;
|
190 |
+
background: rgba(0, 0, 0, 0.7) !important;
|
191 |
padding: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
border-radius: 8px;
|
|
|
|
|
193 |
}
|
|
|
|
|
194 |
@keyframes text-glow {
|
195 |
0% { text-shadow: 0 0 5px rgba(192, 192, 192, 0); }
|
196 |
50% { text-shadow: 0 0 15px rgba(192, 192, 192, 1); }
|
197 |
100% { text-shadow: 0 0 5px rgba(192, 192, 192, 0); }
|
198 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
"""
|
200 |
|
201 |
+
# Load user config at startup
|
202 |
+
user_config = load_config()
|
203 |
+
initial_settings = user_config["settings"]
|
204 |
+
initial_favorites = user_config["favorites"]
|
205 |
+
initial_presets = user_config["presets"]
|
206 |
+
|
207 |
with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
|
208 |
+
current_lang = gr.State(value=i18n.language)
|
209 |
+
favorites_state = gr.State(value=initial_favorites)
|
210 |
+
presets_state = gr.State(value=initial_presets)
|
211 |
+
|
212 |
+
header_html = gr.HTML(
|
213 |
+
value=f"""
|
214 |
+
<div class="header-text">{i18n("SESA Audio Separation")}</div>
|
215 |
+
<div class="header-subtitle">{i18n("ultimate_audio_separation")}</div>
|
216 |
"""
|
217 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
|
219 |
with gr.Tabs():
|
220 |
+
with gr.Tab(i18n("audio_separation_tab"), id="separation_tab"):
|
221 |
with gr.Row(equal_height=True):
|
|
|
222 |
with gr.Column(scale=1, min_width=380):
|
223 |
+
with gr.Accordion(i18n("input_model"), open=True) as input_model_accordion:
|
224 |
with gr.Tabs():
|
225 |
+
with gr.Tab(i18n("upload")) as upload_tab:
|
226 |
input_audio_file = gr.File(
|
227 |
file_types=[".wav", ".mp3", ".m4a", ".mp4", ".mkv", ".flac"],
|
228 |
elem_classes=["compact-upload", "horizontal", "x-narrow"],
|
229 |
label=""
|
230 |
)
|
231 |
+
with gr.Tab(i18n("path")) as path_tab:
|
232 |
+
file_path_input = gr.Textbox(placeholder=i18n("path_placeholder"))
|
|
|
233 |
|
234 |
with gr.Row():
|
235 |
model_category = gr.Dropdown(
|
236 |
+
label=i18n("category"),
|
237 |
+
choices=[i18n(cat) for cat in MODEL_CONFIGS.keys()],
|
238 |
+
value=i18n(initial_settings["model_category"])
|
|
|
|
|
|
|
|
|
239 |
)
|
240 |
+
favorite_button = gr.Button(i18n("add_favorite"), variant="secondary", scale=0)
|
241 |
|
242 |
+
model_dropdown = gr.Dropdown(
|
243 |
+
label=i18n("model"),
|
244 |
+
choices=update_model_dropdown(i18n(initial_settings["model_category"]), favorites=initial_favorites)["choices"],
|
245 |
+
value=initial_settings["selected_model"]
|
246 |
+
)
|
247 |
+
|
248 |
+
with gr.Accordion(i18n("settings"), open=False) as settings_accordion:
|
249 |
with gr.Row():
|
250 |
+
with gr.Column(scale=1):
|
251 |
+
export_format = gr.Dropdown(
|
252 |
+
label=i18n("format"),
|
253 |
+
choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
|
254 |
+
value=initial_settings["export_format"]
|
255 |
+
)
|
256 |
+
with gr.Column(scale=1):
|
257 |
+
chunk_size = gr.Dropdown(
|
258 |
+
label=i18n("chunk_size"),
|
259 |
+
choices=[352800, 485100],
|
260 |
+
value=initial_settings["chunk_size"],
|
261 |
+
info=i18n("chunk_size_info")
|
262 |
+
)
|
263 |
|
264 |
with gr.Row():
|
265 |
+
with gr.Column(scale=2):
|
266 |
+
overlap = gr.Slider(
|
267 |
+
minimum=2,
|
268 |
+
maximum=50,
|
269 |
+
step=1,
|
270 |
+
label=i18n("overlap"),
|
271 |
+
value=initial_settings["overlap"],
|
272 |
+
info=i18n("overlap_info")
|
273 |
+
)
|
274 |
|
275 |
with gr.Row():
|
276 |
+
with gr.Column(scale=1):
|
277 |
+
use_tta = gr.Checkbox(
|
278 |
+
label=i18n("tta_boost"),
|
279 |
+
info=i18n("tta_info"),
|
280 |
+
value=initial_settings["use_tta"]
|
281 |
+
)
|
282 |
+
|
283 |
+
with gr.Row():
|
284 |
+
with gr.Column(scale=1):
|
285 |
+
use_demud_phaseremix_inst = gr.Checkbox(
|
286 |
+
label=i18n("phase_fix"),
|
287 |
+
info=i18n("phase_fix_info"),
|
288 |
+
value=initial_settings["use_demud_phaseremix_inst"]
|
289 |
+
)
|
290 |
+
|
291 |
+
with gr.Column(scale=1):
|
292 |
+
extract_instrumental = gr.Checkbox(
|
293 |
+
label=i18n("instrumental"),
|
294 |
+
info=i18n("instrumental_info"),
|
295 |
+
value=initial_settings["extract_instrumental"]
|
296 |
+
)
|
297 |
+
|
298 |
+
with gr.Row():
|
299 |
+
use_apollo = gr.Checkbox(
|
300 |
+
label=i18n("enhance_with_apollo"),
|
301 |
+
value=initial_settings["use_apollo"],
|
302 |
+
info=i18n("apollo_enhancement_info")
|
303 |
+
)
|
304 |
+
|
305 |
+
with gr.Group(visible=initial_settings["use_apollo"]) as apollo_settings_group:
|
306 |
+
with gr.Row():
|
307 |
+
with gr.Column(scale=1):
|
308 |
+
apollo_chunk_size = gr.Slider(
|
309 |
+
label=i18n("apollo_chunk_size"),
|
310 |
+
minimum=3,
|
311 |
+
maximum=25,
|
312 |
+
step=1,
|
313 |
+
value=initial_settings["apollo_chunk_size"],
|
314 |
+
info=i18n("apollo_chunk_size_info"),
|
315 |
+
interactive=True
|
316 |
+
)
|
317 |
+
with gr.Column(scale=1):
|
318 |
+
apollo_overlap = gr.Slider(
|
319 |
+
label=i18n("apollo_overlap"),
|
320 |
+
minimum=2,
|
321 |
+
maximum=10,
|
322 |
+
step=1,
|
323 |
+
value=initial_settings["apollo_overlap"],
|
324 |
+
info=i18n("apollo_overlap_info"),
|
325 |
+
interactive=True
|
326 |
+
)
|
327 |
+
|
328 |
+
with gr.Row():
|
329 |
+
apollo_method = gr.Dropdown(
|
330 |
+
label=i18n("apollo_processing_method"),
|
331 |
+
choices=[i18n("normal_method"), i18n("mid_side_method")],
|
332 |
+
value=i18n(initial_settings["apollo_method"]),
|
333 |
+
interactive=True
|
334 |
+
)
|
335 |
+
|
336 |
+
with gr.Row(visible=initial_settings["apollo_method"] != "mid_side_method") as apollo_normal_model_row:
|
337 |
+
apollo_normal_model = gr.Dropdown(
|
338 |
+
label=i18n("apollo_normal_model"),
|
339 |
+
choices=["MP3 Enhancer", "Lew Vocal Enhancer", "Lew Vocal Enhancer v2 (beta)", "Apollo Universal Model"],
|
340 |
+
value=initial_settings["apollo_normal_model"],
|
341 |
+
interactive=True
|
342 |
+
)
|
343 |
+
|
344 |
+
with gr.Row(visible=initial_settings["apollo_method"] == "mid_side_method") as apollo_midside_model_row:
|
345 |
+
apollo_midside_model = gr.Dropdown(
|
346 |
+
label=i18n("apollo_mid_side_model"),
|
347 |
+
choices=["MP3 Enhancer", "Lew Vocal Enhancer", "Lew Vocal Enhancer v2 (beta)", "Apollo Universal Model"],
|
348 |
+
value=initial_settings["apollo_midside_model"],
|
349 |
+
interactive=True
|
350 |
+
)
|
351 |
+
|
352 |
+
with gr.Row():
|
353 |
+
use_matchering = gr.Checkbox(
|
354 |
+
label=i18n("apply_matchering"),
|
355 |
+
value=initial_settings.get("use_matchering", False),
|
356 |
+
info=i18n("matchering_info")
|
357 |
+
)
|
358 |
+
|
359 |
+
with gr.Group(visible=initial_settings.get("use_matchering", True)) as matchering_settings_group:
|
360 |
+
matchering_passes = gr.Slider(
|
361 |
+
label=i18n("matchering_passes"),
|
362 |
+
minimum=1,
|
363 |
+
maximum=5,
|
364 |
+
step=1,
|
365 |
+
value=initial_settings.get("matchering_passes", 1),
|
366 |
+
info=i18n("matchering_passes_info"),
|
367 |
+
interactive=True
|
368 |
+
)
|
369 |
|
370 |
with gr.Row():
|
371 |
+
process_btn = gr.Button(i18n("process"), variant="primary")
|
372 |
+
clear_old_output_btn = gr.Button(i18n("reset"), variant="secondary")
|
373 |
+
clear_old_output_status = gr.Textbox(label=i18n("status"), interactive=False)
|
374 |
+
|
375 |
+
# Favorite handler
|
376 |
+
def update_favorite_button(model, favorites):
|
377 |
+
cleaned_model = clean_model(model) if model else None
|
378 |
+
is_favorited = cleaned_model in favorites if cleaned_model else False
|
379 |
+
return gr.update(value=i18n("remove_favorite") if is_favorited else i18n("add_favorite"))
|
380 |
+
|
381 |
+
def toggle_favorite(model, favorites):
|
382 |
+
if not model:
|
383 |
+
return favorites, gr.update(), gr.update()
|
384 |
+
cleaned_model = clean_model(model)
|
385 |
+
is_favorited = cleaned_model in favorites
|
386 |
+
new_favorites = update_favorites(favorites, cleaned_model, add=not is_favorited)
|
387 |
+
save_config(new_favorites, load_config()["settings"], load_config()["presets"])
|
388 |
+
category = model_category.value
|
389 |
+
return (
|
390 |
+
new_favorites,
|
391 |
+
gr.update(choices=update_model_dropdown(category, favorites=new_favorites)["choices"]),
|
392 |
+
gr.update(value=i18n("add_favorite") if is_favorited else i18n("remove_favorite"))
|
393 |
+
)
|
394 |
+
|
395 |
+
model_dropdown.change(
|
396 |
+
fn=update_favorite_button,
|
397 |
+
inputs=[model_dropdown, favorites_state],
|
398 |
+
outputs=favorite_button
|
399 |
+
)
|
400 |
+
|
401 |
+
favorite_button.click(
|
402 |
+
fn=toggle_favorite,
|
403 |
+
inputs=[model_dropdown, favorites_state],
|
404 |
+
outputs=[favorites_state, model_dropdown, favorite_button]
|
405 |
+
)
|
406 |
+
|
407 |
+
use_apollo.change(
|
408 |
+
fn=lambda x: gr.update(visible=x),
|
409 |
+
inputs=use_apollo,
|
410 |
+
outputs=apollo_settings_group
|
411 |
+
)
|
412 |
+
|
413 |
+
use_matchering.change(
|
414 |
+
fn=lambda x: gr.update(visible=x),
|
415 |
+
inputs=use_matchering,
|
416 |
+
outputs=matchering_settings_group
|
417 |
+
)
|
418 |
+
|
419 |
+
apollo_method.change(
|
420 |
+
fn=lambda x: [
|
421 |
+
gr.update(visible=x != i18n("mid_side_method")),
|
422 |
+
gr.update(visible=x == i18n("mid_side_method")),
|
423 |
+
"Apollo Universal Model" if x == i18n("mid_side_method") else None
|
424 |
+
],
|
425 |
+
inputs=apollo_method,
|
426 |
+
outputs=[apollo_normal_model_row, apollo_midside_model_row, apollo_normal_model]
|
427 |
+
)
|
428 |
|
|
|
429 |
with gr.Column(scale=2, min_width=800):
|
430 |
with gr.Tabs():
|
431 |
+
with gr.Tab(i18n("main_tab")) as main_tab:
|
432 |
with gr.Column():
|
433 |
+
original_audio = gr.Audio(label=i18n("original"), interactive=False)
|
434 |
with gr.Row():
|
435 |
+
vocals_audio = gr.Audio(label=i18n("vocals"), show_download_button=True)
|
436 |
+
instrumental_audio = gr.Audio(label=i18n("instrumental_output"), show_download_button=True)
|
437 |
+
other_audio = gr.Audio(label=i18n("other"), show_download_button=True)
|
438 |
|
439 |
+
with gr.Tab(i18n("details_tab")) as details_tab:
|
440 |
with gr.Column():
|
441 |
with gr.Row():
|
442 |
+
male_audio = gr.Audio(label=i18n("male"))
|
443 |
+
female_audio = gr.Audio(label=i18n("female"))
|
444 |
+
speech_audio = gr.Audio(label=i18n("speech"))
|
445 |
with gr.Row():
|
446 |
+
drum_audio = gr.Audio(label=i18n("drums"))
|
447 |
+
bass_audio = gr.Audio(label=i18n("bass"))
|
448 |
with gr.Row():
|
449 |
+
effects_audio = gr.Audio(label=i18n("effects"))
|
|
|
450 |
|
451 |
+
with gr.Tab(i18n("advanced_tab")) as advanced_tab:
|
452 |
with gr.Column():
|
453 |
with gr.Row():
|
454 |
+
phaseremix_audio = gr.Audio(label=i18n("phase_remix"))
|
455 |
+
dry_audio = gr.Audio(label=i18n("dry"))
|
456 |
with gr.Row():
|
457 |
+
music_audio = gr.Audio(label=i18n("music"))
|
458 |
+
karaoke_audio = gr.Audio(label=i18n("karaoke"))
|
459 |
+
bleed_audio = gr.Audio(label=i18n("bleed"))
|
460 |
+
|
461 |
+
separation_progress_html = gr.HTML(
|
462 |
+
value=f"""
|
463 |
+
<div id="custom-progress" style="margin-top: 10px;">
|
464 |
+
<div style="font-size: 1rem; color: #C0C0C0; margin-bottom: 5px;" id="progress-label">{i18n("waiting_for_processing")}</div>
|
465 |
+
<div style="width: 100%; background-color: #444; border-radius: 5px; overflow: hidden;">
|
466 |
+
<div id="progress-bar" style="width: 0%; height: 20px; background-color: #6e8efb; transition: width 0.3s;"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
467 |
</div>
|
468 |
+
</div>
|
469 |
+
"""
|
470 |
+
)
|
471 |
+
separation_process_status = gr.Textbox(
|
472 |
+
label=i18n("status"),
|
473 |
+
interactive=False,
|
474 |
+
placeholder=i18n("waiting_for_processing"),
|
475 |
+
visible=False
|
476 |
+
)
|
477 |
+
processing_tip = gr.Markdown(i18n("processing_tip"))
|
478 |
|
479 |
+
with gr.Tab(i18n("auto_ensemble_tab"), id="auto_ensemble_tab"):
|
|
|
480 |
with gr.Row():
|
481 |
with gr.Column():
|
482 |
with gr.Group():
|
483 |
+
auto_input_audio_file = gr.File(
|
484 |
+
file_types=[".wav", ".mp3", ".m4a", ".mp4", ".mkv", ".flac"],
|
485 |
+
label=i18n("upload_file")
|
486 |
+
)
|
487 |
auto_file_path_input = gr.Textbox(
|
488 |
+
label=i18n("enter_file_path"),
|
489 |
+
placeholder=i18n("file_path_placeholder"),
|
490 |
interactive=True
|
491 |
)
|
492 |
|
493 |
+
with gr.Accordion(i18n("advanced_settings"), open=False) as auto_settings_accordion:
|
494 |
with gr.Row():
|
495 |
+
auto_use_tta = gr.Checkbox(label=i18n("use_tta"), value=False)
|
496 |
+
auto_extract_instrumental = gr.Checkbox(label=i18n("instrumental_only"))
|
497 |
|
498 |
with gr.Row():
|
499 |
auto_overlap = gr.Slider(
|
500 |
+
label=i18n("auto_overlap"),
|
501 |
minimum=2,
|
502 |
maximum=50,
|
503 |
value=2,
|
504 |
step=1
|
505 |
)
|
506 |
auto_chunk_size = gr.Dropdown(
|
507 |
+
label=i18n("auto_chunk_size"),
|
508 |
choices=[352800, 485100],
|
509 |
value=352800
|
510 |
)
|
511 |
export_format2 = gr.Dropdown(
|
512 |
+
label=i18n("output_format"),
|
513 |
choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
|
514 |
value='wav FLOAT'
|
515 |
)
|
516 |
|
|
|
|
|
|
|
517 |
with gr.Row():
|
518 |
+
auto_use_apollo = gr.Checkbox(
|
519 |
+
label=i18n("enhance_with_apollo"),
|
520 |
+
value=False,
|
521 |
+
info=i18n("apollo_enhancement_info")
|
522 |
)
|
523 |
|
524 |
+
with gr.Group(visible=False) as auto_apollo_settings_group:
|
525 |
+
with gr.Row():
|
526 |
+
with gr.Column(scale=1):
|
527 |
+
auto_apollo_chunk_size = gr.Slider(
|
528 |
+
label=i18n("apollo_chunk_size"),
|
529 |
+
minimum=3,
|
530 |
+
maximum=25,
|
531 |
+
step=1,
|
532 |
+
value=19,
|
533 |
+
info=i18n("apollo_chunk_size_info"),
|
534 |
+
interactive=True
|
535 |
+
)
|
536 |
+
with gr.Column(scale=1):
|
537 |
+
auto_apollo_overlap = gr.Slider(
|
538 |
+
label=i18n("apollo_overlap"),
|
539 |
+
minimum=2,
|
540 |
+
maximum=10,
|
541 |
+
step=1,
|
542 |
+
value=2,
|
543 |
+
info=i18n("apollo_overlap_info"),
|
544 |
+
interactive=True
|
545 |
+
)
|
546 |
+
|
547 |
+
with gr.Row():
|
548 |
+
auto_apollo_method = gr.Dropdown(
|
549 |
+
label=i18n("apollo_processing_method"),
|
550 |
+
choices=[i18n("normal_method"), i18n("mid_side_method")],
|
551 |
+
value=i18n("normal_method"),
|
552 |
+
interactive=True
|
553 |
+
)
|
554 |
|
555 |
+
with gr.Row(visible=True) as auto_apollo_normal_model_row:
|
556 |
+
auto_apollo_normal_model = gr.Dropdown(
|
557 |
+
label=i18n("apollo_normal_model"),
|
558 |
+
choices=["MP3 Enhancer", "Lew Vocal Enhancer", "Lew Vocal Enhancer v2 (beta)", "Apollo Universal Model"],
|
559 |
+
value="Apollo Universal Model",
|
560 |
+
interactive=True
|
561 |
+
)
|
562 |
+
|
563 |
+
with gr.Row(visible=False) as auto_apollo_midside_model_row:
|
564 |
+
auto_apollo_midside_model = gr.Dropdown(
|
565 |
+
label=i18n("apollo_mid_side_model"),
|
566 |
+
choices=["MP3 Enhancer", "Lew Vocal Enhancer", "Lew Vocal Enhancer v2 (beta)", "Apollo Universal Model"],
|
567 |
+
value="Apollo Universal Model",
|
568 |
+
interactive=True
|
569 |
+
)
|
570 |
+
|
571 |
+
with gr.Row():
|
572 |
+
auto_use_matchering = gr.Checkbox(
|
573 |
+
label=i18n("apply_matchering"),
|
574 |
+
value=False,
|
575 |
+
info=i18n("matchering_info")
|
576 |
+
)
|
577 |
+
|
578 |
+
with gr.Group(visible=True) as auto_matchering_settings_group:
|
579 |
+
auto_matchering_passes = gr.Slider(
|
580 |
+
label=i18n("matchering_passes"),
|
581 |
+
minimum=1,
|
582 |
+
maximum=5,
|
583 |
+
step=1,
|
584 |
+
value=1,
|
585 |
+
info=i18n("matchering_passes_info"),
|
586 |
+
interactive=True
|
587 |
+
)
|
588 |
+
|
589 |
+
with gr.Group():
|
590 |
+
model_selection_header = gr.Markdown(f"### {i18n('model_selection')}")
|
591 |
+
with gr.Row():
|
592 |
+
auto_category_dropdown = gr.Dropdown(
|
593 |
+
label=i18n("model_category"),
|
594 |
+
choices=[i18n(cat) for cat in MODEL_CONFIGS.keys()],
|
595 |
+
value=i18n("Vocal Models")
|
596 |
+
)
|
597 |
+
selected_models = gr.Dropdown(
|
598 |
+
label=i18n("selected_models"),
|
599 |
+
choices=update_model_dropdown(i18n(initial_settings["auto_category"]), favorites=initial_favorites)["choices"],
|
600 |
+
value=initial_settings["selected_models"],
|
601 |
+
multiselect=True
|
602 |
+
)
|
603 |
|
604 |
with gr.Row():
|
605 |
+
preset_dropdown = gr.Dropdown(
|
606 |
+
label=i18n("select_preset"),
|
607 |
+
choices=list(initial_presets.keys()),
|
608 |
+
value=None,
|
609 |
+
allow_custom_value=False,
|
610 |
+
interactive=True
|
611 |
+
)
|
612 |
+
with gr.Row():
|
613 |
+
preset_name_input = gr.Textbox(
|
614 |
+
label=i18n("preset_name"),
|
615 |
+
placeholder=i18n("enter_preset_name"),
|
616 |
+
interactive=True
|
617 |
+
)
|
618 |
+
save_preset_btn = gr.Button(i18n("save_preset"), variant="secondary", scale=0)
|
619 |
+
delete_preset_btn = gr.Button(i18n("delete_preset"), variant="secondary", scale=0)
|
620 |
+
refresh_presets_btn = gr.Button(i18n("refresh_presets"), variant="secondary", scale=0)
|
621 |
|
|
|
622 |
with gr.Group():
|
623 |
+
ensemble_settings_header = gr.Markdown(f"### {i18n('ensemble_settings')}")
|
624 |
with gr.Row():
|
625 |
auto_ensemble_type = gr.Dropdown(
|
626 |
+
label=i18n("method"),
|
627 |
choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
|
628 |
+
'avg_fft', 'median_fft', 'min_fft', 'max_fft'],
|
629 |
+
value=initial_settings["auto_ensemble_type"]
|
630 |
+
)
|
631 |
+
|
632 |
+
ensemble_recommendation = gr.Markdown(i18n("recommendation"))
|
633 |
+
|
634 |
+
auto_process_btn = gr.Button(i18n("start_processing"), variant="primary")
|
635 |
+
|
636 |
+
def load_preset(preset_name, presets, category, favorites):
|
637 |
+
if preset_name and preset_name in presets:
|
638 |
+
preset = presets[preset_name]
|
639 |
+
# Mark starred models with ⭐
|
640 |
+
favorite_models = [f"{model} ⭐" if model in favorites else model for model in preset["models"]]
|
641 |
+
# Get the category from the preset, default to current category if not specified
|
642 |
+
preset_category = preset.get("auto_category_dropdown", category)
|
643 |
+
# Update model choices based on the preset's category
|
644 |
+
model_choices = update_model_dropdown(preset_category, favorites=favorites)["choices"]
|
645 |
+
print(f"Preset '{preset_name}' loaded with models: {favorite_models}, category: {preset_category}")
|
646 |
+
return (
|
647 |
+
gr.update(value=preset_category), # Update auto_category_dropdown
|
648 |
+
gr.update(choices=model_choices, value=favorite_models), # Update selected_models
|
649 |
+
gr.update(value=preset["ensemble_method"]) # Update auto_ensemble_type
|
650 |
)
|
651 |
+
print(f"Preset '{preset_name}' not found.")
|
652 |
+
return gr.update(), gr.update(), gr.update()
|
653 |
+
|
654 |
+
def sync_presets():
|
655 |
+
"""Reload presets from config and update dropdown."""
|
656 |
+
config = load_config()
|
657 |
+
return config["presets"], gr.update(choices=list(config["presets"].keys()), value=None)
|
658 |
+
|
659 |
+
preset_dropdown.change(
|
660 |
+
fn=load_preset,
|
661 |
+
inputs=[preset_dropdown, presets_state, auto_category_dropdown, favorites_state],
|
662 |
+
outputs=[auto_category_dropdown, selected_models, auto_ensemble_type]
|
663 |
+
)
|
664 |
+
|
665 |
+
def handle_save_preset(preset_name, models, ensemble_method, presets, favorites, auto_category_dropdown):
|
666 |
+
if not preset_name:
|
667 |
+
return gr.update(), presets, i18n("no_preset_name_provided")
|
668 |
+
if not models and not favorites:
|
669 |
+
return gr.update(), presets, i18n("no_models_selected_for_preset")
|
670 |
+
new_presets = save_preset(
|
671 |
+
presets,
|
672 |
+
preset_name,
|
673 |
+
models,
|
674 |
+
ensemble_method,
|
675 |
+
auto_category_dropdown=auto_category_dropdown # Pass the category explicitly
|
676 |
+
)
|
677 |
+
save_config(favorites, load_config()["settings"], new_presets)
|
678 |
+
print(f"Preset dropdown updated with choices: {list(new_presets.keys())}")
|
679 |
+
return gr.update(choices=list(new_presets.keys()), value=None), new_presets, i18n("preset_saved").format(preset_name)
|
680 |
+
|
681 |
+
save_preset_btn.click(
|
682 |
+
fn=handle_save_preset,
|
683 |
+
inputs=[preset_name_input, selected_models, auto_ensemble_type, presets_state, favorites_state, auto_category_dropdown],
|
684 |
+
outputs=[preset_dropdown, presets_state]
|
685 |
+
)
|
686 |
|
687 |
+
def handle_delete_preset(preset_name, presets):
|
688 |
+
if not preset_name or preset_name not in presets:
|
689 |
+
return gr.update(), presets
|
690 |
+
new_presets = delete_preset(presets, preset_name)
|
691 |
+
save_config(load_config()["favorites"], load_config()["settings"], new_presets)
|
692 |
+
return gr.update(choices=list(new_presets.keys()), value=None), new_presets
|
693 |
+
|
694 |
+
delete_preset_btn.click(
|
695 |
+
fn=handle_delete_preset,
|
696 |
+
inputs=[preset_dropdown, presets_state],
|
697 |
+
outputs=[preset_dropdown, presets_state]
|
698 |
+
)
|
699 |
|
700 |
+
refresh_presets_btn.click(
|
701 |
+
fn=sync_presets,
|
702 |
+
inputs=[],
|
703 |
+
outputs=[presets_state, preset_dropdown]
|
704 |
+
)
|
705 |
+
|
706 |
+
auto_use_apollo.change(
|
707 |
+
fn=lambda x: gr.update(visible=x),
|
708 |
+
inputs=auto_use_apollo,
|
709 |
+
outputs=auto_apollo_settings_group
|
710 |
+
)
|
711 |
+
|
712 |
+
auto_use_matchering.change(
|
713 |
+
fn=lambda x: gr.update(visible=x),
|
714 |
+
inputs=auto_use_matchering,
|
715 |
+
outputs=auto_matchering_settings_group
|
716 |
+
)
|
717 |
+
|
718 |
+
auto_apollo_method.change(
|
719 |
+
fn=lambda x: [
|
720 |
+
gr.update(visible=x != i18n("mid_side_method")),
|
721 |
+
gr.update(visible=x == i18n("mid_side_method")),
|
722 |
+
"Apollo Universal Model" if x == i18n("mid_side_method") else None
|
723 |
+
],
|
724 |
+
inputs=auto_apollo_method,
|
725 |
+
outputs=[auto_apollo_normal_model_row, auto_apollo_midside_model_row, auto_apollo_normal_model]
|
726 |
+
)
|
727 |
|
728 |
with gr.Column():
|
729 |
with gr.Tabs():
|
730 |
+
with gr.Tab(i18n("original_audio_tab")) as original_audio_tab:
|
731 |
original_audio2 = gr.Audio(
|
732 |
+
label=i18n("original_audio"),
|
733 |
interactive=False,
|
734 |
every=1,
|
735 |
elem_id="original_audio_player"
|
736 |
)
|
737 |
+
with gr.Tab(i18n("ensemble_result_tab")) as ensemble_result_tab:
|
738 |
auto_output_audio = gr.Audio(
|
739 |
+
label=i18n("output_preview"),
|
740 |
show_download_button=True,
|
741 |
interactive=False
|
742 |
)
|
743 |
+
refresh_output_btn = gr.Button(i18n("refresh_output"), variant="secondary")
|
744 |
+
|
745 |
+
ensemble_progress_html = gr.HTML(
|
746 |
+
value=f"""
|
747 |
+
<div id="custom-progress" style="margin-top: 10px;">
|
748 |
+
<div style="font-size: 1rem; color: #C0C0C0; margin-bottom: 5px;" id="progress-label">{i18n("waiting_for_processing")}</div>
|
749 |
+
<div style="width: 100%; background-color: #444; border-radius: 5px; overflow: hidden;">
|
750 |
+
<div id="progress-bar" style="width: 0%; height: 20px; background-color: #6e8efb; transition: width 0.3s;"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
751 |
</div>
|
752 |
</div>
|
753 |
+
"""
|
754 |
+
)
|
755 |
+
ensemble_process_status = gr.Textbox(
|
756 |
+
label=i18n("status"),
|
757 |
+
interactive=False,
|
758 |
+
placeholder=i18n("waiting_for_processing"),
|
759 |
+
visible=False
|
760 |
+
)
|
761 |
+
|
762 |
+
with gr.Tab(i18n("download_sources_tab"), id="download_tab"):
|
763 |
with gr.Row():
|
764 |
with gr.Column():
|
765 |
+
gr.Markdown(f"### {i18n('direct_links')}")
|
766 |
+
direct_url_input = gr.Textbox(label=i18n("audio_file_url"))
|
767 |
+
direct_download_btn = gr.Button(i18n("download_from_url"), variant="secondary")
|
768 |
+
direct_download_status = gr.Textbox(label=i18n("download_status"))
|
769 |
+
direct_download_output = gr.File(label=i18n("downloaded_file"), interactive=False)
|
770 |
|
771 |
with gr.Column():
|
772 |
+
gr.Markdown(f"### {i18n('cookie_management')}")
|
773 |
cookie_file = gr.File(
|
774 |
+
label=i18n("upload_cookies_txt"),
|
775 |
file_types=[".txt"],
|
776 |
interactive=True,
|
777 |
elem_id="cookie_upload"
|
778 |
)
|
779 |
+
cookie_info = gr.Markdown(i18n("cookie_info"))
|
780 |
+
|
781 |
+
with gr.Tab(i18n("manual_ensemble_tab"), id="manual_ensemble_tab"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
782 |
with gr.Row(equal_height=True):
|
783 |
with gr.Column(scale=1, min_width=400):
|
784 |
+
with gr.Accordion(i18n("input_sources"), open=True) as input_sources_accordion:
|
785 |
with gr.Row():
|
786 |
+
refresh_btn = gr.Button(i18n("refresh"), variant="secondary", size="sm")
|
787 |
ensemble_type = gr.Dropdown(
|
788 |
+
label=i18n("ensemble_algorithm"),
|
789 |
choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
|
790 |
+
'avg_fft', 'median_fft', 'min_fft', 'max_fft'],
|
791 |
value='avg_wave'
|
792 |
)
|
793 |
|
794 |
+
file_dropdown_header = gr.Markdown(f"### {i18n('select_audio_files')}")
|
795 |
file_path = os.path.join(Path.home(), 'Music-Source-Separation', 'output')
|
796 |
initial_files = glob.glob(f"{file_path}/*.wav") + glob.glob(os.path.join(BASE_DIR, 'Music-Source-Separation-Training', 'old_output', '*.wav'))
|
|
|
|
|
797 |
file_dropdown = gr.Dropdown(
|
798 |
choices=initial_files,
|
799 |
+
label=i18n("available_files"),
|
800 |
multiselect=True,
|
801 |
interactive=True,
|
802 |
elem_id="file-dropdown"
|
803 |
)
|
|
|
804 |
weights_input = gr.Textbox(
|
805 |
+
label=i18n("custom_weights"),
|
806 |
+
placeholder=i18n("custom_weights_placeholder"),
|
807 |
+
info=i18n("custom_weights_info")
|
808 |
)
|
809 |
|
|
|
810 |
with gr.Column(scale=2, min_width=800):
|
811 |
with gr.Tabs():
|
812 |
+
with gr.Tab(i18n("result_preview_tab")) as result_preview_tab:
|
813 |
ensemble_output_audio = gr.Audio(
|
814 |
+
label=i18n("ensembled_output"),
|
815 |
interactive=False,
|
816 |
show_download_button=True,
|
817 |
elem_id="output-audio"
|
818 |
)
|
819 |
+
with gr.Tab(i18n("processing_log_tab")) as processing_log_tab:
|
820 |
+
with gr.Accordion(i18n("processing_details"), open=True, elem_id="log-accordion"):
|
821 |
+
ensemble_status = gr.Textbox(
|
822 |
+
label="",
|
823 |
+
interactive=False,
|
824 |
+
placeholder=i18n("processing_log_placeholder"),
|
825 |
+
lines=10,
|
826 |
+
max_lines=20,
|
827 |
+
elem_id="log-box"
|
828 |
+
)
|
829 |
+
with gr.Row():
|
830 |
+
ensemble_process_btn = gr.Button(
|
831 |
+
i18n("process_ensemble"),
|
832 |
+
variant="primary",
|
833 |
+
size="sm",
|
834 |
+
elem_id="process-btn"
|
835 |
+
)
|
836 |
|
837 |
+
def save_settings_on_process(*args):
|
838 |
+
apollo_method_value = args[11]
|
839 |
+
backend_apollo_method = "mid_side_method" if apollo_method_value == i18n("mid_side_method") else "normal_method"
|
840 |
+
cleaned_model = clean_model(args[1]) if args[1] else None
|
841 |
+
settings = {
|
842 |
+
"chunk_size": args[2],
|
843 |
+
"overlap": args[3],
|
844 |
+
"export_format": args[4],
|
845 |
+
"use_tta": args[5],
|
846 |
+
"use_demud_phaseremix_inst": args[6],
|
847 |
+
"extract_instrumental": args[7],
|
848 |
+
"use_apollo": args[8],
|
849 |
+
"apollo_chunk_size": args[9],
|
850 |
+
"apollo_overlap": args[10],
|
851 |
+
"apollo_method": backend_apollo_method,
|
852 |
+
"apollo_normal_model": args[12],
|
853 |
+
"apollo_midside_model": args[13],
|
854 |
+
"use_matchering": args[14],
|
855 |
+
"matchering_passes": args[15],
|
856 |
+
"model_category": args[16],
|
857 |
+
"selected_model": cleaned_model,
|
858 |
+
"auto_ensemble_type": args[7]
|
859 |
+
}
|
860 |
+
save_config(load_config()["favorites"], settings, load_config()["presets"])
|
861 |
+
modified_args = list(args)
|
862 |
+
modified_args[1] = cleaned_model
|
863 |
+
modified_args[17] = cleaned_model
|
864 |
+
return process_audio(*modified_args)
|
865 |
+
|
866 |
+
def save_auto_ensemble_settings(*args):
|
867 |
+
settings = load_config()["settings"]
|
868 |
+
settings["auto_ensemble_type"] = args[7]
|
869 |
+
settings["use_matchering"] = args[14]
|
870 |
+
settings["matchering_passes"] = args[15]
|
871 |
+
save_config(load_config()["favorites"], settings, load_config()["presets"])
|
872 |
+
# Handle generator output from auto_ensemble_process
|
873 |
+
output_audio, status, progress_html = None, i18n("waiting_for_processing"), ensemble_progress_html.value
|
874 |
+
for update in auto_ensemble_process(*args):
|
875 |
+
if isinstance(update, tuple) and len(update) == 3:
|
876 |
+
output_audio, status, progress_html = update
|
877 |
+
return output_audio, status, progress_html
|
878 |
+
|
879 |
+
def update_category_dropdowns(cat):
|
880 |
+
logging.debug(f"Input category: {cat}")
|
881 |
+
eng_cat = next((k for k in MODEL_CONFIGS.keys() if i18n(k) == cat), list(MODEL_CONFIGS.keys())[0])
|
882 |
+
logging.debug(f"Using English category: {eng_cat}")
|
883 |
+
choices = update_model_dropdown(eng_cat, favorites=load_config()["favorites"])["choices"]
|
884 |
+
logging.debug(f"Model choices: {choices}")
|
885 |
+
return gr.update(choices=choices), gr.update(choices=choices)
|
886 |
+
|
887 |
+
model_category.change(
|
888 |
+
fn=update_category_dropdowns,
|
889 |
+
inputs=model_category,
|
890 |
+
outputs=[model_dropdown, selected_models]
|
891 |
+
)
|
892 |
|
|
|
|
|
893 |
clear_old_output_btn.click(fn=clear_old_output, outputs=clear_old_output_status)
|
894 |
|
895 |
input_audio_file.upload(
|
|
|
914 |
outputs=[auto_input_audio_file, original_audio2]
|
915 |
)
|
916 |
|
917 |
+
auto_category_dropdown.change(
|
918 |
+
fn=lambda cat: gr.update(choices=update_model_dropdown(next((k for k in MODEL_CONFIGS.keys() if i18n(k) == cat), list(MODEL_CONFIGS.keys())[0]), favorites=load_config()["favorites"])["choices"]),
|
919 |
+
inputs=auto_category_dropdown,
|
920 |
+
outputs=selected_models
|
921 |
+
)
|
922 |
+
|
923 |
+
def debug_inputs(*args):
|
924 |
+
input_names = [
|
925 |
+
"input_audio_file", "model_dropdown", "chunk_size", "overlap", "export_format",
|
926 |
+
"use_tta", "use_demud_phaseremix_inst", "extract_instrumental",
|
927 |
+
"use_apollo", "apollo_chunk_size", "apollo_overlap",
|
928 |
+
"apollo_method", "apollo_normal_model", "apollo_midside_model",
|
929 |
+
"use_matchering", "matchering_passes", "model_category", "selected_model"
|
930 |
+
]
|
931 |
+
cleaned_args = list(args)
|
932 |
+
cleaned_args[1] = clean_model(cleaned_args[1]) if cleaned_args[1] else None
|
933 |
+
cleaned_args[17] = clean_model(cleaned_args[17]) if cleaned_args[17] else None
|
934 |
+
for name, value in zip(input_names, cleaned_args):
|
935 |
+
print(f"UI Input - {name}: {value}")
|
936 |
+
return args
|
937 |
|
938 |
process_btn.click(
|
939 |
+
fn=lambda *args: save_settings_on_process(*debug_inputs(*args)),
|
940 |
inputs=[
|
941 |
input_audio_file, model_dropdown, chunk_size, overlap, export_format,
|
942 |
+
use_tta, use_demud_phaseremix_inst, extract_instrumental,
|
943 |
+
use_apollo, apollo_chunk_size, apollo_overlap,
|
944 |
+
apollo_method, apollo_normal_model, apollo_midside_model,
|
945 |
+
use_matchering, matchering_passes, model_category, model_dropdown
|
946 |
],
|
947 |
outputs=[
|
948 |
vocals_audio, instrumental_audio, phaseremix_audio, drum_audio, karaoke_audio,
|
949 |
+
other_audio, bass_audio, effects_audio, speech_audio, bleed_audio, music_audio,
|
950 |
+
dry_audio, male_audio, female_audio,
|
951 |
+
separation_process_status, separation_progress_html
|
952 |
]
|
953 |
)
|
954 |
|
955 |
auto_process_btn.click(
|
956 |
+
fn=save_auto_ensemble_settings,
|
957 |
inputs=[
|
958 |
+
auto_input_audio_file,
|
959 |
+
selected_models,
|
960 |
+
auto_chunk_size,
|
961 |
+
auto_overlap,
|
962 |
+
export_format2,
|
963 |
+
auto_use_tta,
|
964 |
+
auto_extract_instrumental,
|
965 |
+
auto_ensemble_type,
|
966 |
+
gr.State(None),
|
967 |
+
auto_use_apollo,
|
968 |
+
auto_apollo_normal_model,
|
969 |
+
auto_apollo_chunk_size,
|
970 |
+
auto_apollo_overlap,
|
971 |
+
auto_apollo_method,
|
972 |
+
auto_use_matchering,
|
973 |
+
auto_matchering_passes,
|
974 |
+
auto_apollo_midside_model
|
975 |
],
|
976 |
+
outputs=[auto_output_audio, ensemble_process_status, ensemble_progress_html]
|
977 |
)
|
978 |
|
979 |
direct_download_btn.click(
|
|
|
982 |
outputs=[direct_download_output, direct_download_status, input_audio_file, auto_input_audio_file, original_audio, original_audio2]
|
983 |
)
|
984 |
|
985 |
+
refresh_output_btn.click(
|
986 |
+
fn=refresh_auto_output,
|
987 |
+
inputs=[],
|
988 |
+
outputs=[auto_output_audio, ensemble_process_status]
|
989 |
+
)
|
990 |
+
|
991 |
refresh_btn.click(fn=update_file_list, outputs=file_dropdown)
|
992 |
ensemble_process_btn.click(fn=ensemble_audio_fn, inputs=[file_dropdown, ensemble_type, weights_input], outputs=[ensemble_output_audio, ensemble_status])
|
993 |
|
994 |
+
return demo
|
helpers.py
CHANGED
@@ -20,6 +20,8 @@ from datetime import datetime
|
|
20 |
import yt_dlp
|
21 |
import validators
|
22 |
from pytube import YouTube
|
|
|
|
|
23 |
import io
|
24 |
import math
|
25 |
import hashlib
|
@@ -27,12 +29,18 @@ import gc
|
|
27 |
import psutil
|
28 |
import concurrent.futures
|
29 |
from tqdm import tqdm
|
|
|
30 |
import tempfile
|
31 |
from urllib.parse import urlparse, quote
|
32 |
import argparse
|
33 |
from tqdm.auto import tqdm
|
34 |
import torch.nn as nn
|
35 |
from model import get_model_config, MODEL_CONFIGS
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
# Temel dizinler
|
38 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
@@ -46,25 +54,77 @@ ENSEMBLE_DIR = os.path.join(BASE_DIR, "ensemble")
|
|
46 |
COOKIE_PATH = os.path.join(BASE_DIR, "cookies.txt")
|
47 |
INFERENCE_SCRIPT_PATH = os.path.join(BASE_DIR, "inference.py")
|
48 |
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
for directory in [BASE_DIR, INPUT_DIR, OUTPUT_DIR, OLD_OUTPUT_DIR, AUTO_ENSEMBLE_TEMP, AUTO_ENSEMBLE_OUTPUT, VIDEO_TEMP, ENSEMBLE_DIR]:
|
51 |
os.makedirs(directory, exist_ok=True)
|
52 |
|
53 |
-
# YAML için özel sınıf ve yapılandırıcı
|
54 |
class IndentDumper(yaml.Dumper):
|
55 |
def increase_indent(self, flow=False, indentless=False):
|
56 |
return super(IndentDumper, self).increase_indent(flow, False)
|
57 |
|
58 |
def tuple_constructor(loader, node):
|
59 |
-
"""
|
60 |
values = loader.construct_sequence(node)
|
61 |
return tuple(values)
|
62 |
|
63 |
yaml.SafeLoader.add_constructor('tag:yaml.org,2002:python/tuple', tuple_constructor)
|
64 |
|
65 |
-
def
|
66 |
-
"""
|
67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
def handle_file_upload(uploaded_file, file_path, is_auto_ensemble=False):
|
70 |
clear_temp_folder("/tmp", exclude_items=["gradio", "config.json"])
|
@@ -80,23 +140,26 @@ def handle_file_upload(uploaded_file, file_path, is_auto_ensemble=False):
|
|
80 |
return target_path, target_path
|
81 |
return None, None
|
82 |
|
|
|
|
|
|
|
83 |
def clear_directory(directory):
|
84 |
-
"""
|
85 |
files = glob.glob(os.path.join(directory, '*'))
|
86 |
for f in files:
|
87 |
try:
|
88 |
os.remove(f)
|
89 |
except Exception as e:
|
90 |
-
print(
|
91 |
|
92 |
def clear_temp_folder(folder_path, exclude_items=None):
|
93 |
-
"""
|
94 |
try:
|
95 |
if not os.path.exists(folder_path):
|
96 |
-
print(
|
97 |
return False
|
98 |
if not os.path.isdir(folder_path):
|
99 |
-
print(
|
100 |
return False
|
101 |
exclude_items = exclude_items or []
|
102 |
for item_name in os.listdir(folder_path):
|
@@ -109,36 +172,45 @@ def clear_temp_folder(folder_path, exclude_items=None):
|
|
109 |
elif os.path.isdir(item_path):
|
110 |
shutil.rmtree(item_path)
|
111 |
except Exception as e:
|
112 |
-
print(
|
113 |
return True
|
114 |
except Exception as e:
|
115 |
-
print(
|
116 |
return False
|
117 |
|
118 |
def clear_old_output():
|
119 |
old_output_folder = os.path.join(BASE_DIR, 'old_output')
|
120 |
try:
|
121 |
if not os.path.exists(old_output_folder):
|
122 |
-
return "
|
123 |
shutil.rmtree(old_output_folder)
|
124 |
os.makedirs(old_output_folder, exist_ok=True)
|
125 |
-
return "
|
126 |
except Exception as e:
|
127 |
-
return
|
128 |
|
129 |
def shorten_filename(filename, max_length=30):
|
130 |
-
"""
|
131 |
base, ext = os.path.splitext(filename)
|
132 |
if len(base) <= max_length:
|
133 |
return filename
|
134 |
return base[:15] + "..." + base[-10:] + ext
|
135 |
|
136 |
def clean_filename(title):
|
137 |
-
"""
|
138 |
return re.sub(r'[^\w\-_\. ]', '', title).strip()
|
139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
def convert_to_wav(file_path):
|
141 |
-
"""
|
142 |
original_filename = os.path.basename(file_path)
|
143 |
filename, ext = os.path.splitext(original_filename)
|
144 |
if ext.lower() == '.wav':
|
@@ -152,13 +224,125 @@ def convert_to_wav(file_path):
|
|
152 |
subprocess.run(command, check=True, capture_output=True)
|
153 |
return wav_output
|
154 |
except subprocess.CalledProcessError as e:
|
155 |
-
print(
|
156 |
return None
|
157 |
|
158 |
def generate_random_port():
|
159 |
-
"""
|
160 |
return random.randint(1000, 9000)
|
161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
def update_file_list():
|
163 |
output_files = glob.glob(os.path.join(OUTPUT_DIR, "*.wav"))
|
164 |
old_output_files = glob.glob(os.path.join(OLD_OUTPUT_DIR, "*.wav"))
|
@@ -166,7 +350,7 @@ def update_file_list():
|
|
166 |
return gr.Dropdown(choices=files)
|
167 |
|
168 |
def save_uploaded_file(uploaded_file, is_input=False, target_dir=None):
|
169 |
-
"""
|
170 |
media_extensions = ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a', '.mp4']
|
171 |
target_dir = target_dir or (INPUT_DIR if is_input else OUTPUT_DIR)
|
172 |
timestamp_patterns = [
|
@@ -204,15 +388,15 @@ def save_uploaded_file(uploaded_file, is_input=False, target_dir=None):
|
|
204 |
else:
|
205 |
shutil.copy(uploaded_file, target_path)
|
206 |
|
207 |
-
print(
|
208 |
return target_path
|
209 |
|
210 |
def move_old_files(output_folder):
|
211 |
-
"""
|
212 |
os.makedirs(OLD_OUTPUT_DIR, exist_ok=True)
|
213 |
for filename in os.listdir(output_folder):
|
214 |
file_path = os.path.join(output_folder, filename)
|
215 |
if os.path.isfile(file_path):
|
216 |
new_filename = f"{os.path.splitext(filename)[0]}_old{os.path.splitext(filename)[1]}"
|
217 |
new_file_path = os.path.join(OLD_OUTPUT_DIR, new_filename)
|
218 |
-
shutil.move(file_path, new_file_path)
|
|
|
20 |
import yt_dlp
|
21 |
import validators
|
22 |
from pytube import YouTube
|
23 |
+
from googleapiclient.discovery import build
|
24 |
+
from googleapiclient.http import MediaIoBaseDownload
|
25 |
import io
|
26 |
import math
|
27 |
import hashlib
|
|
|
29 |
import psutil
|
30 |
import concurrent.futures
|
31 |
from tqdm import tqdm
|
32 |
+
from google.oauth2.credentials import Credentials
|
33 |
import tempfile
|
34 |
from urllib.parse import urlparse, quote
|
35 |
import argparse
|
36 |
from tqdm.auto import tqdm
|
37 |
import torch.nn as nn
|
38 |
from model import get_model_config, MODEL_CONFIGS
|
39 |
+
from assets.i18n.i18n import I18nAuto
|
40 |
+
import matchering as mg
|
41 |
+
from scipy.signal import find_peaks
|
42 |
+
|
43 |
+
i18n = I18nAuto()
|
44 |
|
45 |
# Temel dizinler
|
46 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
54 |
COOKIE_PATH = os.path.join(BASE_DIR, "cookies.txt")
|
55 |
INFERENCE_SCRIPT_PATH = os.path.join(BASE_DIR, "inference.py")
|
56 |
|
57 |
+
def extract_model_name_from_checkpoint(checkpoint_path):
|
58 |
+
if not checkpoint_path:
|
59 |
+
return "Unknown"
|
60 |
+
base_name = os.path.basename(checkpoint_path)
|
61 |
+
model_name = os.path.splitext(base_name)[0]
|
62 |
+
print(f"Original checkpoint path: {checkpoint_path}, extracted model_name: {model_name}")
|
63 |
+
return model_name.strip()
|
64 |
+
|
65 |
for directory in [BASE_DIR, INPUT_DIR, OUTPUT_DIR, OLD_OUTPUT_DIR, AUTO_ENSEMBLE_TEMP, AUTO_ENSEMBLE_OUTPUT, VIDEO_TEMP, ENSEMBLE_DIR]:
|
66 |
os.makedirs(directory, exist_ok=True)
|
67 |
|
|
|
68 |
class IndentDumper(yaml.Dumper):
|
69 |
def increase_indent(self, flow=False, indentless=False):
|
70 |
return super(IndentDumper, self).increase_indent(flow, False)
|
71 |
|
72 |
def tuple_constructor(loader, node):
|
73 |
+
"""YAML'dan bir tuple yükler."""
|
74 |
values = loader.construct_sequence(node)
|
75 |
return tuple(values)
|
76 |
|
77 |
yaml.SafeLoader.add_constructor('tag:yaml.org,2002:python/tuple', tuple_constructor)
|
78 |
|
79 |
+
def clean_model(model):
|
80 |
+
"""
|
81 |
+
Cleans a model name by removing unwanted characters like ⭐ and extra whitespace.
|
82 |
+
|
83 |
+
Args:
|
84 |
+
model (str): The model name to clean.
|
85 |
+
|
86 |
+
Returns:
|
87 |
+
str: The cleaned model name, or None if input is invalid.
|
88 |
+
"""
|
89 |
+
if not model or not isinstance(model, str):
|
90 |
+
return None
|
91 |
+
# Remove ⭐ and extra whitespace
|
92 |
+
cleaned = model.replace("⭐", "").strip()
|
93 |
+
# Remove any additional unwanted characters if needed
|
94 |
+
cleaned = cleaned.replace("\t", " ").replace("\n", " ")
|
95 |
+
return cleaned
|
96 |
+
|
97 |
+
def get_original_category(translated_category):
|
98 |
+
for original_cat in MODEL_CONFIGS.keys():
|
99 |
+
if i18n(original_cat) == translated_category:
|
100 |
+
return original_cat
|
101 |
+
return None
|
102 |
+
|
103 |
+
def clamp_percentage(value):
|
104 |
+
"""Clamp percentage values to the 0-100 range."""
|
105 |
+
try:
|
106 |
+
return min(max(float(value), 0), 100)
|
107 |
+
except (ValueError, TypeError):
|
108 |
+
print(f"Warning: Invalid percentage value {value}, defaulting to 0")
|
109 |
+
return 0
|
110 |
+
|
111 |
+
def update_model_dropdown(category, favorites=None):
|
112 |
+
# Map translated category back to English
|
113 |
+
eng_cat = next((k for k in MODEL_CONFIGS.keys() if i18n(k) == category), list(MODEL_CONFIGS.keys())[0])
|
114 |
+
models = MODEL_CONFIGS.get(eng_cat, [])
|
115 |
+
choices = []
|
116 |
+
favorite_models = []
|
117 |
+
non_favorite_models = []
|
118 |
+
|
119 |
+
for model in models:
|
120 |
+
model_name = f"{model} ⭐" if favorites and model in favorites else model
|
121 |
+
if favorites and model in favorites:
|
122 |
+
favorite_models.append(model_name)
|
123 |
+
else:
|
124 |
+
non_favorite_models.append(model_name)
|
125 |
+
|
126 |
+
choices = favorite_models + non_favorite_models
|
127 |
+
return {"choices": choices}
|
128 |
|
129 |
def handle_file_upload(uploaded_file, file_path, is_auto_ensemble=False):
|
130 |
clear_temp_folder("/tmp", exclude_items=["gradio", "config.json"])
|
|
|
140 |
return target_path, target_path
|
141 |
return None, None
|
142 |
|
143 |
+
if torch.cuda.is_available():
|
144 |
+
torch.cuda.empty_cache()
|
145 |
+
|
146 |
def clear_directory(directory):
|
147 |
+
"""Verilen dizindeki tüm dosyaları siler."""
|
148 |
files = glob.glob(os.path.join(directory, '*'))
|
149 |
for f in files:
|
150 |
try:
|
151 |
os.remove(f)
|
152 |
except Exception as e:
|
153 |
+
print(i18n("file_deletion_error").format(f, e))
|
154 |
|
155 |
def clear_temp_folder(folder_path, exclude_items=None):
|
156 |
+
"""Dizinin içeriğini güvenli bir şekilde temizler ve belirtilen öğeleri korur."""
|
157 |
try:
|
158 |
if not os.path.exists(folder_path):
|
159 |
+
print(i18n("directory_not_exist_warning").format(folder_path))
|
160 |
return False
|
161 |
if not os.path.isdir(folder_path):
|
162 |
+
print(i18n("not_a_directory_warning").format(folder_path))
|
163 |
return False
|
164 |
exclude_items = exclude_items or []
|
165 |
for item_name in os.listdir(folder_path):
|
|
|
172 |
elif os.path.isdir(item_path):
|
173 |
shutil.rmtree(item_path)
|
174 |
except Exception as e:
|
175 |
+
print(i18n("item_deletion_error").format(item_path, e))
|
176 |
return True
|
177 |
except Exception as e:
|
178 |
+
print(i18n("critical_error").format(e))
|
179 |
return False
|
180 |
|
181 |
def clear_old_output():
|
182 |
old_output_folder = os.path.join(BASE_DIR, 'old_output')
|
183 |
try:
|
184 |
if not os.path.exists(old_output_folder):
|
185 |
+
return i18n("old_output_not_exist")
|
186 |
shutil.rmtree(old_output_folder)
|
187 |
os.makedirs(old_output_folder, exist_ok=True)
|
188 |
+
return i18n("old_outputs_cleared")
|
189 |
except Exception as e:
|
190 |
+
return i18n("error").format(e)
|
191 |
|
192 |
def shorten_filename(filename, max_length=30):
|
193 |
+
"""Dosya adını belirtilen maksimum uzunluğa kısaltır."""
|
194 |
base, ext = os.path.splitext(filename)
|
195 |
if len(base) <= max_length:
|
196 |
return filename
|
197 |
return base[:15] + "..." + base[-10:] + ext
|
198 |
|
199 |
def clean_filename(title):
|
200 |
+
"""Dosya adından özel karakterleri kaldırır."""
|
201 |
return re.sub(r'[^\w\-_\. ]', '', title).strip()
|
202 |
|
203 |
+
def sanitize_filename(filename):
|
204 |
+
base, ext = os.path.splitext(filename)
|
205 |
+
base = re.sub(r'\.+', '_', base)
|
206 |
+
base = re.sub(r'[#<>:"/\\|?*]', '_', base)
|
207 |
+
base = re.sub(r'\s+', '_', base)
|
208 |
+
base = re.sub(r'_+', '_', base)
|
209 |
+
base = base.strip('_')
|
210 |
+
return f"{base}{ext}"
|
211 |
+
|
212 |
def convert_to_wav(file_path):
|
213 |
+
"""Ses dosyasını WAV formatına dönüştürür."""
|
214 |
original_filename = os.path.basename(file_path)
|
215 |
filename, ext = os.path.splitext(original_filename)
|
216 |
if ext.lower() == '.wav':
|
|
|
224 |
subprocess.run(command, check=True, capture_output=True)
|
225 |
return wav_output
|
226 |
except subprocess.CalledProcessError as e:
|
227 |
+
print(i18n("ffmpeg_error").format(e.returncode, e.stderr.decode()))
|
228 |
return None
|
229 |
|
230 |
def generate_random_port():
|
231 |
+
"""Rastgele bir port numarası oluşturur."""
|
232 |
return random.randint(1000, 9000)
|
233 |
|
234 |
+
def save_segment(audio, sr, path):
|
235 |
+
"""
|
236 |
+
Save audio segment to a file.
|
237 |
+
|
238 |
+
Args:
|
239 |
+
audio (np.ndarray): Audio data.
|
240 |
+
sr (int): Sample rate.
|
241 |
+
path (str): Output file path.
|
242 |
+
"""
|
243 |
+
sf.write(path, audio, sr)
|
244 |
+
|
245 |
+
def run_matchering(reference_path, target_path, output_path, passes=1, bit_depth=24):
|
246 |
+
"""
|
247 |
+
Run Matchering to master the target audio using the reference audio.
|
248 |
+
|
249 |
+
Args:
|
250 |
+
reference_path (str): Path to the reference audio (clear segment).
|
251 |
+
target_path (str): Path to the target audio to be mastered.
|
252 |
+
output_path (str): Path for the mastered output.
|
253 |
+
passes (int): Number of Matchering passes (1-4).
|
254 |
+
bit_depth (int): Output bit depth (16 or 24).
|
255 |
+
|
256 |
+
Returns:
|
257 |
+
str: Path to the mastered output file.
|
258 |
+
"""
|
259 |
+
# Ensure inputs are WAV files
|
260 |
+
ref_audio, sr = librosa.load(reference_path, sr=44100, mono=False)
|
261 |
+
tgt_audio, sr = librosa.load(target_path, sr=44100, mono=False)
|
262 |
+
|
263 |
+
# Save temporary WAV files
|
264 |
+
temp_ref = os.path.join(tempfile.gettempdir(), "matchering_ref.wav")
|
265 |
+
temp_tgt = os.path.join(tempfile.gettempdir(), "matchering_tgt.wav")
|
266 |
+
save_segment(ref_audio.T if ref_audio.ndim > 1 else ref_audio, sr, temp_ref)
|
267 |
+
save_segment(tgt_audio.T if tgt_audio.ndim > 1 else tgt_audio, sr, temp_tgt)
|
268 |
+
|
269 |
+
# Configure Matchering with default settings
|
270 |
+
config = mg.Config() # No parameters, use defaults
|
271 |
+
|
272 |
+
# Select bit depth for output
|
273 |
+
result_format = mg.pcm24 if bit_depth == 24 else mg.pcm16
|
274 |
+
|
275 |
+
# Run Matchering for multiple passes
|
276 |
+
current_tgt = temp_tgt
|
277 |
+
for i in range(passes):
|
278 |
+
temp_out = os.path.join(tempfile.gettempdir(), f"matchering_out_pass_{i}.wav")
|
279 |
+
mg.process(
|
280 |
+
reference=temp_ref,
|
281 |
+
target=current_tgt,
|
282 |
+
results=[result_format(temp_out)], # Bit depth control
|
283 |
+
config=config
|
284 |
+
)
|
285 |
+
current_tgt = temp_out
|
286 |
+
|
287 |
+
# Move final output to desired path
|
288 |
+
shutil.move(current_tgt, output_path)
|
289 |
+
|
290 |
+
# Clean up temporary files
|
291 |
+
for temp_file in [temp_ref, temp_tgt] + [os.path.join(tempfile.gettempdir(), f"matchering_out_pass_{i}.wav") for i in range(passes-1)]:
|
292 |
+
if os.path.exists(temp_file):
|
293 |
+
os.remove(temp_file)
|
294 |
+
|
295 |
+
return output_path
|
296 |
+
|
297 |
+
def find_clear_segment(audio_path, segment_duration=15, sr=44100):
|
298 |
+
"""
|
299 |
+
Find the clearest (high-energy, low-noise) segment in an audio file.
|
300 |
+
|
301 |
+
Args:
|
302 |
+
audio_path (str): Path to the original audio file.
|
303 |
+
segment_duration (float): Duration of the segment to extract (in seconds).
|
304 |
+
sr (int): Sample rate for loading audio.
|
305 |
+
|
306 |
+
Returns:
|
307 |
+
tuple: (start_time, end_time, segment_audio) of the clearest segment.
|
308 |
+
"""
|
309 |
+
# Load audio
|
310 |
+
audio, sr = librosa.load(audio_path, sr=sr, mono=True)
|
311 |
+
|
312 |
+
# Compute RMS energy in windows
|
313 |
+
window_size = int(5 * sr) # 5-second windows
|
314 |
+
hop_length = window_size // 2
|
315 |
+
rms = librosa.feature.rms(y=audio, frame_length=window_size, hop_length=hop_length)[0]
|
316 |
+
|
317 |
+
# Compute spectral flatness for noise detection
|
318 |
+
flatness = librosa.feature.spectral_flatness(y=audio, n_fft=window_size, hop_length=hop_length)[0]
|
319 |
+
|
320 |
+
# Combine metrics: high RMS and low flatness indicate clear, high-energy segments
|
321 |
+
score = rms / (flatness + 1e-6) # Avoid division by zero
|
322 |
+
|
323 |
+
# Find peaks in the score
|
324 |
+
peaks, _ = find_peaks(score, height=np.mean(score), distance=5)
|
325 |
+
if len(peaks) == 0:
|
326 |
+
# Fallback: Use the middle of the track
|
327 |
+
peak_idx = len(score) // 2
|
328 |
+
else:
|
329 |
+
peak_idx = peaks[np.argmax(score[peaks])]
|
330 |
+
|
331 |
+
# Calculate start and end times
|
332 |
+
start_sample = peak_idx * hop_length
|
333 |
+
end_sample = start_sample + int(segment_duration * sr)
|
334 |
+
|
335 |
+
# Ensure the segment fits within the audio
|
336 |
+
if end_sample > len(audio):
|
337 |
+
end_sample = len(audio)
|
338 |
+
start_sample = max(0, end_sample - int(segment_duration * sr))
|
339 |
+
|
340 |
+
start_time = start_sample / sr
|
341 |
+
end_time = end_sample / sr
|
342 |
+
segment_audio = audio[start_sample:end_sample]
|
343 |
+
|
344 |
+
return start_time, end_time, segment_audio
|
345 |
+
|
346 |
def update_file_list():
|
347 |
output_files = glob.glob(os.path.join(OUTPUT_DIR, "*.wav"))
|
348 |
old_output_files = glob.glob(os.path.join(OLD_OUTPUT_DIR, "*.wav"))
|
|
|
350 |
return gr.Dropdown(choices=files)
|
351 |
|
352 |
def save_uploaded_file(uploaded_file, is_input=False, target_dir=None):
|
353 |
+
"""Yüklenen dosyayı belirtilen dizine kaydeder."""
|
354 |
media_extensions = ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a', '.mp4']
|
355 |
target_dir = target_dir or (INPUT_DIR if is_input else OUTPUT_DIR)
|
356 |
timestamp_patterns = [
|
|
|
388 |
else:
|
389 |
shutil.copy(uploaded_file, target_path)
|
390 |
|
391 |
+
print(i18n("file_saved_successfully").format(os.path.basename(target_path)))
|
392 |
return target_path
|
393 |
|
394 |
def move_old_files(output_folder):
|
395 |
+
"""Eski dosyaları old_output dizinine taşır."""
|
396 |
os.makedirs(OLD_OUTPUT_DIR, exist_ok=True)
|
397 |
for filename in os.listdir(output_folder):
|
398 |
file_path = os.path.join(output_folder, filename)
|
399 |
if os.path.isfile(file_path):
|
400 |
new_filename = f"{os.path.splitext(filename)[0]}_old{os.path.splitext(filename)[1]}"
|
401 |
new_file_path = os.path.join(OLD_OUTPUT_DIR, new_filename)
|
402 |
+
shutil.move(file_path, new_file_path)
|
inference.py
CHANGED
@@ -11,11 +11,18 @@ import glob
|
|
11 |
import torch
|
12 |
import soundfile as sf
|
13 |
import torch.nn as nn
|
14 |
-
from datetime import datetime
|
15 |
import numpy as np
|
16 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
-
# Using the embedded version of Python can also correctly import the utils module.
|
19 |
current_dir = os.path.dirname(os.path.abspath(__file__))
|
20 |
sys.path.append(current_dir)
|
21 |
|
@@ -25,40 +32,18 @@ from utils import prefer_target_instrument, apply_tta, load_start_checkpoint, lo
|
|
25 |
import warnings
|
26 |
warnings.filterwarnings("ignore")
|
27 |
|
28 |
-
|
29 |
def shorten_filename(filename, max_length=30):
|
30 |
-
"""
|
31 |
-
Shortens a filename to a specified maximum length
|
32 |
-
|
33 |
-
Args:
|
34 |
-
filename (str): The filename to be shortened
|
35 |
-
max_length (int): Maximum allowed length for the filename
|
36 |
-
|
37 |
-
Returns:
|
38 |
-
str: Shortened filename
|
39 |
-
"""
|
40 |
base, ext = os.path.splitext(filename)
|
41 |
if len(base) <= max_length:
|
42 |
return filename
|
43 |
-
|
44 |
-
# Take first 15 and last 10 characters
|
45 |
shortened = base[:15] + "..." + base[-10:] + ext
|
46 |
return shortened
|
47 |
|
48 |
def get_soundfile_subtype(pcm_type, is_float=False):
|
49 |
-
"""
|
50 |
-
PCM türüne göre uygun soundfile subtypei belirle
|
51 |
-
|
52 |
-
Args:
|
53 |
-
pcm_type (str): PCM türü ('PCM_16', 'PCM_24', 'FLOAT')
|
54 |
-
is_float (bool): Float formatı kullanılıp kullanılmayacağı
|
55 |
-
|
56 |
-
Returns:
|
57 |
-
str: Soundfile subtype
|
58 |
-
"""
|
59 |
if is_float:
|
60 |
return 'FLOAT'
|
61 |
-
|
62 |
subtype_map = {
|
63 |
'PCM_16': 'PCM_16',
|
64 |
'PCM_24': 'PCM_24',
|
@@ -73,220 +58,122 @@ def run_folder(model, args, config, device, verbose: bool = False):
|
|
73 |
mixture_paths = sorted(glob.glob(os.path.join(args.input_folder, '*.*')))
|
74 |
sample_rate = getattr(config.audio, 'sample_rate', 44100)
|
75 |
|
76 |
-
print(
|
77 |
|
78 |
instruments = prefer_target_instrument(config)[:]
|
79 |
-
os.makedirs(args.store_dir, exist_ok=True)
|
80 |
|
81 |
-
#
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
85 |
for path in mixture_paths:
|
86 |
try:
|
87 |
-
# Dosya işleme başlangıcı
|
88 |
-
current_file += 1
|
89 |
-
print(f"Processing file {current_file}/{total_files}")
|
90 |
-
|
91 |
mix, sr = librosa.load(path, sr=sample_rate, mono=False)
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
if 'normalize' in config.inference:
|
95 |
if config.inference['normalize'] is True:
|
96 |
-
|
97 |
-
|
98 |
-
# Toplam işlem sürelerini izlemek için başlangıç zamanı
|
99 |
-
total_duration = 0.0
|
100 |
-
total_steps = 100.0 # Toplam %100
|
101 |
-
current_progress = 0.0
|
102 |
-
|
103 |
-
# Model yükleme ve ilk ayrıştırma (%0 -> %30)
|
104 |
-
start_time_step = time.time()
|
105 |
-
waveforms_orig = demix(config, model, mix, device, model_type=args.model_type)
|
106 |
-
step_duration = time.time() - start_time_step
|
107 |
-
total_duration += step_duration
|
108 |
-
current_progress += 30.0 * (step_duration / total_duration) if total_duration > 0 else 30.0
|
109 |
-
print(f"Progress: {min(current_progress, 30.0):.1f}%")
|
110 |
-
|
111 |
-
if args.use_tta:
|
112 |
-
# TTA işlemi (%30 -> %50)
|
113 |
-
start_time_step = time.time()
|
114 |
-
waveforms_orig = apply_tta(config, model, mix, waveforms_orig, device, args.model_type)
|
115 |
-
step_duration = time.time() - start_time_step
|
116 |
-
total_duration += step_duration
|
117 |
-
progress_increment = 20.0 * (step_duration / total_duration) if total_duration > 0 else 20.0
|
118 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
119 |
-
current_progress = min(30.0 + i, 50.0)
|
120 |
-
time.sleep(0.001) # Küçük bir gecikme, gerçek işlem için gereksiz olabilir
|
121 |
-
print(f"Progress: {current_progress:.1f}%")
|
122 |
-
|
123 |
-
if args.demud_phaseremix_inst:
|
124 |
-
print(f"Demudding track (phase remix - instrumental): {path}")
|
125 |
-
instr = 'vocals' if 'vocals' in instruments else instruments[0]
|
126 |
-
instruments.append('instrumental_phaseremix')
|
127 |
-
if 'instrumental' not in instruments and 'Instrumental' not in instruments:
|
128 |
-
mix_modified = mix_orig - 2*waveforms_orig[instr]
|
129 |
-
mix_modified_ = mix_modified.copy()
|
130 |
-
|
131 |
-
start_time_step = time.time()
|
132 |
-
waveforms_modified = demix(config, model, mix_modified, device, model_type=args.model_type)
|
133 |
-
step_duration = time.time() - start_time_step
|
134 |
-
total_duration += step_duration
|
135 |
-
progress_increment = 10.0 * (step_duration / total_duration) if total_duration > 0 else 10.0
|
136 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
137 |
-
current_progress = min(50.0 + i, 60.0)
|
138 |
-
time.sleep(0.001)
|
139 |
-
print(f"Progress: {current_progress:.1f}%")
|
140 |
-
|
141 |
-
if args.use_tta:
|
142 |
-
start_time_step = time.time()
|
143 |
-
waveforms_modified = apply_tta(config, model, mix_modified, waveforms_modified, device, args.model_type)
|
144 |
-
step_duration = time.time() - start_time_step
|
145 |
-
total_duration += step_duration
|
146 |
-
progress_increment = 10.0 * (step_duration / total_duration) if total_duration > 0 else 10.0
|
147 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
148 |
-
current_progress = min(60.0 + i, 70.0)
|
149 |
-
time.sleep(0.001)
|
150 |
-
print(f"Progress: {current_progress:.1f}%")
|
151 |
-
|
152 |
-
waveforms_orig['instrumental_phaseremix'] = mix_orig + waveforms_modified[instr]
|
153 |
-
else:
|
154 |
-
mix_modified = 2*waveforms_orig[instr] - mix_orig
|
155 |
-
mix_modified_ = mix_modified.copy()
|
156 |
-
|
157 |
-
start_time_step = time.time()
|
158 |
-
waveforms_modified = demix(config, model, mix_modified, device, model_type=args.model_type)
|
159 |
-
step_duration = time.time() - start_time_step
|
160 |
-
total_duration += step_duration
|
161 |
-
progress_increment = 10.0 * (step_duration / total_duration) if total_duration > 0 else 10.0
|
162 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
163 |
-
current_progress = min(50.0 + i, 60.0)
|
164 |
-
time.sleep(0.001)
|
165 |
-
print(f"Progress: {current_progress:.1f}%")
|
166 |
-
|
167 |
-
if args.use_tta:
|
168 |
-
start_time_step = time.time()
|
169 |
-
waveforms_modified = apply_tta(config, model, mix_modified, waveforms_orig, device, args.model_type)
|
170 |
-
step_duration = time.time() - start_time_step
|
171 |
-
total_duration += step_duration
|
172 |
-
progress_increment = 10.0 * (step_duration / total_duration) if total_duration > 0 else 10.0
|
173 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
174 |
-
current_progress = min(60.0 + i, 70.0)
|
175 |
-
time.sleep(0.001)
|
176 |
-
print(f"Progress: {current_progress:.1f}%")
|
177 |
-
|
178 |
-
waveforms_orig['instrumental_phaseremix'] = mix_orig + mix_modified_ - waveforms_modified[instr]
|
179 |
-
current_progress = 70.0
|
180 |
-
|
181 |
-
if args.extract_instrumental:
|
182 |
-
instr = 'vocals' if 'vocals' in instruments else instruments[0]
|
183 |
-
waveforms_orig['instrumental'] = mix_orig - waveforms_orig[instr]
|
184 |
-
if 'instrumental' not in instruments:
|
185 |
-
instruments.append('instrumental')
|
186 |
-
|
187 |
-
# Dosya yazma ve finalize (%70 -> %100)
|
188 |
-
start_time_step = time.time()
|
189 |
-
for instr in instruments:
|
190 |
-
estimates = waveforms_orig[instr]
|
191 |
-
if 'normalize' in config.inference:
|
192 |
-
if config.inference['normalize'] is True:
|
193 |
-
estimates = denormalize_audio(estimates, norm_params)
|
194 |
-
|
195 |
-
# Dosya formatı ve PCM türü belirleme
|
196 |
-
is_float = getattr(args, 'export_format', '').startswith('wav FLOAT')
|
197 |
-
codec = 'flac' if getattr(args, 'flac_file', False) else 'wav'
|
198 |
-
|
199 |
-
# Subtype belirleme
|
200 |
-
if codec == 'flac':
|
201 |
-
subtype = get_soundfile_subtype(args.pcm_type, is_float)
|
202 |
-
else:
|
203 |
-
subtype = get_soundfile_subtype('FLOAT', is_float)
|
204 |
-
|
205 |
-
shortened_filename = shorten_filename(os.path.basename(path))
|
206 |
-
output_filename = f"{shortened_filename}_{instr}.{codec}"
|
207 |
-
output_path = os.path.join(args.store_dir, output_filename)
|
208 |
-
|
209 |
-
sf.write(output_path, estimates.T, sr, subtype=subtype)
|
210 |
-
step_duration = time.time() - start_time_step
|
211 |
-
total_duration += step_duration
|
212 |
-
progress_increment = 20.0 * (step_duration / total_duration) if total_duration > 0 else 20.0
|
213 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
214 |
-
current_progress = min(70.0 + i, 90.0)
|
215 |
-
time.sleep(0.001)
|
216 |
-
print(f"Progress: {current_progress:.1f}%")
|
217 |
-
|
218 |
-
# Finalize (%90 -> %100)
|
219 |
-
start_time_step = time.time()
|
220 |
-
time.sleep(0.1) # Finalize için küçük bir bekleme (gerçek işlem süresiyle değiştirilebilir)
|
221 |
-
step_duration = time.time() - start_time_step
|
222 |
-
total_duration += step_duration
|
223 |
-
progress_increment = 10.0 * (step_duration / total_duration) if total_duration > 0 else 10.0
|
224 |
-
for i in np.arange(0.1, progress_increment + 0.1, 0.1):
|
225 |
-
current_progress = min(90.0 + i, 100.0)
|
226 |
-
time.sleep(0.001)
|
227 |
-
print(f"Progress: {current_progress:.1f}%")
|
228 |
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
|
|
|
|
233 |
|
234 |
-
|
|
|
|
|
|
|
|
|
|
|
235 |
|
236 |
def proc_folder(args):
|
237 |
-
parser = argparse.ArgumentParser()
|
238 |
-
parser.add_argument("--model_type", type=str, default='mdx23c',
|
239 |
-
|
240 |
-
parser.add_argument("--
|
241 |
-
parser.add_argument("--
|
242 |
-
parser.add_argument("--
|
243 |
-
|
244 |
-
parser.add_argument("--
|
245 |
-
parser.add_argument("--
|
246 |
-
parser.add_argument("--
|
247 |
-
parser.add_argument("--
|
248 |
-
|
249 |
-
parser.add_argument("--
|
250 |
-
|
251 |
-
parser.add_argument("--
|
252 |
-
|
253 |
-
parser.add_argument("--
|
254 |
-
|
255 |
-
parser.add_argument("--
|
256 |
-
|
257 |
-
default='flac PCM_24',
|
258 |
-
help="Export format and PCM type")
|
259 |
-
parser.add_argument("--pcm_type", type=str,
|
260 |
-
choices=['PCM_16', 'PCM_24'],
|
261 |
-
default='PCM_24',
|
262 |
-
help="PCM type for FLAC files")
|
263 |
-
parser.add_argument("--use_tta", action='store_true',
|
264 |
-
help="Enable test time augmentation")
|
265 |
-
parser.add_argument("--lora_checkpoint", type=str, default='',
|
266 |
-
help="Initial checkpoint to LoRA weights")
|
267 |
-
|
268 |
-
# Argümanları ayrıştır
|
269 |
-
parsed_args = parser.parse_args(args)
|
270 |
-
|
271 |
-
# Burada parsed_args.audio_path ile ses dosyası yolunu kullanabilirsiniz
|
272 |
-
print(f"Audio path provided: {parsed_args.audio_path}")
|
273 |
-
|
274 |
if args is None:
|
275 |
args = parser.parse_args()
|
276 |
else:
|
277 |
args = parser.parse_args(args)
|
278 |
|
279 |
-
# Cihaz seçimi
|
280 |
device = "cpu"
|
281 |
if args.force_cpu:
|
282 |
device = "cpu"
|
283 |
elif torch.cuda.is_available():
|
284 |
-
print(
|
285 |
device = f'cuda:{args.device_ids[0]}' if type(args.device_ids) == list else f'cuda:{args.device_ids}'
|
286 |
elif torch.backends.mps.is_available():
|
287 |
device = "mps"
|
288 |
|
289 |
-
print("
|
290 |
|
291 |
model_load_start_time = time.time()
|
292 |
torch.backends.cudnn.benchmark = True
|
@@ -296,18 +183,16 @@ def proc_folder(args):
|
|
296 |
if args.start_check_point != '':
|
297 |
load_start_checkpoint(args, model, type_='inference')
|
298 |
|
299 |
-
print("
|
300 |
|
301 |
-
# Çoklu CUDA GPU kullanımı
|
302 |
if type(args.device_ids) == list and len(args.device_ids) > 1 and not args.force_cpu:
|
303 |
model = nn.DataParallel(model, device_ids=args.device_ids)
|
304 |
|
305 |
model = model.to(device)
|
306 |
|
307 |
-
print("
|
308 |
-
|
309 |
-
run_folder(model, args, config, device, verbose=True)
|
310 |
|
|
|
311 |
|
312 |
if __name__ == "__main__":
|
313 |
-
proc_folder(None)
|
|
|
11 |
import torch
|
12 |
import soundfile as sf
|
13 |
import torch.nn as nn
|
|
|
14 |
import numpy as np
|
15 |
+
from assets.i18n.i18n import I18nAuto
|
16 |
+
|
17 |
+
# Colab kontrolü
|
18 |
+
try:
|
19 |
+
from google.colab import drive
|
20 |
+
IS_COLAB = True
|
21 |
+
except ImportError:
|
22 |
+
IS_COLAB = False
|
23 |
+
|
24 |
+
i18n = I18nAuto()
|
25 |
|
|
|
26 |
current_dir = os.path.dirname(os.path.abspath(__file__))
|
27 |
sys.path.append(current_dir)
|
28 |
|
|
|
32 |
import warnings
|
33 |
warnings.filterwarnings("ignore")
|
34 |
|
|
|
35 |
def shorten_filename(filename, max_length=30):
|
36 |
+
"""Dosya adını belirtilen maksimum uzunluğa kısaltır."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
base, ext = os.path.splitext(filename)
|
38 |
if len(base) <= max_length:
|
39 |
return filename
|
|
|
|
|
40 |
shortened = base[:15] + "..." + base[-10:] + ext
|
41 |
return shortened
|
42 |
|
43 |
def get_soundfile_subtype(pcm_type, is_float=False):
|
44 |
+
"""PCM türüne göre uygun soundfile alt türünü belirler."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
if is_float:
|
46 |
return 'FLOAT'
|
|
|
47 |
subtype_map = {
|
48 |
'PCM_16': 'PCM_16',
|
49 |
'PCM_24': 'PCM_24',
|
|
|
58 |
mixture_paths = sorted(glob.glob(os.path.join(args.input_folder, '*.*')))
|
59 |
sample_rate = getattr(config.audio, 'sample_rate', 44100)
|
60 |
|
61 |
+
print(i18n("total_files_found").format(len(mixture_paths), sample_rate))
|
62 |
|
63 |
instruments = prefer_target_instrument(config)[:]
|
|
|
64 |
|
65 |
+
# Çıktı klasörünü kullan (processing.py tarafından ayarlandı)
|
66 |
+
store_dir = args.store_dir
|
67 |
+
os.makedirs(store_dir, exist_ok=True)
|
68 |
+
|
69 |
+
if not verbose:
|
70 |
+
mixture_paths = tqdm(mixture_paths, desc=i18n("total_progress"))
|
71 |
+
else:
|
72 |
+
mixture_paths = mixture_paths
|
73 |
+
|
74 |
+
detailed_pbar = not args.disable_detailed_pbar
|
75 |
+
print(i18n("detailed_pbar_enabled").format(detailed_pbar))
|
76 |
|
77 |
for path in mixture_paths:
|
78 |
try:
|
|
|
|
|
|
|
|
|
79 |
mix, sr = librosa.load(path, sr=sample_rate, mono=False)
|
80 |
+
print(i18n("loaded_audio").format(path, mix.shape))
|
81 |
+
except Exception as e:
|
82 |
+
print(i18n("cannot_read_track").format(path))
|
83 |
+
print(i18n("error_message").format(str(e)))
|
84 |
+
continue
|
85 |
+
|
86 |
+
mix_orig = mix.copy()
|
87 |
+
if 'normalize' in config.inference:
|
88 |
+
if config.inference['normalize'] is True:
|
89 |
+
mix, norm_params = normalize_audio(mix)
|
90 |
+
|
91 |
+
waveforms_orig = demix(config, model, mix, device, model_type=args.model_type, pbar=detailed_pbar)
|
92 |
+
|
93 |
+
if args.use_tta:
|
94 |
+
waveforms_orig = apply_tta(config, model, mix, waveforms_orig, device, args.model_type)
|
95 |
+
|
96 |
+
if args.demud_phaseremix_inst:
|
97 |
+
print(i18n("demudding_track").format(path))
|
98 |
+
instr = 'vocals' if 'vocals' in instruments else instruments[0]
|
99 |
+
instruments.append('instrumental_phaseremix')
|
100 |
+
if 'instrumental' not in instruments and 'Instrumental' not in instruments:
|
101 |
+
mix_modified = mix_orig - 2*waveforms_orig[instr]
|
102 |
+
mix_modified_ = mix_modified.copy()
|
103 |
+
waveforms_modified = demix(config, model, mix_modified, device, model_type=args.model_type, pbar=detailed_pbar)
|
104 |
+
if args.use_tta:
|
105 |
+
waveforms_modified = apply_tta(config, model, mix_modified, waveforms_modified, device, args.model_type)
|
106 |
+
waveforms_orig['instrumental_phaseremix'] = mix_orig + waveforms_modified[instr]
|
107 |
+
else:
|
108 |
+
mix_modified = 2*waveforms_orig[instr] - mix_orig
|
109 |
+
mix_modified_ = mix_modified.copy()
|
110 |
+
waveforms_modified = demix(config, model, mix_modified, device, model_type=args.model_type, pbar=detailed_pbar)
|
111 |
+
if args.use_tta:
|
112 |
+
waveforms_modified = apply_tta(config, model, mix_modified, waveforms_orig, device, args.model_type)
|
113 |
+
waveforms_orig['instrumental_phaseremix'] = mix_orig + mix_modified_ - waveforms_modified[instr]
|
114 |
+
|
115 |
+
if args.extract_instrumental:
|
116 |
+
instr = 'vocals' if 'vocals' in instruments else instruments[0]
|
117 |
+
waveforms_orig['instrumental'] = mix_orig - waveforms_orig[instr]
|
118 |
+
if 'instrumental' not in instruments:
|
119 |
+
instruments.append('instrumental')
|
120 |
+
|
121 |
+
for instr in instruments:
|
122 |
+
estimates = waveforms_orig[instr]
|
123 |
if 'normalize' in config.inference:
|
124 |
if config.inference['normalize'] is True:
|
125 |
+
estimates = denormalize_audio(estimates, norm_params)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
+
is_float = getattr(args, 'export_format', '').startswith('wav FLOAT')
|
128 |
+
codec = 'flac' if getattr(args, 'flac_file', False) else 'wav'
|
129 |
+
if codec == 'flac':
|
130 |
+
subtype = get_soundfile_subtype(args.pcm_type, is_float)
|
131 |
+
else:
|
132 |
+
subtype = get_soundfile_subtype('FLOAT', is_float)
|
133 |
|
134 |
+
shortened_filename = shorten_filename(os.path.basename(path))
|
135 |
+
output_filename = f"{shortened_filename}_{instr}.{codec}"
|
136 |
+
output_path = os.path.join(store_dir, output_filename)
|
137 |
+
sf.write(output_path, estimates.T, sr, subtype=subtype)
|
138 |
+
|
139 |
+
print(i18n("elapsed_time").format(time.time() - start_time))
|
140 |
|
141 |
def proc_folder(args):
|
142 |
+
parser = argparse.ArgumentParser(description=i18n("proc_folder_description"))
|
143 |
+
parser.add_argument("--model_type", type=str, default='mdx23c', help=i18n("model_type_help"))
|
144 |
+
parser.add_argument("--config_path", type=str, help=i18n("config_path_help"))
|
145 |
+
parser.add_argument("--demud_phaseremix_inst", action='store_true', help=i18n("demud_phaseremix_help"))
|
146 |
+
parser.add_argument("--start_check_point", type=str, default='', help=i18n("start_checkpoint_help"))
|
147 |
+
parser.add_argument("--input_folder", type=str, help=i18n("input_folder_help"))
|
148 |
+
parser.add_argument("--audio_path", type=str, help=i18n("audio_path_help"))
|
149 |
+
parser.add_argument("--store_dir", type=str, default="", help=i18n("store_dir_help"))
|
150 |
+
parser.add_argument("--device_ids", nargs='+', type=int, default=0, help=i18n("device_ids_help"))
|
151 |
+
parser.add_argument("--extract_instrumental", action='store_true', help=i18n("extract_instrumental_help"))
|
152 |
+
parser.add_argument("--disable_detailed_pbar", action='store_true', help=i18n("disable_detailed_pbar_help"))
|
153 |
+
parser.add_argument("--force_cpu", action='store_true', help=i18n("force_cpu_help"))
|
154 |
+
parser.add_argument("--flac_file", action='store_true', help=i18n("flac_file_help"))
|
155 |
+
parser.add_argument("--export_format", type=str, choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'], default='flac PCM_24', help=i18n("export_format_help"))
|
156 |
+
parser.add_argument("--pcm_type", type=str, choices=['PCM_16', 'PCM_24'], default='PCM_24', help=i18n("pcm_type_help"))
|
157 |
+
parser.add_argument("--use_tta", action='store_true', help=i18n("use_tta_help"))
|
158 |
+
parser.add_argument("--lora_checkpoint", type=str, default='', help=i18n("lora_checkpoint_help"))
|
159 |
+
parser.add_argument("--chunk_size", type=int, default=1000000, help="Inference chunk size")
|
160 |
+
parser.add_argument("--overlap", type=int, default=4, help="Inference overlap factor")
|
161 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
if args is None:
|
163 |
args = parser.parse_args()
|
164 |
else:
|
165 |
args = parser.parse_args(args)
|
166 |
|
|
|
167 |
device = "cpu"
|
168 |
if args.force_cpu:
|
169 |
device = "cpu"
|
170 |
elif torch.cuda.is_available():
|
171 |
+
print(i18n("cuda_available"))
|
172 |
device = f'cuda:{args.device_ids[0]}' if type(args.device_ids) == list else f'cuda:{args.device_ids}'
|
173 |
elif torch.backends.mps.is_available():
|
174 |
device = "mps"
|
175 |
|
176 |
+
print(i18n("using_device").format(device))
|
177 |
|
178 |
model_load_start_time = time.time()
|
179 |
torch.backends.cudnn.benchmark = True
|
|
|
183 |
if args.start_check_point != '':
|
184 |
load_start_checkpoint(args, model, type_='inference')
|
185 |
|
186 |
+
print(i18n("instruments_print").format(config.training.instruments))
|
187 |
|
|
|
188 |
if type(args.device_ids) == list and len(args.device_ids) > 1 and not args.force_cpu:
|
189 |
model = nn.DataParallel(model, device_ids=args.device_ids)
|
190 |
|
191 |
model = model.to(device)
|
192 |
|
193 |
+
print(i18n("model_load_time").format(time.time() - model_load_start_time))
|
|
|
|
|
194 |
|
195 |
+
run_folder(model, args, config, device, verbose=False)
|
196 |
|
197 |
if __name__ == "__main__":
|
198 |
+
proc_folder(None)
|
kaggle/clean_model.py
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Kaggle için gerekli kütüphaneleri yükleme
|
2 |
+
import os
|
3 |
+
import glob
|
4 |
+
import subprocess
|
5 |
+
import time
|
6 |
+
import gc
|
7 |
+
import shutil
|
8 |
+
import sys
|
9 |
+
from datetime import datetime
|
10 |
+
import torch
|
11 |
+
import yaml
|
12 |
+
import numpy as np
|
13 |
+
import requests
|
14 |
+
import json
|
15 |
+
import locale
|
16 |
+
import re
|
17 |
+
import psutil
|
18 |
+
import concurrent.futures
|
19 |
+
from tqdm import tqdm
|
20 |
+
from urllib.parse import urlparse, quote
|
21 |
+
|
22 |
+
# Ses işleme kütüphaneleri
|
23 |
+
!pip install librosa soundfile
|
24 |
+
import librosa
|
25 |
+
import soundfile as sf
|
26 |
+
|
27 |
+
# Uyarıları görmezden gel
|
28 |
+
import warnings
|
29 |
+
warnings.filterwarnings("ignore")
|
30 |
+
|
31 |
+
# Kaggle dizin ayarları
|
32 |
+
BASE_DIR = "/kaggle/working/" # Kaggle'da çalışma dizini
|
33 |
+
INFERENCE_PATH = os.path.join(BASE_DIR, "inference.py") # inference.py varsa buraya kopyalanmalı
|
34 |
+
OUTPUT_DIR = os.path.join(BASE_DIR, "output") # Çıkış dizini
|
35 |
+
AUTO_ENSEMBLE_OUTPUT = os.path.join(BASE_DIR, "ensemble_output") # Ensemble çıkış dizini
|
36 |
+
|
37 |
+
# Çıkış dizinlerini oluştur
|
38 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
39 |
+
os.makedirs(AUTO_ENSEMBLE_OUTPUT, exist_ok=True)
|
40 |
+
|
41 |
+
def clean_model_name(model):
|
42 |
+
"""
|
43 |
+
Clean and standardize model names for filename
|
44 |
+
"""
|
45 |
+
model_name_mapping = {
|
46 |
+
'VOCALS-InstVocHQ': 'InstVocHQ',
|
47 |
+
'VOCALS-MelBand-Roformer (by KimberleyJSN)': 'KimberleyJSN',
|
48 |
+
'VOCALS-BS-Roformer_1297 (by viperx)': 'VOCALS_BS_Roformer1297',
|
49 |
+
'VOCALS-BS-Roformer_1296 (by viperx)': 'VOCALS-BS-Roformer_1296',
|
50 |
+
'VOCALS-BS-RoformerLargev1 (by unwa)': 'UnwaLargeV1',
|
51 |
+
'VOCALS-Mel-Roformer big beta 4 (by unwa)': 'UnwaBigBeta4',
|
52 |
+
'VOCALS-Melband-Roformer BigBeta5e (by unwa)': 'UnwaBigBeta5e',
|
53 |
+
'INST-Mel-Roformer v1 (by unwa)': 'UnwaInstV1',
|
54 |
+
'INST-Mel-Roformer v2 (by unwa)': 'UnwaInstV2',
|
55 |
+
'INST-VOC-Mel-Roformer a.k.a. duality (by unwa)': 'UnwaDualityV1',
|
56 |
+
'INST-VOC-Mel-Roformer a.k.a. duality v2 (by unwa)': 'UnwaDualityV2',
|
57 |
+
'KARAOKE-MelBand-Roformer (by aufr33 & viperx)': 'KaraokeMelBandRoformer',
|
58 |
+
'VOCALS-VitLarge23 (by ZFTurbo)': 'VitLarge23',
|
59 |
+
'VOCALS-MelBand-Roformer (by Becruily)': 'BecruilyVocals',
|
60 |
+
'INST-MelBand-Roformer (by Becruily)': 'BecruilyInst',
|
61 |
+
'VOCALS-MelBand-Roformer Kim FT (by Unwa)': 'KimFT',
|
62 |
+
'INST-MelBand-Roformer Kim FT (by Unwa)': 'KimFTInst',
|
63 |
+
'OTHER-BS-Roformer_1053 (by viperx)': 'OtherViperx1053',
|
64 |
+
'CROWD-REMOVAL-MelBand-Roformer (by aufr33)': 'CrowdRemovalRoformer',
|
65 |
+
'CINEMATIC-BandIt_Plus (by kwatcharasupat)': 'CinematicBandItPlus',
|
66 |
+
'DRUMSEP-MDX23C_DrumSep_6stem (by aufr33 & jarredou)': 'DrumSepMDX23C',
|
67 |
+
'4STEMS-SCNet_MUSDB18 (by starrytong)': 'FourStemsSCNet',
|
68 |
+
'DE-REVERB-MDX23C (by aufr33 & jarredou)': 'DeReverbMDX23C',
|
69 |
+
'DENOISE-MelBand-Roformer-1 (by aufr33)': 'DenoiseMelBand1',
|
70 |
+
'DENOISE-MelBand-Roformer-2 (by aufr33)': 'DenoiseMelBand2',
|
71 |
+
'INST-MelBand-Roformer (by Becruily)': 'BecruilyInst',
|
72 |
+
'4STEMS-SCNet_XL_MUSDB18 (by ZFTurbo)': 'FourStemsSCNetXL',
|
73 |
+
'4STEMS-SCNet_Large (by starrytong)': 'FourStemsSCNetLarge',
|
74 |
+
'4STEMS-BS-Roformer_MUSDB18 (by ZFTurbo)': 'FourStemsBSRoformer',
|
75 |
+
'DE-REVERB-MelBand-Roformer aggr./v2/19.1729 (by anvuew)': 'DeReverbMelBandAggr',
|
76 |
+
'DE-REVERB-Echo-MelBand-Roformer (by Sucial)': 'DeReverbEchoMelBand',
|
77 |
+
'bleed_suppressor_v1 (by unwa)': 'BleedSuppressorV1',
|
78 |
+
'inst_v1e (by unwa)': 'InstV1E',
|
79 |
+
'inst_gabox (by Gabox)': 'InstGabox',
|
80 |
+
'inst_gaboxBV1 (by Gabox)': 'InstGaboxBV1',
|
81 |
+
'inst_gaboxBV2 (by Gabox)': 'InstGaboxBV2',
|
82 |
+
'inst_gaboxBFV1 (by Gabox)': 'InstGaboxBFV1',
|
83 |
+
'inst_gaboxFV2 (by Gabox)': 'InstGaboxFV2',
|
84 |
+
'inst_gaboxFV1 (by Gabox)': 'InstGaboxFV1',
|
85 |
+
'dereverb_mel_band_roformer_less_aggressive_anvuew': 'DereverbMelBandRoformerLessAggressive',
|
86 |
+
'dereverb_mel_band_roformer_anvuew': 'DereverbMelBandRoformer',
|
87 |
+
'VOCALS-Male Female-BS-RoFormer Male Female Beta 7_2889 (by aufr33)': 'MaleFemale-BS-RoFormer-(by aufr33)',
|
88 |
+
'VOCALS-MelBand-Roformer (by Becruily)': 'Vocals-MelBand-Roformer-(by Becruily)',
|
89 |
+
'VOCALS-MelBand-Roformer Kim FT 2 (by Unwa)': 'Vocals-MelBand-Roformer-KİM-FT-2(by Unwa)',
|
90 |
+
'voc_gaboxMelRoformer (by Gabox)': 'voc_gaboxMelRoformer',
|
91 |
+
'voc_gaboxBSroformer (by Gabox)': 'voc_gaboxBSroformer',
|
92 |
+
'voc_gaboxMelRoformerFV1 (by Gabox)': 'voc_gaboxMelRoformerFV1',
|
93 |
+
'voc_gaboxMelRoformerFV2 (by Gabox)': 'voc_gaboxMelRoformerFV2',
|
94 |
+
'SYH99999/MelBandRoformerSYHFTB1(by Amane)': 'MelBandRoformerSYHFTB1',
|
95 |
+
'inst_V5 (by Gabox)': 'INSTV5-(by Gabox)',
|
96 |
+
'inst_Fv4Noise (by Gabox)': 'Inst_Fv4Noise-(by Gabox)',
|
97 |
+
'Intrumental_Gabox (by Gabox)': 'Intrumental_Gabox-(by Gabox)',
|
98 |
+
'inst_GaboxFv3 (by Gabox)': 'INST_GaboxFv3-(by Gabox)',
|
99 |
+
'SYH99999/MelBandRoformerSYHFTB1_Model1 (by Amane)': 'MelBandRoformerSYHFTB1_model1',
|
100 |
+
'SYH99999/MelBandRoformerSYHFTB1_Model2 (by Amane)': 'MelBandRoformerSYHFTB1_model2',
|
101 |
+
'SYH99999/MelBandRoformerSYHFTB1_Model3 (by Amane)': 'MelBandRoformerSYHFTB1_model3',
|
102 |
+
'VOCALS-MelBand-Roformer Kim FT 2 Blendless (by unwa)': 'VOCALS-MelBand-Roformer-Kim-FT-2-Blendless-(by unwa)',
|
103 |
+
'inst_gaboxFV6 (by Gabox)': 'inst_gaboxFV6-(by Gabox)',
|
104 |
+
'denoisedebleed (by Gabox)': 'denoisedebleed-(by Gabox)',
|
105 |
+
'INSTV5N (by Gabox)': 'INSTV5N_(by Gabox)',
|
106 |
+
'Voc_Fv3 (by Gabox)': 'Voc_Fv3_(by Gabox)',
|
107 |
+
'MelBandRoformer4StemFTLarge (SYH99999)': 'MelBandRoformer4StemFTLarge_(SYH99999)',
|
108 |
+
'dereverb_mel_band_roformer_mono (by anvuew)': 'dereverb_mel_band_roformer_mono_(by anvuew)',
|
109 |
+
'INSTV6N (by Gabox)': 'INSTV6N_(by Gabox)',
|
110 |
+
'KaraokeGabox': 'KaraokeGabox',
|
111 |
+
'FullnessVocalModel (by Amane)': 'FullnessVocalModel',
|
112 |
+
'Inst_GaboxV7 (by Gabox)': 'Inst_GaboxV7_(by Gabox)',
|
113 |
+
}
|
114 |
+
|
115 |
+
if model in model_name_mapping:
|
116 |
+
return model_name_mapping[model]
|
117 |
+
|
118 |
+
cleaned = re.sub(r'\s*\(.*?\)', '', model) # Remove parenthetical info
|
119 |
+
cleaned = cleaned.replace('-', '_')
|
120 |
+
cleaned = ''.join(char for char in cleaned if char.isalnum() or char == '_')
|
121 |
+
|
122 |
+
return cleaned
|
123 |
+
|
124 |
+
def shorten_filename(filename, max_length=30):
|
125 |
+
"""
|
126 |
+
Shortens a filename to a specified maximum length
|
127 |
+
"""
|
128 |
+
base, ext = os.path.splitext(filename)
|
129 |
+
if len(base) <= max_length:
|
130 |
+
return filename
|
131 |
+
shortened = base[:15] + "..." + base[-10:] + ext
|
132 |
+
return shortened
|
133 |
+
|
134 |
+
def clean_filename(filename):
|
135 |
+
"""
|
136 |
+
Temizlenmiş dosya adını döndürür
|
137 |
+
"""
|
138 |
+
cleanup_patterns = [
|
139 |
+
r'_\d{8}_\d{6}_\d{6}$', # _20231215_123456_123456
|
140 |
+
r'_\d{14}$', # _20231215123456
|
141 |
+
r'_\d{10}$', # _1702658400
|
142 |
+
r'_\d+$' # Herhangi bir sayı
|
143 |
+
]
|
144 |
+
|
145 |
+
base, ext = os.path.splitext(filename)
|
146 |
+
for pattern in cleanup_patterns:
|
147 |
+
base = re.sub(pattern, '', base)
|
148 |
+
|
149 |
+
file_types = ['vocals', 'instrumental', 'drum', 'bass', 'other', 'effects', 'speech', 'music', 'dry', 'male', 'female']
|
150 |
+
for type_keyword in file_types:
|
151 |
+
base = base.replace(f'_{type_keyword}', '')
|
152 |
+
|
153 |
+
detected_type = None
|
154 |
+
for type_keyword in file_types:
|
155 |
+
if type_keyword in base.lower():
|
156 |
+
detected_type = type_keyword
|
157 |
+
break
|
158 |
+
|
159 |
+
clean_base = base.strip('_- ')
|
160 |
+
return clean_base, detected_type, ext
|
161 |
+
|
162 |
+
# Örnek kullanım (Kaggle veri setinden dosya okuma)
|
163 |
+
# Veri setiniz /kaggle/input/ altında olmalı
|
164 |
+
# Örnek: input_file = "/kaggle/input/your-dataset/sample_audio.wav"
|
165 |
+
# clean_base, detected_type, ext = clean_filename("example_vocals_20231215.wav")
|
166 |
+
# print(clean_base, detected_type, ext)
|
kaggle/download.py
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Kaggle için gerekli kütüphaneleri yükleme
|
2 |
+
!pip install yt-dlp validators requests
|
3 |
+
import os
|
4 |
+
import re
|
5 |
+
import validators
|
6 |
+
import yt_dlp
|
7 |
+
import requests
|
8 |
+
import shutil
|
9 |
+
|
10 |
+
# Kaggle dizin ayarları
|
11 |
+
BASE_DIR = "/kaggle/working/"
|
12 |
+
INPUT_DIR = os.path.join(BASE_DIR, "input")
|
13 |
+
COOKIE_PATH = os.path.join(BASE_DIR, "cookies.txt")
|
14 |
+
|
15 |
+
# Giriş dizinini oluştur
|
16 |
+
os.makedirs(INPUT_DIR, exist_ok=True)
|
17 |
+
|
18 |
+
# Basit bir i18n yerine geçici hata mesajları
|
19 |
+
def i18n(key):
|
20 |
+
messages = {
|
21 |
+
"invalid_url": "Geçersiz URL.",
|
22 |
+
"cookie_file_updated": "Çerez dosyası güncellendi.",
|
23 |
+
"cookie_installation_error": "Çerez dosyası yükleme hatası: {}",
|
24 |
+
"file_size_zero_error": "Dosya boyutu sıfır.",
|
25 |
+
"direct_download_failed": "Doğrudan indirme başarısız.",
|
26 |
+
"direct_download_error": "Doğrudan indirme hatası: {}",
|
27 |
+
"google_drive_error": "Google Drive indirme hatası: {}",
|
28 |
+
"download_error": "İndirme hatası: {}",
|
29 |
+
"wav_conversion_failed": "WAV dönüşümü başarısız.",
|
30 |
+
"download_success": "İndirme başarılı.",
|
31 |
+
"download_failed": "İndirme başarısız."
|
32 |
+
}
|
33 |
+
return messages.get(key, key)
|
34 |
+
|
35 |
+
# helpers.py'deki fonksiyonların sadeleştirilmiş hali
|
36 |
+
def clear_directory(directory):
|
37 |
+
if os.path.exists(directory):
|
38 |
+
for f in os.listdir(directory):
|
39 |
+
file_path = os.path.join(directory, f)
|
40 |
+
if os.path.isfile(file_path):
|
41 |
+
os.remove(file_path)
|
42 |
+
|
43 |
+
def clear_temp_folder(directory, exclude_items=[]):
|
44 |
+
if os.path.exists(directory):
|
45 |
+
for f in os.listdir(directory):
|
46 |
+
if f not in exclude_items:
|
47 |
+
file_path = os.path.join(directory, f)
|
48 |
+
if os.path.isfile(file_path):
|
49 |
+
os.remove(file_path)
|
50 |
+
|
51 |
+
def download_callback(url, download_type='direct', cookie_file=None):
|
52 |
+
# Geçici ve giriş dizinlerini temizle
|
53 |
+
clear_temp_folder("/tmp", exclude_items=["gradio", "config.json"])
|
54 |
+
clear_directory(INPUT_DIR)
|
55 |
+
os.makedirs(INPUT_DIR, exist_ok=True)
|
56 |
+
|
57 |
+
# URL'nin temel doğruluğunu kontrol et
|
58 |
+
if not url or not isinstance(url, str) or not (url.startswith('http://') or url.startswith('https://')):
|
59 |
+
return None, i18n("invalid_url"), None, None, None, None
|
60 |
+
|
61 |
+
# Çerez dosyasını yükle
|
62 |
+
if cookie_file is not None:
|
63 |
+
try:
|
64 |
+
with open(cookie_file, "rb") as f:
|
65 |
+
cookie_content = f.read()
|
66 |
+
with open(COOKIE_PATH, "wb") as f:
|
67 |
+
f.write(cookie_content)
|
68 |
+
print(i18n("cookie_file_updated"))
|
69 |
+
except Exception as e:
|
70 |
+
print(i18n("cookie_installation_error").format(str(e)))
|
71 |
+
|
72 |
+
wav_path = None
|
73 |
+
download_success = False
|
74 |
+
|
75 |
+
# 1. Discord CDN veya doğrudan dosya linki kontrolü
|
76 |
+
if any(url.endswith(ext) for ext in ['.wav', '.mp3', '.m4a', '.ogg', '.flac']):
|
77 |
+
try:
|
78 |
+
file_name = os.path.basename(url.split('?')[0])
|
79 |
+
output_path = os.path.join(INPUT_DIR, file_name)
|
80 |
+
response = requests.get(url, stream=True)
|
81 |
+
if response.status_code == 200:
|
82 |
+
with open(output_path, 'wb') as f:
|
83 |
+
for chunk in response.iter_content(chunk_size=8192):
|
84 |
+
if chunk:
|
85 |
+
f.write(chunk)
|
86 |
+
# Dosya WAV değilse, FFmpeg ile WAV'a dönüştür
|
87 |
+
if not file_name.endswith('.wav'):
|
88 |
+
wav_output = os.path.splitext(output_path)[0] + '.wav'
|
89 |
+
os.system(f'ffmpeg -i "{output_path}" -acodec pcm_s16le -ar 44100 "{wav_output}"')
|
90 |
+
if os.path.exists(wav_output):
|
91 |
+
os.remove(output_path)
|
92 |
+
output_path = wav_output
|
93 |
+
if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
|
94 |
+
wav_path = output_path
|
95 |
+
download_success = True
|
96 |
+
else:
|
97 |
+
raise Exception(i18n("file_size_zero_error"))
|
98 |
+
else:
|
99 |
+
raise Exception(i18n("direct_download_failed"))
|
100 |
+
except Exception as e:
|
101 |
+
error_msg = i18n("direct_download_error").format(str(e))
|
102 |
+
print(error_msg)
|
103 |
+
return None, error_msg, None, None, None, None
|
104 |
+
|
105 |
+
# 2. Google Drive linki yerine Kaggle veri seti kullanımı
|
106 |
+
# Not: Google Drive yerine Kaggle veri setinden dosya yüklenmesi önerilir
|
107 |
+
# Örnek: /kaggle/input/your-dataset/sample_audio.wav
|
108 |
+
# Bu kısmı atlayacağız, çünkü Kaggle'da Google Drive bağlantısı desteklenmez
|
109 |
+
|
110 |
+
# 3. YouTube ve diğer medya linkleri için yt-dlp
|
111 |
+
else:
|
112 |
+
ydl_opts = {
|
113 |
+
'format': 'bestaudio/best',
|
114 |
+
'outtmpl': os.path.join(INPUT_DIR, '%(title)s.%(ext)s'),
|
115 |
+
'postprocessors': [{
|
116 |
+
'key': 'FFmpegExtractAudio',
|
117 |
+
'preferredcodec': 'wav',
|
118 |
+
'preferredquality': '0'
|
119 |
+
}],
|
120 |
+
'cookiefile': COOKIE_PATH if os.path.exists(COOKIE_PATH) else None,
|
121 |
+
'nocheckcertificate': True,
|
122 |
+
'ignoreerrors': True,
|
123 |
+
'retries': 3
|
124 |
+
}
|
125 |
+
try:
|
126 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
127 |
+
info_dict = ydl.extract_info(url, download=True)
|
128 |
+
temp_path = ydl.prepare_filename(info_dict)
|
129 |
+
wav_path = os.path.splitext(temp_path)[0] + '.wav'
|
130 |
+
if os.path.exists(wav_path):
|
131 |
+
download_success = True
|
132 |
+
else:
|
133 |
+
raise Exception(i18n("wav_conversion_failed"))
|
134 |
+
except Exception as e:
|
135 |
+
error_msg = i18n("download_error").format(str(e))
|
136 |
+
print(error_msg)
|
137 |
+
return None, error_msg, None, None, None, None
|
138 |
+
|
139 |
+
# Başarılı indirme sonrası işlemleri
|
140 |
+
if download_success and wav_path:
|
141 |
+
# Gereksiz dosyaları temizle
|
142 |
+
for f in os.listdir(INPUT_DIR):
|
143 |
+
if f != os.path.basename(wav_path):
|
144 |
+
os.remove(os.path.join(INPUT_DIR, f))
|
145 |
+
|
146 |
+
# Kaggle'da Google Drive yerine /kaggle/working/ dizinine kaydet
|
147 |
+
print(f"Dosya kaydedildi: {wav_path}")
|
148 |
+
|
149 |
+
return (
|
150 |
+
wav_path,
|
151 |
+
i18n("download_success"),
|
152 |
+
wav_path,
|
153 |
+
wav_path,
|
154 |
+
wav_path,
|
155 |
+
wav_path
|
156 |
+
)
|
157 |
+
|
158 |
+
return None, i18n("download_failed"), None, None, None, None
|
159 |
+
|
160 |
+
# Örnek kullanım
|
161 |
+
# url = "https://example.com/sample.mp3"
|
162 |
+
# wav_path, message, _, _, _, _ = download_callback(url)
|
163 |
+
# print(message, wav_path)
|
kaggle/ensemble.py
ADDED
@@ -0,0 +1,314 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Kaggle için gerekli kütüphaneleri yükleme
|
2 |
+
!pip install librosa soundfile psutil tqdm
|
3 |
+
import os
|
4 |
+
import sys
|
5 |
+
import argparse
|
6 |
+
import numpy as np
|
7 |
+
import soundfile as sf
|
8 |
+
import librosa
|
9 |
+
import psutil
|
10 |
+
import gc
|
11 |
+
import traceback
|
12 |
+
from scipy.signal import stft, istft
|
13 |
+
from pathlib import Path
|
14 |
+
import tempfile
|
15 |
+
import shutil
|
16 |
+
import json
|
17 |
+
from tqdm import tqdm
|
18 |
+
import time
|
19 |
+
|
20 |
+
class AudioEnsembleEngine:
|
21 |
+
def __init__(self):
|
22 |
+
self.temp_dir = None
|
23 |
+
self.log_file = "/kaggle/working/ensemble_processor.log"
|
24 |
+
|
25 |
+
def __enter__(self):
|
26 |
+
self.temp_dir = tempfile.mkdtemp(prefix='audio_ensemble_', dir='/kaggle/working/')
|
27 |
+
self.setup_logging()
|
28 |
+
return self
|
29 |
+
|
30 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
31 |
+
if self.temp_dir and os.path.exists(self.temp_dir):
|
32 |
+
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
33 |
+
|
34 |
+
def setup_logging(self):
|
35 |
+
"""Initialize detailed logging system."""
|
36 |
+
with open(self.log_file, 'w') as f:
|
37 |
+
f.write("Audio Ensemble Processor Log\n")
|
38 |
+
f.write("="*50 + "\n")
|
39 |
+
f.write(f"System Memory: {psutil.virtual_memory().total/(1024**3):.2f} GB\n")
|
40 |
+
f.write(f"Python Version: {sys.version}\n\n")
|
41 |
+
|
42 |
+
def log_message(self, message):
|
43 |
+
"""Log messages with timestamp."""
|
44 |
+
with open(self.log_file, 'a') as f:
|
45 |
+
f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {message}\n")
|
46 |
+
|
47 |
+
def normalize_path(self, path):
|
48 |
+
"""Handle all path-related issues comprehensively."""
|
49 |
+
try:
|
50 |
+
# Kaggle'da dosya yolları /kaggle/input/ veya /kaggle/working/ altında
|
51 |
+
path = str(Path(path).absolute().resolve())
|
52 |
+
|
53 |
+
# Handle problematic characters
|
54 |
+
if any(char in path for char in '[]()|&; '):
|
55 |
+
base, ext = os.path.splitext(path)
|
56 |
+
safe_name = f"{hash(base)}{ext}"
|
57 |
+
temp_path = os.path.join(self.temp_dir, safe_name)
|
58 |
+
|
59 |
+
if not os.path.exists(temp_path):
|
60 |
+
data, sr = librosa.load(path, sr=None, mono=False)
|
61 |
+
sf.write(temp_path, data.T, sr)
|
62 |
+
|
63 |
+
return temp_path
|
64 |
+
|
65 |
+
return path
|
66 |
+
except Exception as e:
|
67 |
+
self.log_message(f"Path normalization failed: {str(e)}")
|
68 |
+
return path
|
69 |
+
|
70 |
+
def validate_inputs(self, files, method, output_path):
|
71 |
+
"""Comprehensive input validation with detailed error reporting."""
|
72 |
+
errors = []
|
73 |
+
valid_methods = [
|
74 |
+
'avg_wave', 'median_wave', 'max_wave', 'min_wave',
|
75 |
+
'max_fft', 'min_fft', 'median_fft'
|
76 |
+
]
|
77 |
+
|
78 |
+
# Method validation
|
79 |
+
if method not in valid_methods:
|
80 |
+
errors.append(f"Invalid method '{method}'. Available: {valid_methods}")
|
81 |
+
|
82 |
+
# File validation
|
83 |
+
valid_files = []
|
84 |
+
sample_rates = set()
|
85 |
+
durations = []
|
86 |
+
channels_set = set()
|
87 |
+
|
88 |
+
for f in files:
|
89 |
+
try:
|
90 |
+
f_normalized = self.normalize_path(f)
|
91 |
+
|
92 |
+
# Basic checks
|
93 |
+
if not os.path.exists(f_normalized):
|
94 |
+
errors.append(f"File not found: {f_normalized}")
|
95 |
+
continue
|
96 |
+
|
97 |
+
if os.path.getsize(f_normalized) == 0:
|
98 |
+
errors.append(f"Empty file: {f_normalized}")
|
99 |
+
continue
|
100 |
+
|
101 |
+
# Audio file validation
|
102 |
+
try:
|
103 |
+
with sf.SoundFile(f_normalized) as sf_file:
|
104 |
+
sr = sf_file.samplerate
|
105 |
+
frames = sf_file.frames
|
106 |
+
channels = sf_file.channels
|
107 |
+
except Exception as e:
|
108 |
+
errors.append(f"Invalid audio file {f_normalized}: {str(e)}")
|
109 |
+
continue
|
110 |
+
|
111 |
+
# Audio characteristics
|
112 |
+
if channels != 2:
|
113 |
+
errors.append(f"File must be stereo (has {channels} channels): {f_normalized}")
|
114 |
+
continue
|
115 |
+
|
116 |
+
sample_rates.add(sr)
|
117 |
+
durations.append(frames / sr)
|
118 |
+
channels_set.add(channels)
|
119 |
+
valid_files.append(f_normalized)
|
120 |
+
|
121 |
+
except Exception as e:
|
122 |
+
errors.append(f"Error processing {f}: {str(e)}")
|
123 |
+
continue
|
124 |
+
|
125 |
+
# Final checks
|
126 |
+
if len(valid_files) < 2:
|
127 |
+
errors.append("At least 2 valid files required")
|
128 |
+
|
129 |
+
if len(sample_rates) > 1:
|
130 |
+
errors.append(f"Sample rate mismatch: {sample_rates}")
|
131 |
+
|
132 |
+
if len(channels_set) > 1:
|
133 |
+
errors.append(f"Channel count mismatch: {channels_set}")
|
134 |
+
|
135 |
+
# Output path validation
|
136 |
+
try:
|
137 |
+
output_path = self.normalize_path(output_path)
|
138 |
+
output_dir = os.path.dirname(output_path) or '/kaggle/working/'
|
139 |
+
|
140 |
+
if not os.path.exists(output_dir):
|
141 |
+
os.makedirs(output_dir, exist_ok=True)
|
142 |
+
|
143 |
+
if not os.access(output_dir, os.W_OK):
|
144 |
+
errors.append(f"No write permission for output directory: {output_dir}")
|
145 |
+
except Exception as e:
|
146 |
+
errors.append(f"Output path error: {str(e)}")
|
147 |
+
|
148 |
+
if errors:
|
149 |
+
error_msg = "\n".join(errors)
|
150 |
+
self.log_message(f"Validation failed:\n{error_msg}")
|
151 |
+
raise ValueError(error_msg)
|
152 |
+
|
153 |
+
target_sr = sample_rates.pop() if sample_rates else 44100
|
154 |
+
return valid_files, target_sr, min(durations) if durations else None
|
155 |
+
|
156 |
+
def process_waveform(self, chunks, method, weights=None):
|
157 |
+
"""All waveform domain processing methods."""
|
158 |
+
if method == 'avg_wave':
|
159 |
+
if weights is not None:
|
160 |
+
return np.average(chunks, axis=0, weights=weights)
|
161 |
+
return np.mean(chunks, axis=0)
|
162 |
+
elif method == 'median_wave':
|
163 |
+
return np.median(chunks, axis=0)
|
164 |
+
elif method == 'max_wave':
|
165 |
+
return np.max(chunks, axis=0)
|
166 |
+
elif method == 'min_wave':
|
167 |
+
return np.min(chunks, axis=0)
|
168 |
+
|
169 |
+
def process_spectral(self, chunks, method):
|
170 |
+
"""All frequency domain processing methods."""
|
171 |
+
specs = []
|
172 |
+
for c in chunks:
|
173 |
+
channel_specs = []
|
174 |
+
for channel in range(c.shape[0]):
|
175 |
+
_, _, Zxx = stft(c[channel], nperseg=1024, noverlap=512)
|
176 |
+
channel_specs.append(Zxx)
|
177 |
+
specs.append(np.array(channel_specs))
|
178 |
+
|
179 |
+
specs = np.array(specs)
|
180 |
+
mag = np.abs(specs)
|
181 |
+
|
182 |
+
if method == 'max_fft':
|
183 |
+
combined_mag = np.max(mag, axis=0)
|
184 |
+
elif method == 'min_fft':
|
185 |
+
combined_mag = np.min(mag, axis=0)
|
186 |
+
elif method == 'median_fft':
|
187 |
+
combined_mag = np.median(mag, axis=0)
|
188 |
+
|
189 |
+
# Use phase from first file
|
190 |
+
combined_spec = combined_mag * np.exp(1j * np.angle(specs[0]))
|
191 |
+
|
192 |
+
# ISTFT reconstruction
|
193 |
+
reconstructed = np.zeros((combined_spec.shape[0], chunks[0].shape[1]))
|
194 |
+
for channel in range(combined_spec.shape[0]):
|
195 |
+
_, xrec = istft(combined_spec[channel], nperseg=1024, noverlap=512)
|
196 |
+
reconstructed[channel] = xrec[:chunks[0].shape[1]]
|
197 |
+
|
198 |
+
return reconstructed
|
199 |
+
|
200 |
+
def run_ensemble(self, files, method, output_path, weights=None, buffer_size=32768):
|
201 |
+
"""Core ensemble processing with maximum robustness."""
|
202 |
+
try:
|
203 |
+
# Validate and prepare inputs
|
204 |
+
valid_files, target_sr, duration = self.validate_inputs(files, method, output_path)
|
205 |
+
output_path = self.normalize_path(output_path)
|
206 |
+
|
207 |
+
self.log_message(f"Starting ensemble with method: {method}")
|
208 |
+
self.log_message(f"Input files: {json.dumps(valid_files, indent=2)}")
|
209 |
+
self.log_message(f"Target sample rate: {target_sr}Hz")
|
210 |
+
self.log_message(f"Output path: {output_path}")
|
211 |
+
|
212 |
+
# Prepare weights
|
213 |
+
if weights and len(weights) == len(valid_files):
|
214 |
+
weights = np.array(weights, dtype=np.float32)
|
215 |
+
weights /= weights.sum() # Normalize
|
216 |
+
self.log_message(f"Using weights: {weights}")
|
217 |
+
else:
|
218 |
+
weights = None
|
219 |
+
|
220 |
+
# Open all files
|
221 |
+
readers = []
|
222 |
+
try:
|
223 |
+
readers = [sf.SoundFile(f) for f in valid_files]
|
224 |
+
shortest_frames = min(int(duration * r.samplerate) for r in readers)
|
225 |
+
|
226 |
+
# Prepare output
|
227 |
+
with sf.SoundFile(output_path, 'w', target_sr, 2, 'PCM_24') as outfile:
|
228 |
+
# Process in chunks with progress bar
|
229 |
+
progress = tqdm(total=shortest_frames, unit='samples', desc='Processing')
|
230 |
+
|
231 |
+
for pos in range(0, shortest_frames, buffer_size):
|
232 |
+
chunk_size = min(buffer_size, shortest_frames - pos)
|
233 |
+
|
234 |
+
# Read aligned chunks from all files
|
235 |
+
chunks = []
|
236 |
+
for r in readers:
|
237 |
+
r.seek(pos)
|
238 |
+
data = r.read(chunk_size)
|
239 |
+
if data.size == 0:
|
240 |
+
data = np.zeros((chunk_size, 2))
|
241 |
+
chunks.append(data.T) # Transpose to (channels, samples)
|
242 |
+
|
243 |
+
chunks = np.array(chunks)
|
244 |
+
|
245 |
+
# Process based on method type
|
246 |
+
if method.endswith('_fft'):
|
247 |
+
result = self.process_spectral(chunks, method)
|
248 |
+
else:
|
249 |
+
result = self.process_waveform(chunks, method, weights)
|
250 |
+
|
251 |
+
# Write output
|
252 |
+
outfile.write(result.T) # Transpose back to (samples, channels)
|
253 |
+
|
254 |
+
# Clean up and update progress
|
255 |
+
del chunks, result
|
256 |
+
if pos % (5 * buffer_size) == 0:
|
257 |
+
gc.collect()
|
258 |
+
|
259 |
+
progress.update(chunk_size)
|
260 |
+
|
261 |
+
progress.close()
|
262 |
+
|
263 |
+
self.log_message(f"Successfully created output: {output_path}")
|
264 |
+
print(f"\nEnsemble completed successfully: {output_path}")
|
265 |
+
return True
|
266 |
+
|
267 |
+
except Exception as e:
|
268 |
+
self.log_message(f"Processing error: {str(e)}\n{traceback.format_exc()}")
|
269 |
+
raise
|
270 |
+
finally:
|
271 |
+
for r in readers:
|
272 |
+
try:
|
273 |
+
r.close()
|
274 |
+
except:
|
275 |
+
pass
|
276 |
+
|
277 |
+
except Exception as e:
|
278 |
+
self.log_message(f"Fatal error: {str(e)}\n{traceback.format_exc()}")
|
279 |
+
print(f"\nError during processing: {str(e)}", file=sys.stderr)
|
280 |
+
return False
|
281 |
+
|
282 |
+
def main():
|
283 |
+
parser = argparse.ArgumentParser(
|
284 |
+
description='Ultimate Audio Ensemble Processor - Supports all ensemble methods',
|
285 |
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter
|
286 |
+
)
|
287 |
+
parser.add_argument('--files', nargs='+', required=True,
|
288 |
+
help='Input audio files (supports special characters)')
|
289 |
+
parser.add_argument('--type', required=True,
|
290 |
+
choices=['avg_wave', 'median_wave', 'max_wave', 'min_wave',
|
291 |
+
'max_fft', 'min_fft', 'median_fft'],
|
292 |
+
help='Ensemble method to use')
|
293 |
+
parser.add_argument('--weights', nargs='+', type=float,
|
294 |
+
help='Relative weights for each input file')
|
295 |
+
parser.add_argument('--output', required=True,
|
296 |
+
help='Output file path')
|
297 |
+
parser.add_argument('--buffer', type=int, default=32768,
|
298 |
+
help='Buffer size in samples (larger=faster but uses more memory)')
|
299 |
+
|
300 |
+
args = parser.parse_args()
|
301 |
+
|
302 |
+
with AudioEnsembleEngine() as engine:
|
303 |
+
success = engine.run_ensemble(
|
304 |
+
files=args.files,
|
305 |
+
method=args.type,
|
306 |
+
output_path=args.output,
|
307 |
+
weights=args.weights,
|
308 |
+
buffer_size=args.buffer
|
309 |
+
)
|
310 |
+
|
311 |
+
sys.exit(0 if success else 1)
|
312 |
+
|
313 |
+
if __name__ == "__main__":
|
314 |
+
main()
|
kaggle/test
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
main.py
CHANGED
@@ -5,21 +5,17 @@ import time
|
|
5 |
import sys
|
6 |
import random
|
7 |
import argparse
|
8 |
-
import time
|
9 |
import librosa
|
10 |
from tqdm.auto import tqdm
|
11 |
-
import sys
|
12 |
-
import os
|
13 |
-
import glob
|
14 |
import torch
|
15 |
import soundfile as sf
|
16 |
import torch.nn as nn
|
17 |
from datetime import datetime
|
18 |
import numpy as np
|
19 |
-
import librosa
|
20 |
import shutil
|
21 |
from gui import create_interface
|
22 |
from pyngrok import ngrok
|
|
|
23 |
|
24 |
import warnings
|
25 |
warnings.filterwarnings("ignore")
|
@@ -39,9 +35,9 @@ def start_gradio(port, share=False):
|
|
39 |
inline=False
|
40 |
)
|
41 |
|
42 |
-
def start_localtunnel(port):
|
43 |
"""Starts the Gradio interface with localtunnel sharing."""
|
44 |
-
print(
|
45 |
os.system('npm install -g localtunnel &>/dev/null')
|
46 |
|
47 |
with open('url.txt', 'w') as file:
|
@@ -53,44 +49,47 @@ def start_localtunnel(port):
|
|
53 |
with open('url.txt', 'r') as file:
|
54 |
tunnel_url = file.read().replace("your url is: ", "").strip()
|
55 |
|
56 |
-
print(
|
57 |
-
print(
|
58 |
|
59 |
start_gradio(port, share=False)
|
60 |
|
61 |
-
def start_ngrok(port, ngrok_token):
|
62 |
"""Starts the Gradio interface with ngrok sharing."""
|
63 |
-
print(
|
64 |
try:
|
65 |
ngrok.set_auth_token(ngrok_token)
|
66 |
ngrok.kill()
|
67 |
tunnel = ngrok.connect(port)
|
68 |
-
print(
|
69 |
|
70 |
start_gradio(port, share=False)
|
71 |
except Exception as e:
|
72 |
-
print(
|
73 |
sys.exit(1)
|
74 |
|
75 |
def main(method="gradio", port=None, ngrok_token=""):
|
76 |
"""Main entry point for the application."""
|
|
|
|
|
|
|
77 |
# Portu otomatik belirle veya kullanıcıdan geleni kullan
|
78 |
port = port or generate_random_port()
|
79 |
-
print(
|
80 |
|
81 |
# Paylaşım yöntemine göre işlem yap
|
82 |
if method == "gradio":
|
83 |
-
print("
|
84 |
start_gradio(port, share=True)
|
85 |
elif method == "localtunnel":
|
86 |
-
start_localtunnel(port)
|
87 |
elif method == "ngrok":
|
88 |
if not ngrok_token:
|
89 |
-
print("
|
90 |
sys.exit(1)
|
91 |
-
start_ngrok(port, ngrok_token)
|
92 |
else:
|
93 |
-
print("
|
94 |
sys.exit(1)
|
95 |
|
96 |
# Sürekli çalışır durumda tut (gerekirse)
|
@@ -98,11 +97,10 @@ def main(method="gradio", port=None, ngrok_token=""):
|
|
98 |
while True:
|
99 |
time.sleep(5)
|
100 |
except KeyboardInterrupt:
|
101 |
-
print("
|
102 |
sys.exit(0)
|
103 |
|
104 |
if __name__ == "__main__":
|
105 |
-
import argparse
|
106 |
parser = argparse.ArgumentParser(description="Music Source Separation Web UI")
|
107 |
parser.add_argument("--method", type=str, default="gradio", choices=["gradio", "localtunnel", "ngrok"], help="Sharing method (default: gradio)")
|
108 |
parser.add_argument("--port", type=int, default=None, help="Server port (default: random between 1000-9000)")
|
|
|
5 |
import sys
|
6 |
import random
|
7 |
import argparse
|
|
|
8 |
import librosa
|
9 |
from tqdm.auto import tqdm
|
|
|
|
|
|
|
10 |
import torch
|
11 |
import soundfile as sf
|
12 |
import torch.nn as nn
|
13 |
from datetime import datetime
|
14 |
import numpy as np
|
|
|
15 |
import shutil
|
16 |
from gui import create_interface
|
17 |
from pyngrok import ngrok
|
18 |
+
from assets.i18n.i18n import I18nAuto # I18nAuto'yu içe aktar
|
19 |
|
20 |
import warnings
|
21 |
warnings.filterwarnings("ignore")
|
|
|
35 |
inline=False
|
36 |
)
|
37 |
|
38 |
+
def start_localtunnel(port, i18n):
|
39 |
"""Starts the Gradio interface with localtunnel sharing."""
|
40 |
+
print(i18n("starting_localtunnel").format(port=port))
|
41 |
os.system('npm install -g localtunnel &>/dev/null')
|
42 |
|
43 |
with open('url.txt', 'w') as file:
|
|
|
49 |
with open('url.txt', 'r') as file:
|
50 |
tunnel_url = file.read().replace("your url is: ", "").strip()
|
51 |
|
52 |
+
print(i18n("share_link").format(url=tunnel_url))
|
53 |
+
print(i18n("password_ip").format(ip=endpoint_ip))
|
54 |
|
55 |
start_gradio(port, share=False)
|
56 |
|
57 |
+
def start_ngrok(port, ngrok_token, i18n):
|
58 |
"""Starts the Gradio interface with ngrok sharing."""
|
59 |
+
print(i18n("starting_ngrok").format(port=port))
|
60 |
try:
|
61 |
ngrok.set_auth_token(ngrok_token)
|
62 |
ngrok.kill()
|
63 |
tunnel = ngrok.connect(port)
|
64 |
+
print(i18n("ngrok_url").format(url=tunnel.public_url))
|
65 |
|
66 |
start_gradio(port, share=False)
|
67 |
except Exception as e:
|
68 |
+
print(i18n("ngrok_error").format(error=str(e)))
|
69 |
sys.exit(1)
|
70 |
|
71 |
def main(method="gradio", port=None, ngrok_token=""):
|
72 |
"""Main entry point for the application."""
|
73 |
+
# I18nAuto'yu başlat
|
74 |
+
i18n = I18nAuto()
|
75 |
+
|
76 |
# Portu otomatik belirle veya kullanıcıdan geleni kullan
|
77 |
port = port or generate_random_port()
|
78 |
+
print(i18n("selected_port").format(port=port))
|
79 |
|
80 |
# Paylaşım yöntemine göre işlem yap
|
81 |
if method == "gradio":
|
82 |
+
print(i18n("starting_gradio_with_sharing"))
|
83 |
start_gradio(port, share=True)
|
84 |
elif method == "localtunnel":
|
85 |
+
start_localtunnel(port, i18n)
|
86 |
elif method == "ngrok":
|
87 |
if not ngrok_token:
|
88 |
+
print(i18n("ngrok_token_required"))
|
89 |
sys.exit(1)
|
90 |
+
start_ngrok(port, ngrok_token, i18n)
|
91 |
else:
|
92 |
+
print(i18n("invalid_method"))
|
93 |
sys.exit(1)
|
94 |
|
95 |
# Sürekli çalışır durumda tut (gerekirse)
|
|
|
97 |
while True:
|
98 |
time.sleep(5)
|
99 |
except KeyboardInterrupt:
|
100 |
+
print(i18n("process_stopped"))
|
101 |
sys.exit(0)
|
102 |
|
103 |
if __name__ == "__main__":
|
|
|
104 |
parser = argparse.ArgumentParser(description="Music Source Separation Web UI")
|
105 |
parser.add_argument("--method", type=str, default="gradio", choices=["gradio", "localtunnel", "ngrok"], help="Sharing method (default: gradio)")
|
106 |
parser.add_argument("--port", type=int, default=None, help="Server port (default: random between 1000-9000)")
|
model.py
CHANGED
@@ -53,6 +53,36 @@ def download_file(url):
|
|
53 |
# Model konfigurasyonlarını kategorize bir sözlükte tut
|
54 |
MODEL_CONFIGS = {
|
55 |
"Vocal Models": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
'VOCALS-InstVocHQ': {
|
57 |
'model_type': 'mdx23c',
|
58 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_vocals_mdx23c.yaml'),
|
@@ -245,6 +275,16 @@ MODEL_CONFIGS = {
|
|
245 |
}
|
246 |
},
|
247 |
"Instrumental Models": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
'INST-Mel-Roformer v1 (by unwa)': {
|
249 |
'model_type': 'mel_band_roformer',
|
250 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_melbandroformer_inst.yaml'),
|
@@ -255,6 +295,26 @@ MODEL_CONFIGS = {
|
|
255 |
],
|
256 |
'needs_conf_edit': True
|
257 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
'INST-Mel-Roformer v2 (by unwa)': {
|
259 |
'model_type': 'mel_band_roformer',
|
260 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_melbandroformer_inst_v2.yaml'),
|
@@ -528,6 +588,16 @@ MODEL_CONFIGS = {
|
|
528 |
'https://huggingface.co/GaboxR67/MelBandRoformers/resolve/main/melbandroformers/instrumental/denoisedebleed.ckpt'
|
529 |
],
|
530 |
'needs_conf_edit': True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
531 |
}
|
532 |
},
|
533 |
"Dereverb Models": {
|
@@ -592,7 +662,7 @@ MODEL_CONFIGS = {
|
|
592 |
'needs_conf_edit': True
|
593 |
}
|
594 |
},
|
595 |
-
"
|
596 |
'KARAOKE-MelBand-Roformer (by aufr33 & viperx)': {
|
597 |
'model_type': 'mel_band_roformer',
|
598 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_mel_band_roformer_karaoke.yaml'),
|
@@ -603,6 +673,18 @@ MODEL_CONFIGS = {
|
|
603 |
],
|
604 |
'needs_conf_edit': True
|
605 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
606 |
'OTHER-BS-Roformer_1053 (by viperx)': {
|
607 |
'model_type': 'bs_roformer',
|
608 |
'config_path': os.path.join(CHECKPOINT_DIR, 'model_bs_roformer_ep_937_sdr_10.5309.yaml'),
|
@@ -633,6 +715,16 @@ MODEL_CONFIGS = {
|
|
633 |
],
|
634 |
'needs_conf_edit': False
|
635 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
636 |
'DRUMSEP-MDX23C_DrumSep_6stem (by aufr33 & jarredou)': {
|
637 |
'model_type': 'mdx23c',
|
638 |
'config_path': os.path.join(CHECKPOINT_DIR, 'aufr33-jarredou_DrumSep_model_mdx23c_ep_141_sdr_10.8059.yaml'),
|
@@ -643,16 +735,6 @@ MODEL_CONFIGS = {
|
|
643 |
],
|
644 |
'needs_conf_edit': False
|
645 |
},
|
646 |
-
'bleed_suppressor_v1 (by unwa)': {
|
647 |
-
'model_type': 'mel_band_roformer',
|
648 |
-
'config_path': os.path.join(CHECKPOINT_DIR, 'config_bleed_suppressor_v1.yaml'),
|
649 |
-
'start_check_point': os.path.join(CHECKPOINT_DIR, 'bleed_suppressor_v1.ckpt'),
|
650 |
-
'download_urls': [
|
651 |
-
'https://huggingface.co/ASesYusuf1/MODELS/resolve/main/bleed_suppressor_v1.ckpt',
|
652 |
-
'https://huggingface.co/ASesYusuf1/MODELS/resolve/main/config_bleed_suppressor_v1.yaml'
|
653 |
-
],
|
654 |
-
'needs_conf_edit': True
|
655 |
-
},
|
656 |
'SYH99999/MelBandRoformerSYHFTB1_Model1 (by Amane)': {
|
657 |
'model_type': 'mel_band_roformer',
|
658 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config.yaml'),
|
@@ -682,16 +764,6 @@ MODEL_CONFIGS = {
|
|
682 |
'https://huggingface.co/SYH99999/MelBandRoformerSYHFTB1/resolve/main/model3.ckpt'
|
683 |
],
|
684 |
'needs_conf_edit': True
|
685 |
-
},
|
686 |
-
'KaraokeGabox': {
|
687 |
-
'model_type': 'mel_band_roformer',
|
688 |
-
'config_path': os.path.join(CHECKPOINT_DIR, 'config_mel_band_roformer_karaoke.yaml'),
|
689 |
-
'start_check_point': os.path.join(CHECKPOINT_DIR, 'KaraokeGabox.ckpt'),
|
690 |
-
'download_urls': [
|
691 |
-
'https://github.com/deton24/Colab-for-new-MDX_UVR_models/releases/download/v1.0.0/config_mel_band_roformer_karaoke.yaml',
|
692 |
-
'https://huggingface.co/GaboxR67/MelBandRoformers/blob/main/melbandroformers/experimental/KaraokeGabox.ckpt'
|
693 |
-
],
|
694 |
-
'needs_conf_edit': True
|
695 |
}
|
696 |
}
|
697 |
}
|
|
|
53 |
# Model konfigurasyonlarını kategorize bir sözlükte tut
|
54 |
MODEL_CONFIGS = {
|
55 |
"Vocal Models": {
|
56 |
+
'VOCALS-big_beta6X (by Unwa)': {
|
57 |
+
'model_type': 'mel_band_roformer',
|
58 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'big_beta6x.yaml'),
|
59 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'big_beta6x.ckpt'),
|
60 |
+
'download_urls': [
|
61 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-big/resolve/main/big_beta6x.yaml',
|
62 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-big/resolve/main/big_beta6x.ckpt'
|
63 |
+
],
|
64 |
+
'needs_conf_edit': False
|
65 |
+
},
|
66 |
+
'VOCALS-big_beta6 (by Unwa)': {
|
67 |
+
'model_type': 'mel_band_roformer',
|
68 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'big_beta6.yaml'),
|
69 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'big_beta6.ckpt'),
|
70 |
+
'download_urls': [
|
71 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-big/resolve/main/big_beta6.yaml',
|
72 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-big/resolve/main/big_beta6.ckpt'
|
73 |
+
],
|
74 |
+
'needs_conf_edit': False
|
75 |
+
},
|
76 |
+
'VOCALS-Mel-Roformer FT 3 Preview (by unwa)': {
|
77 |
+
'model_type': 'mel_band_roformer',
|
78 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'config_kimmel_unwa_ft.yaml'),
|
79 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'kimmel_unwa_ft3_prev.ckpt'),
|
80 |
+
'download_urls': [
|
81 |
+
'https://huggingface.co/pcunwa/Kim-Mel-Band-Roformer-FT/resolve/main/config_kimmel_unwa_ft.yaml',
|
82 |
+
'https://huggingface.co/pcunwa/Kim-Mel-Band-Roformer-FT/resolve/main/kimmel_unwa_ft3_prev.ckpt'
|
83 |
+
],
|
84 |
+
'needs_conf_edit': False
|
85 |
+
},
|
86 |
'VOCALS-InstVocHQ': {
|
87 |
'model_type': 'mdx23c',
|
88 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_vocals_mdx23c.yaml'),
|
|
|
275 |
}
|
276 |
},
|
277 |
"Instrumental Models": {
|
278 |
+
'Inst_GaboxFv8 (by Gabox)': {
|
279 |
+
'model_type': 'mel_band_roformer',
|
280 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'inst_gabox.yaml'),
|
281 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'Inst_GaboxFv8.ckpt'),
|
282 |
+
'download_urls': [
|
283 |
+
'https://huggingface.co/GaboxR67/MelBandRoformers/resolve/main/melbandroformers/instrumental/Inst_GaboxFv8.ckpt',
|
284 |
+
'https://huggingface.co/GaboxR67/MelBandRoformers/resolve/main/melbandroformers/instrumental/inst_gabox.yaml'
|
285 |
+
],
|
286 |
+
'needs_conf_edit': True
|
287 |
+
},
|
288 |
'INST-Mel-Roformer v1 (by unwa)': {
|
289 |
'model_type': 'mel_band_roformer',
|
290 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_melbandroformer_inst.yaml'),
|
|
|
295 |
],
|
296 |
'needs_conf_edit': True
|
297 |
},
|
298 |
+
'INST-Mel-Roformer v1e+ (by unwa)': {
|
299 |
+
'model_type': 'mel_band_roformer',
|
300 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'config_melbandroformer_inst.yaml'),
|
301 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'inst_v1e_plus.ckpt'),
|
302 |
+
'download_urls': [
|
303 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-Inst/resolve/main/inst_v1e_plus.ckpt',
|
304 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-Inst/raw/main/config_melbandroformer_inst.yaml'
|
305 |
+
],
|
306 |
+
'needs_conf_edit': True
|
307 |
+
},
|
308 |
+
'INST-Mel-Roformer v1+ (by unwa)': {
|
309 |
+
'model_type': 'mel_band_roformer',
|
310 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'config_melbandroformer_inst.yaml'),
|
311 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'inst_v1_plus_test.ckpt'),
|
312 |
+
'download_urls': [
|
313 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-Inst/resolve/main/inst_v1_plus_test.ckpt',
|
314 |
+
'https://huggingface.co/pcunwa/Mel-Band-Roformer-Inst/raw/main/config_melbandroformer_inst.yaml'
|
315 |
+
],
|
316 |
+
'needs_conf_edit': True
|
317 |
+
},
|
318 |
'INST-Mel-Roformer v2 (by unwa)': {
|
319 |
'model_type': 'mel_band_roformer',
|
320 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_melbandroformer_inst_v2.yaml'),
|
|
|
588 |
'https://huggingface.co/GaboxR67/MelBandRoformers/resolve/main/melbandroformers/instrumental/denoisedebleed.ckpt'
|
589 |
],
|
590 |
'needs_conf_edit': True
|
591 |
+
},
|
592 |
+
'bleed_suppressor_v1 (by unwa)': {
|
593 |
+
'model_type': 'mel_band_roformer',
|
594 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'config_bleed_suppressor_v1.yaml'),
|
595 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'bleed_suppressor_v1.ckpt'),
|
596 |
+
'download_urls': [
|
597 |
+
'https://huggingface.co/ASesYusuf1/MODELS/resolve/main/bleed_suppressor_v1.ckpt',
|
598 |
+
'https://huggingface.co/ASesYusuf1/MODELS/resolve/main/config_bleed_suppressor_v1.yaml'
|
599 |
+
],
|
600 |
+
'needs_conf_edit': True
|
601 |
}
|
602 |
},
|
603 |
"Dereverb Models": {
|
|
|
662 |
'needs_conf_edit': True
|
663 |
}
|
664 |
},
|
665 |
+
"Karaoke": {
|
666 |
'KARAOKE-MelBand-Roformer (by aufr33 & viperx)': {
|
667 |
'model_type': 'mel_band_roformer',
|
668 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config_mel_band_roformer_karaoke.yaml'),
|
|
|
673 |
],
|
674 |
'needs_conf_edit': True
|
675 |
},
|
676 |
+
'KaraokeGabox': {
|
677 |
+
'model_type': 'mel_band_roformer',
|
678 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'config_mel_band_roformer_karaoke.yaml'),
|
679 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'KaraokeGabox.ckpt'),
|
680 |
+
'download_urls': [
|
681 |
+
'https://github.com/deton24/Colab-for-new-MDX_UVR_models/releases/download/v1.0.0/config_mel_band_roformer_karaoke.yaml',
|
682 |
+
'https://huggingface.co/GaboxR67/MelBandRoformers/blob/main/melbandroformers/experimental/KaraokeGabox.ckpt'
|
683 |
+
],
|
684 |
+
'needs_conf_edit': True
|
685 |
+
}
|
686 |
+
},
|
687 |
+
"Other Models": {
|
688 |
'OTHER-BS-Roformer_1053 (by viperx)': {
|
689 |
'model_type': 'bs_roformer',
|
690 |
'config_path': os.path.join(CHECKPOINT_DIR, 'model_bs_roformer_ep_937_sdr_10.5309.yaml'),
|
|
|
715 |
],
|
716 |
'needs_conf_edit': False
|
717 |
},
|
718 |
+
'CINEMATIC-BandIt_v2 multi (by kwatcharasupat)': {
|
719 |
+
'model_type': 'bandit_v2',
|
720 |
+
'config_path': os.path.join(CHECKPOINT_DIR, 'config_dnr_bandit_v2_mus64.yaml'),
|
721 |
+
'start_check_point': os.path.join(CHECKPOINT_DIR, 'checkpoint-multi_state_dict.ckpt'),
|
722 |
+
'download_urls': [
|
723 |
+
'https://huggingface.co/jarredou/banditv2_state_dicts_only/resolve/main/checkpoint-multi_state_dict.ckpt',
|
724 |
+
'https://raw.githubusercontent.com/ZFTurbo/Music-Source-Separation-Training/refs/heads/main/configs/config_dnr_bandit_v2_mus64.yaml'
|
725 |
+
],
|
726 |
+
'needs_conf_edit': True
|
727 |
+
},
|
728 |
'DRUMSEP-MDX23C_DrumSep_6stem (by aufr33 & jarredou)': {
|
729 |
'model_type': 'mdx23c',
|
730 |
'config_path': os.path.join(CHECKPOINT_DIR, 'aufr33-jarredou_DrumSep_model_mdx23c_ep_141_sdr_10.8059.yaml'),
|
|
|
735 |
],
|
736 |
'needs_conf_edit': False
|
737 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
738 |
'SYH99999/MelBandRoformerSYHFTB1_Model1 (by Amane)': {
|
739 |
'model_type': 'mel_band_roformer',
|
740 |
'config_path': os.path.join(CHECKPOINT_DIR, 'config.yaml'),
|
|
|
764 |
'https://huggingface.co/SYH99999/MelBandRoformerSYHFTB1/resolve/main/model3.ckpt'
|
765 |
],
|
766 |
'needs_conf_edit': True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
767 |
}
|
768 |
}
|
769 |
}
|
processing.py
CHANGED
@@ -5,12 +5,16 @@ import time
|
|
5 |
import gc
|
6 |
import shutil
|
7 |
import sys
|
|
|
|
|
|
|
8 |
current_dir = os.path.dirname(os.path.abspath(__file__))
|
9 |
sys.path.append(current_dir)
|
10 |
|
11 |
from datetime import datetime
|
12 |
-
from helpers import INPUT_DIR, OLD_OUTPUT_DIR, ENSEMBLE_DIR, AUTO_ENSEMBLE_TEMP, move_old_files, clear_directory, BASE_DIR
|
13 |
from model import get_model_config
|
|
|
14 |
import torch
|
15 |
import yaml
|
16 |
import gradio as gr
|
@@ -29,33 +33,133 @@ from tqdm import tqdm
|
|
29 |
from google.oauth2.credentials import Credentials
|
30 |
import tempfile
|
31 |
from urllib.parse import urlparse, quote
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
import warnings
|
35 |
warnings.filterwarnings("ignore")
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
try:
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
cmd_parts = [
|
60 |
"python", INFERENCE_PATH,
|
61 |
"--model_type", model_type,
|
@@ -63,6 +167,9 @@ def run_command_and_process_files(model_type, config_path, start_check_point, IN
|
|
63 |
"--start_check_point", start_check_point,
|
64 |
"--input_folder", INPUT_DIR,
|
65 |
"--store_dir", OUTPUT_DIR,
|
|
|
|
|
|
|
66 |
]
|
67 |
if extract_instrumental:
|
68 |
cmd_parts.append("--extract_instrumental")
|
@@ -71,42 +178,31 @@ def run_command_and_process_files(model_type, config_path, start_check_point, IN
|
|
71 |
if demud_phaseremix_inst:
|
72 |
cmd_parts.append("--demud_phaseremix_inst")
|
73 |
|
74 |
-
|
|
|
75 |
cmd_parts,
|
76 |
-
cwd=BASE_DIR,
|
77 |
-
|
78 |
-
stderr=subprocess.PIPE,
|
79 |
text=True,
|
80 |
-
|
81 |
-
universal_newlines=True
|
82 |
)
|
83 |
|
84 |
-
#
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
for line in process.stdout:
|
89 |
-
print(line.strip())
|
90 |
-
# İlerleme yüzdesini parse et (ondalık olarak)
|
91 |
-
if "Progress:" in line:
|
92 |
-
try:
|
93 |
-
percentage = float(re.search(r"Progress: (\d+\.\d+)%", line).group(1))
|
94 |
-
progress(percentage, desc=f"Separating audio... ({percentage:.1f}%)")
|
95 |
-
progress_bar.n = percentage # tqdm'i güncelle
|
96 |
-
progress_bar.refresh()
|
97 |
-
except (AttributeError, ValueError) as e:
|
98 |
-
print(f"Progress parsing error: {e}")
|
99 |
-
elif "Processing file" in line:
|
100 |
-
progress(0, desc=line.strip()) # Yeni dosya işleniyorsa sıfırla
|
101 |
-
|
102 |
-
for line in process.stderr:
|
103 |
-
print(line.strip())
|
104 |
|
105 |
-
|
106 |
-
|
107 |
-
|
|
|
|
|
108 |
|
109 |
-
|
|
|
|
|
|
|
|
|
110 |
|
111 |
def rename_files_with_model(folder, filename_model):
|
112 |
for filename in sorted(os.listdir(folder)):
|
@@ -114,14 +210,25 @@ def run_command_and_process_files(model_type, config_path, start_check_point, IN
|
|
114 |
if not any(filename.lower().endswith(ext) for ext in ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a']):
|
115 |
continue
|
116 |
base, ext = os.path.splitext(filename)
|
117 |
-
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
new_file_path = os.path.join(folder, new_filename)
|
120 |
-
|
|
|
|
|
|
|
121 |
|
122 |
rename_files_with_model(OUTPUT_DIR, filename_model)
|
123 |
|
124 |
output_files = os.listdir(OUTPUT_DIR)
|
|
|
|
|
125 |
|
126 |
def find_file(keyword):
|
127 |
matching_files = [
|
@@ -130,93 +237,239 @@ def run_command_and_process_files(model_type, config_path, start_check_point, IN
|
|
130 |
]
|
131 |
return matching_files[0] if matching_files else None
|
132 |
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
effects_file = find_file('effects')
|
140 |
-
speech_file = find_file('speech')
|
141 |
-
music_file = find_file('music')
|
142 |
-
dry_file = find_file('dry')
|
143 |
-
male_file = find_file('male')
|
144 |
-
female_file = find_file('female')
|
145 |
-
bleed_file = find_file('bleed')
|
146 |
-
karaoke_file = find_file('karaoke')
|
147 |
-
|
148 |
-
return (
|
149 |
-
vocal_file or None,
|
150 |
-
instrumental_file or None,
|
151 |
-
phaseremix_file or None,
|
152 |
-
drum_file or None,
|
153 |
-
bass_file or None,
|
154 |
-
other_file or None,
|
155 |
-
effects_file or None,
|
156 |
-
speech_file or None,
|
157 |
-
music_file or None,
|
158 |
-
dry_file or None,
|
159 |
-
male_file or None,
|
160 |
-
female_file or None,
|
161 |
-
bleed_file or None,
|
162 |
-
karaoke_file or None
|
163 |
-
)
|
164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
except Exception as e:
|
166 |
-
print(f"
|
|
|
|
|
167 |
return (None,) * 14
|
168 |
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
else:
|
181 |
-
print("
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
def ensemble_audio_fn(files, method, weights, progress=gr.Progress()):
|
211 |
try:
|
212 |
if len(files) < 2:
|
213 |
-
return None, "
|
214 |
|
215 |
valid_files = [f for f in files if os.path.exists(f)]
|
216 |
if len(valid_files) < 2:
|
217 |
-
return None, "
|
218 |
|
219 |
-
output_dir = os.path.join(BASE_DIR, "ensembles")
|
220 |
os.makedirs(output_dir, exist_ok=True)
|
221 |
|
222 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
@@ -232,63 +485,113 @@ def ensemble_audio_fn(files, method, weights, progress=gr.Progress()):
|
|
232 |
weights_list = [str(w) for w in map(float, weights.split(','))]
|
233 |
ensemble_args += ["--weights", *weights_list]
|
234 |
|
235 |
-
progress(0, desc="Starting ensemble process
|
236 |
result = subprocess.run(
|
237 |
["python", "ensemble.py"] + ensemble_args,
|
238 |
capture_output=True,
|
239 |
text=True
|
240 |
)
|
241 |
|
242 |
-
# Ensemble için gerçek süreye dayalı ilerleme (0.1'lik adımlarla)
|
243 |
start_time = time.time()
|
244 |
-
total_estimated_time = 10.0 #
|
245 |
-
|
|
|
246 |
elapsed_time = time.time() - start_time
|
247 |
-
progress_value =
|
248 |
-
|
249 |
-
progress(progress_value, desc=f"Ensembling
|
|
|
250 |
|
251 |
-
progress(100, desc="Finalizing ensemble output
|
252 |
-
log = f"
|
253 |
return output_path, log
|
254 |
|
255 |
except Exception as e:
|
256 |
-
return None, f"
|
257 |
finally:
|
258 |
-
progress(100, desc="Ensemble process completed
|
259 |
-
|
260 |
-
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
try:
|
|
|
|
|
|
|
263 |
if not selected_models or len(selected_models) < 1:
|
264 |
-
|
|
|
265 |
|
266 |
-
if
|
267 |
existing_files = os.listdir(INPUT_DIR)
|
268 |
if not existing_files:
|
269 |
-
|
|
|
270 |
audio_path = os.path.join(INPUT_DIR, existing_files[0])
|
271 |
else:
|
272 |
-
audio_path =
|
273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
auto_ensemble_temp = os.path.join(BASE_DIR, "auto_ensemble_temp")
|
275 |
os.makedirs(auto_ensemble_temp, exist_ok=True)
|
276 |
-
os.makedirs(AUTO_ENSEMBLE_OUTPUT, exist_ok=True)
|
277 |
clear_directory(auto_ensemble_temp)
|
278 |
|
279 |
all_outputs = []
|
280 |
total_models = len(selected_models)
|
281 |
-
|
282 |
-
|
283 |
-
progress(0, desc="Starting ensemble process...", total=total_steps)
|
284 |
|
285 |
for i, model in enumerate(selected_models):
|
286 |
-
|
287 |
-
|
|
|
288 |
os.makedirs(model_output_dir, exist_ok=True)
|
289 |
|
290 |
-
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
|
293 |
cmd = [
|
294 |
"python", INFERENCE_PATH,
|
@@ -297,85 +600,240 @@ def auto_ensemble_process(input_audio_file, selected_models, chunk_size, overlap
|
|
297 |
"--start_check_point", start_check_point,
|
298 |
"--input_folder", INPUT_DIR,
|
299 |
"--store_dir", model_output_dir,
|
|
|
|
|
|
|
300 |
]
|
301 |
-
if
|
302 |
cmd.append("--use_tta")
|
303 |
-
if
|
304 |
cmd.append("--extract_instrumental")
|
305 |
|
306 |
print(f"Running command: {' '.join(cmd)}")
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
|
326 |
model_outputs = glob.glob(os.path.join(model_output_dir, "*.wav"))
|
327 |
if not model_outputs:
|
328 |
-
raise FileNotFoundError(
|
329 |
all_outputs.extend(model_outputs)
|
330 |
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
348 |
ensemble_cmd = [
|
349 |
-
"python",
|
350 |
"--files", *quoted_files,
|
351 |
-
"--type",
|
352 |
"--output", f'"{output_path}"'
|
353 |
]
|
354 |
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
|
372 |
if not os.path.exists(output_path):
|
373 |
-
raise RuntimeError("
|
374 |
-
|
375 |
-
|
376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
except Exception as e:
|
378 |
-
|
|
|
|
|
|
|
|
|
|
|
379 |
finally:
|
380 |
shutil.rmtree(auto_ensemble_temp, ignore_errors=True)
|
381 |
-
gc.collect()
|
|
|
|
|
|
5 |
import gc
|
6 |
import shutil
|
7 |
import sys
|
8 |
+
from assets.i18n.i18n import I18nAuto
|
9 |
+
|
10 |
+
i18n = I18nAuto()
|
11 |
current_dir = os.path.dirname(os.path.abspath(__file__))
|
12 |
sys.path.append(current_dir)
|
13 |
|
14 |
from datetime import datetime
|
15 |
+
from helpers import INPUT_DIR, OLD_OUTPUT_DIR, ENSEMBLE_DIR, AUTO_ENSEMBLE_TEMP, move_old_files, clear_directory, BASE_DIR, clean_model, extract_model_name_from_checkpoint, sanitize_filename, find_clear_segment, save_segment, run_matchering, clamp_percentage
|
16 |
from model import get_model_config
|
17 |
+
from apollo_processing import process_with_apollo # Import Apollo processing
|
18 |
import torch
|
19 |
import yaml
|
20 |
import gradio as gr
|
|
|
33 |
from google.oauth2.credentials import Credentials
|
34 |
import tempfile
|
35 |
from urllib.parse import urlparse, quote
|
36 |
+
try:
|
37 |
+
from google.colab import drive
|
38 |
+
IS_COLAB = True
|
39 |
+
except ImportError:
|
40 |
+
IS_COLAB = False
|
41 |
+
import matchering as mg
|
42 |
|
43 |
import warnings
|
44 |
warnings.filterwarnings("ignore")
|
45 |
|
46 |
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
47 |
+
INFERENCE_PATH = os.path.join(BASE_DIR, "inference.py")
|
48 |
+
ENSEMBLE_PATH = os.path.join(BASE_DIR, "ensemble.py")
|
49 |
+
|
50 |
+
if IS_COLAB:
|
51 |
+
AUTO_ENSEMBLE_OUTPUT = "/content/drive/MyDrive/ensemble_output"
|
52 |
+
OUTPUT_DIR = "/content/drive/MyDrive/!output_file"
|
53 |
+
else:
|
54 |
+
AUTO_ENSEMBLE_OUTPUT = os.path.join(BASE_DIR, "ensemble_output")
|
55 |
+
OUTPUT_DIR = os.path.join(BASE_DIR, "output")
|
56 |
+
|
57 |
+
os.makedirs(AUTO_ENSEMBLE_OUTPUT, exist_ok=True)
|
58 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
59 |
+
|
60 |
+
def setup_directories():
|
61 |
+
"""Create necessary directories and check Google Drive access."""
|
62 |
+
if IS_COLAB:
|
63 |
+
try:
|
64 |
+
if not os.path.exists('/content/drive/MyDrive'):
|
65 |
+
print("Mounting Google Drive...")
|
66 |
+
from google.colab import drive
|
67 |
+
drive.mount('/content/drive', force_remount=True)
|
68 |
+
if not os.path.exists('/content/drive/MyDrive'):
|
69 |
+
raise RuntimeError("Google Drive mount failed. Please mount manually with 'from google.colab import drive; drive.mount('/content/drive', force_remount=True)'.")
|
70 |
+
except Exception as e:
|
71 |
+
raise RuntimeError(f"Failed to mount Google Drive: {str(e)}")
|
72 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
73 |
+
os.makedirs(INPUT_DIR, exist_ok=True)
|
74 |
+
os.makedirs(OLD_OUTPUT_DIR, exist_ok=True)
|
75 |
+
os.makedirs(AUTO_ENSEMBLE_OUTPUT, exist_ok=True)
|
76 |
+
|
77 |
+
def refresh_auto_output():
|
78 |
try:
|
79 |
+
output_files = glob.glob(os.path.join(AUTO_ENSEMBLE_OUTPUT, "*.wav"))
|
80 |
+
if not output_files:
|
81 |
+
return None, "No output files found"
|
82 |
+
|
83 |
+
latest_file = max(output_files, key=os.path.getctime)
|
84 |
+
return latest_file, "Output refreshed successfully"
|
85 |
+
except Exception as e:
|
86 |
+
return None, f"Error refreshing output: {str(e)}"
|
87 |
+
|
88 |
+
def update_progress_html(progress_label, progress_percent):
|
89 |
+
"""Generate progress HTML."""
|
90 |
+
progress_percent = clamp_percentage(progress_percent)
|
91 |
+
if progress_percent > 100:
|
92 |
+
print(f"Warning: Progress percentage {progress_percent} exceeds 100, clamping to 100")
|
93 |
+
return f"""
|
94 |
+
<div id="custom-progress" style="margin-top: 10px;">
|
95 |
+
<div style="font-size: 1rem; color: #C0C0C0; margin-bottom: 5px;" id="progress-label">{progress_label}</div>
|
96 |
+
<div style="width: 100%; background-color: #444; border-radius: 5px; overflow: hidden;">
|
97 |
+
<div id="progress-bar" style="width: {progress_percent}%; height: 20px; background-color: #6e8efb; transition: width 0.3s; max-width: 100%;"></div>
|
98 |
+
</div>
|
99 |
+
</div>
|
100 |
+
"""
|
101 |
+
|
102 |
+
def extract_model_name_from_checkpoint(checkpoint_path):
|
103 |
+
if not checkpoint_path:
|
104 |
+
return "Unknown"
|
105 |
+
base_name = os.path.basename(checkpoint_path)
|
106 |
+
model_name = os.path.splitext(base_name)[0]
|
107 |
+
print(f"Original checkpoint path: {checkpoint_path}, extracted model_name: {model_name}")
|
108 |
+
return model_name.strip()
|
109 |
+
|
110 |
+
def run_command_and_process_files(
|
111 |
+
model_type,
|
112 |
+
config_path,
|
113 |
+
start_check_point,
|
114 |
+
INPUT_DIR,
|
115 |
+
OUTPUT_DIR,
|
116 |
+
extract_instrumental,
|
117 |
+
use_tta,
|
118 |
+
demud_phaseremix_inst,
|
119 |
+
progress=None,
|
120 |
+
use_apollo=True,
|
121 |
+
apollo_normal_model="Apollo Universal Model",
|
122 |
+
inference_chunk_size=352800,
|
123 |
+
inference_overlap=2,
|
124 |
+
apollo_chunk_size=19,
|
125 |
+
apollo_overlap=2,
|
126 |
+
apollo_method="normal_method",
|
127 |
+
apollo_midside_model=None,
|
128 |
+
output_format="wav"
|
129 |
+
):
|
130 |
+
"""
|
131 |
+
Run inference.py with specified parameters and process output files.
|
132 |
+
"""
|
133 |
+
try:
|
134 |
+
# Create directories and check Google Drive access
|
135 |
+
setup_directories()
|
136 |
+
|
137 |
+
print(f"run_command_and_process_files: model_type={model_type}, config_path={config_path}, start_check_point={start_check_point}, inference_chunk_size={inference_chunk_size}, inference_overlap={inference_overlap}, apollo_chunk_size={apollo_chunk_size}, apollo_overlap={apollo_overlap}, progress_type={type(progress)}")
|
138 |
+
if not config_path:
|
139 |
+
raise ValueError(f"Configuration path is empty: model_type: {model_type}")
|
140 |
+
if not os.path.exists(config_path):
|
141 |
+
raise FileNotFoundError(f"Configuration file not found: {config_path}")
|
142 |
+
if not start_check_point or not os.path.exists(start_check_point):
|
143 |
+
raise FileNotFoundError(f"Checkpoint file not found: {start_check_point}")
|
144 |
+
|
145 |
+
# Validate inference parameters
|
146 |
+
try:
|
147 |
+
inference_chunk_size = int(inference_chunk_size)
|
148 |
+
inference_overlap = int(inference_overlap)
|
149 |
+
except (TypeError, ValueError) as e:
|
150 |
+
print(f"Invalid inference_chunk_size or inference_overlap: {e}. Defaulting to: inference_chunk_size=352800, inference_overlap=2")
|
151 |
+
inference_chunk_size = 352800
|
152 |
+
inference_overlap = 2
|
153 |
+
|
154 |
+
# Validate Apollo parameters
|
155 |
+
try:
|
156 |
+
apollo_chunk_size = int(apollo_chunk_size)
|
157 |
+
apollo_overlap = int(apollo_overlap)
|
158 |
+
except (TypeError, ValueError) as e:
|
159 |
+
print(f"Invalid apollo_chunk_size or apollo_overlap: {e}. Defaulting to: apollo_chunk_size=19, apollo_overlap=2")
|
160 |
+
apollo_chunk_size = 19
|
161 |
+
apollo_overlap = 2
|
162 |
+
|
163 |
cmd_parts = [
|
164 |
"python", INFERENCE_PATH,
|
165 |
"--model_type", model_type,
|
|
|
167 |
"--start_check_point", start_check_point,
|
168 |
"--input_folder", INPUT_DIR,
|
169 |
"--store_dir", OUTPUT_DIR,
|
170 |
+
"--chunk_size", str(inference_chunk_size),
|
171 |
+
"--overlap", str(inference_overlap),
|
172 |
+
"--export_format", f"{output_format} FLOAT"
|
173 |
]
|
174 |
if extract_instrumental:
|
175 |
cmd_parts.append("--extract_instrumental")
|
|
|
178 |
if demud_phaseremix_inst:
|
179 |
cmd_parts.append("--demud_phaseremix_inst")
|
180 |
|
181 |
+
print(f"Running command: {' '.join(cmd_parts)}")
|
182 |
+
process = subprocess.run(
|
183 |
cmd_parts,
|
184 |
+
cwd=BASE_DIR,
|
185 |
+
capture_output=True,
|
|
|
186 |
text=True,
|
187 |
+
check=True
|
|
|
188 |
)
|
189 |
|
190 |
+
# Log subprocess output
|
191 |
+
print(f"Subprocess stdout: {process.stdout}")
|
192 |
+
if process.stderr:
|
193 |
+
print(f"Subprocess stderr: {process.stderr}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
|
195 |
+
# Progress update (separation phase, 0-80%)
|
196 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
197 |
+
progress(0, desc="Starting audio separation", total=100)
|
198 |
+
else:
|
199 |
+
print("Progress is not callable or None, skipping progress update")
|
200 |
|
201 |
+
# Check if output files were created
|
202 |
+
filename_model = extract_model_name_from_checkpoint(start_check_point)
|
203 |
+
output_files = os.listdir(OUTPUT_DIR)
|
204 |
+
if not output_files:
|
205 |
+
raise FileNotFoundError("No output files created in OUTPUT_DIR")
|
206 |
|
207 |
def rename_files_with_model(folder, filename_model):
|
208 |
for filename in sorted(os.listdir(folder)):
|
|
|
210 |
if not any(filename.lower().endswith(ext) for ext in ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a']):
|
211 |
continue
|
212 |
base, ext = os.path.splitext(filename)
|
213 |
+
detected_type = None
|
214 |
+
for type_key in ['vocals', 'instrumental', 'phaseremix', 'drum', 'bass', 'other', 'effects', 'speech', 'music', 'dry', 'male', 'female', 'bleed', 'karaoke']:
|
215 |
+
if type_key in base.lower():
|
216 |
+
detected_type = type_key
|
217 |
+
break
|
218 |
+
type_suffix = detected_type.capitalize() if detected_type else "Processed"
|
219 |
+
clean_base = sanitize_filename(base.split('_')[0]).rsplit('.', 1)[0]
|
220 |
+
new_filename = f"{clean_base}_{type_suffix}_{filename_model}{ext}"
|
221 |
new_file_path = os.path.join(folder, new_filename)
|
222 |
+
try:
|
223 |
+
os.rename(file_path, new_file_path)
|
224 |
+
except Exception as e:
|
225 |
+
print(f"Could not rename {file_path} to {new_file_path}: {str(e)}")
|
226 |
|
227 |
rename_files_with_model(OUTPUT_DIR, filename_model)
|
228 |
|
229 |
output_files = os.listdir(OUTPUT_DIR)
|
230 |
+
if not output_files:
|
231 |
+
raise FileNotFoundError("No output files in OUTPUT_DIR after renaming")
|
232 |
|
233 |
def find_file(keyword):
|
234 |
matching_files = [
|
|
|
237 |
]
|
238 |
return matching_files[0] if matching_files else None
|
239 |
|
240 |
+
output_list = [
|
241 |
+
find_file('vocals'), find_file('instrumental'), find_file('phaseremix'),
|
242 |
+
find_file('drum'), find_file('bass'), find_file('other'), find_file('effects'),
|
243 |
+
find_file('speech'), find_file('music'), find_file('dry'), find_file('male'),
|
244 |
+
find_file('female'), find_file('bleed'), find_file('karaoke')
|
245 |
+
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
|
247 |
+
normalized_outputs = []
|
248 |
+
for output_file in output_list:
|
249 |
+
if output_file and os.path.exists(output_file):
|
250 |
+
normalized_file = os.path.join(OUTPUT_DIR, f"{sanitize_filename(os.path.splitext(os.path.basename(output_file))[0])}.{output_format}")
|
251 |
+
if output_file.endswith(f".{output_format}") and output_file != normalized_file:
|
252 |
+
shutil.copy(output_file, normalized_file)
|
253 |
+
elif output_file != normalized_file:
|
254 |
+
audio, sr = librosa.load(output_file, sr=None, mono=False)
|
255 |
+
sf.write(normalized_file, audio.T if audio.ndim > 1 else audio, sr)
|
256 |
+
else:
|
257 |
+
normalized_file = output_file
|
258 |
+
normalized_outputs.append(normalized_file)
|
259 |
+
else:
|
260 |
+
normalized_outputs.append(output_file)
|
261 |
+
|
262 |
+
# Apollo processing
|
263 |
+
if use_apollo:
|
264 |
+
normalized_outputs = process_with_apollo(
|
265 |
+
output_files=normalized_outputs,
|
266 |
+
output_dir=OUTPUT_DIR,
|
267 |
+
apollo_chunk_size=apollo_chunk_size,
|
268 |
+
apollo_overlap=apollo_overlap,
|
269 |
+
apollo_method=apollo_method,
|
270 |
+
apollo_normal_model=apollo_normal_model,
|
271 |
+
apollo_midside_model=apollo_midside_model,
|
272 |
+
output_format=output_format,
|
273 |
+
progress=progress,
|
274 |
+
total_progress_start=80,
|
275 |
+
total_progress_end=100
|
276 |
+
)
|
277 |
+
|
278 |
+
# Final progress update
|
279 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
280 |
+
progress(100, desc="Separation complete")
|
281 |
+
return tuple(normalized_outputs)
|
282 |
+
|
283 |
+
except subprocess.CalledProcessError as e:
|
284 |
+
print(f"Subprocess failed, code: {e.returncode}: {e.stderr}")
|
285 |
+
return (None,) * 14
|
286 |
except Exception as e:
|
287 |
+
print(f"run_command_and_process_files error: {str(e)}")
|
288 |
+
import traceback
|
289 |
+
traceback.print_exc()
|
290 |
return (None,) * 14
|
291 |
|
292 |
+
def process_audio(
|
293 |
+
input_audio_file,
|
294 |
+
model,
|
295 |
+
chunk_size,
|
296 |
+
overlap,
|
297 |
+
export_format,
|
298 |
+
use_tta,
|
299 |
+
demud_phaseremix_inst,
|
300 |
+
extract_instrumental,
|
301 |
+
use_apollo,
|
302 |
+
apollo_chunk_size,
|
303 |
+
apollo_overlap,
|
304 |
+
apollo_method,
|
305 |
+
apollo_normal_model,
|
306 |
+
apollo_midside_model,
|
307 |
+
use_matchering=False,
|
308 |
+
matchering_passes=1,
|
309 |
+
progress=gr.Progress(track_tqdm=True),
|
310 |
+
*args,
|
311 |
+
**kwargs
|
312 |
+
):
|
313 |
+
try:
|
314 |
+
# Check Google Drive connection
|
315 |
+
setup_directories()
|
316 |
+
|
317 |
+
if input_audio_file is not None:
|
318 |
+
audio_path = input_audio_file.name if hasattr(input_audio_file, 'name') else input_audio_file
|
319 |
+
else:
|
320 |
+
return (
|
321 |
+
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
322 |
+
"No audio file provided",
|
323 |
+
update_progress_html("No input provided", 0)
|
324 |
+
)
|
325 |
+
|
326 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
327 |
+
os.makedirs(OLD_OUTPUT_DIR, exist_ok=True)
|
328 |
+
move_old_files(OUTPUT_DIR)
|
329 |
+
|
330 |
+
print(f"process_audio: model parameter received: {model}")
|
331 |
+
# Clean model name, remove ⭐ and other unwanted characters
|
332 |
+
clean_model_name = clean_model(model) if not model.startswith("/") else extract_model_name_from_checkpoint(model)
|
333 |
+
print(f"Processing audio: {audio_path}, model: {clean_model_name}")
|
334 |
+
|
335 |
+
print(f"Raw UI inputs - chunk_size: {chunk_size}, overlap: {overlap}, apollo_chunk_size: {apollo_chunk_size}, apollo_overlap: {apollo_overlap}, apollo_method: {apollo_method}")
|
336 |
+
|
337 |
+
# Validate inference parameters
|
338 |
+
try:
|
339 |
+
inference_chunk_size = int(chunk_size)
|
340 |
+
except (TypeError, ValueError):
|
341 |
+
print(f"Invalid chunk_size: {chunk_size}. Defaulting to: 352800.")
|
342 |
+
inference_chunk_size = 352800
|
343 |
+
|
344 |
+
try:
|
345 |
+
inference_overlap = int(overlap)
|
346 |
+
except (TypeError, ValueError):
|
347 |
+
print(f"Invalid overlap: {overlap}. Defaulting to: 2.")
|
348 |
+
inference_overlap = 2
|
349 |
+
|
350 |
+
# Validate Apollo parameters
|
351 |
+
try:
|
352 |
+
apollo_chunk_size = int(apollo_chunk_size)
|
353 |
+
except (TypeError, ValueError):
|
354 |
+
print(f"Invalid apollo_chunk_size: {apollo_chunk_size}. Defaulting to: 19.")
|
355 |
+
apollo_chunk_size = 19
|
356 |
+
|
357 |
+
try:
|
358 |
+
apollo_overlap = int(apollo_overlap)
|
359 |
+
except (TypeError, ValueError):
|
360 |
+
print(f"Invalid apollo_overlap: {apollo_overlap}. Defaulting to: 2.")
|
361 |
+
apollo_overlap = 2
|
362 |
+
|
363 |
+
# Map apollo_method to backend values
|
364 |
+
if apollo_method in ["Mid-side method", "2", 2, "mid_side_method"]:
|
365 |
+
apollo_method = "mid_side_method"
|
366 |
+
elif apollo_method in ["Normal method", "1", 1, "normal_method"]:
|
367 |
+
apollo_method = "normal_method"
|
368 |
else:
|
369 |
+
print(f"Invalid apollo_method: {apollo_method}. Defaulting to: normal_method.")
|
370 |
+
apollo_method = "normal_method"
|
371 |
+
print(f"Parsed apollo_method: {apollo_method}")
|
372 |
+
|
373 |
+
print(f"Corrected values - inference_chunk_size: {inference_chunk_size}, inference_overlap: {inference_overlap}, apollo_chunk_size: {apollo_chunk_size}, apollo_overlap: {apollo_overlap}")
|
374 |
+
|
375 |
+
# Copy input file to INPUT_DIR
|
376 |
+
input_filename = os.path.basename(audio_path)
|
377 |
+
dest_path = os.path.join(INPUT_DIR, input_filename)
|
378 |
+
shutil.copy(audio_path, dest_path)
|
379 |
+
print(f"Input file copied: {dest_path}")
|
380 |
+
|
381 |
+
# Get model configuration with cleaned model name
|
382 |
+
model_type, config_path, start_check_point = get_model_config(clean_model_name, inference_chunk_size, inference_overlap)
|
383 |
+
print(f"Model configuration: model_type={model_type}, config_path={config_path}, start_check_point={start_check_point}")
|
384 |
+
|
385 |
+
outputs = run_command_and_process_files(
|
386 |
+
model_type=model_type,
|
387 |
+
config_path=config_path,
|
388 |
+
start_check_point=start_check_point,
|
389 |
+
INPUT_DIR=INPUT_DIR,
|
390 |
+
OUTPUT_DIR=OUTPUT_DIR,
|
391 |
+
extract_instrumental=extract_instrumental,
|
392 |
+
use_tta=use_tta,
|
393 |
+
demud_phaseremix_inst=demud_phaseremix_inst,
|
394 |
+
progress=progress,
|
395 |
+
use_apollo=use_apollo,
|
396 |
+
apollo_normal_model=apollo_normal_model,
|
397 |
+
inference_chunk_size=inference_chunk_size,
|
398 |
+
inference_overlap=inference_overlap,
|
399 |
+
apollo_chunk_size=apollo_chunk_size,
|
400 |
+
apollo_overlap=apollo_overlap,
|
401 |
+
apollo_method=apollo_method,
|
402 |
+
apollo_midside_model=apollo_midside_model,
|
403 |
+
output_format=export_format.split()[0].lower()
|
404 |
+
)
|
405 |
|
406 |
+
if outputs is None or all(output is None for output in outputs):
|
407 |
+
raise ValueError("run_command_and_process_files returned None or all None outputs")
|
408 |
+
|
409 |
+
# Apply Matchering (if enabled)
|
410 |
+
if use_matchering:
|
411 |
+
# Progress update for Matchering
|
412 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
413 |
+
progress(90, desc="Applying Matchering")
|
414 |
+
|
415 |
+
# Find clean segment from original audio
|
416 |
+
segment_start, segment_end, segment_audio = find_clear_segment(audio_path)
|
417 |
+
segment_path = os.path.join(tempfile.gettempdir(), "matchering_segment.wav")
|
418 |
+
save_segment(segment_audio, 44100, segment_path)
|
419 |
+
|
420 |
+
# Process each output with Matchering
|
421 |
+
mastered_outputs = []
|
422 |
+
for output in outputs:
|
423 |
+
if output and os.path.exists(output):
|
424 |
+
output_base = sanitize_filename(os.path.splitext(os.path.basename(output))[0])
|
425 |
+
mastered_path = os.path.join(OUTPUT_DIR, f"{output_base}_mastered.wav")
|
426 |
+
mastered_output = run_matchering(
|
427 |
+
reference_path=segment_path,
|
428 |
+
target_path=output,
|
429 |
+
output_path=mastered_path,
|
430 |
+
passes=matchering_passes,
|
431 |
+
bit_depth=24
|
432 |
+
)
|
433 |
+
mastered_outputs.append(mastered_path)
|
434 |
+
else:
|
435 |
+
mastered_outputs.append(output)
|
436 |
+
|
437 |
+
# Clean up segment file
|
438 |
+
if os.path.exists(segment_path):
|
439 |
+
os.remove(segment_path)
|
440 |
+
|
441 |
+
outputs = tuple(mastered_outputs)
|
442 |
+
|
443 |
+
if progress is not None and callable(getattr(progress, '__call__', None)):
|
444 |
+
progress(100, desc="Processing complete")
|
445 |
+
|
446 |
+
return (
|
447 |
+
outputs[0], outputs[1], outputs[2], outputs[3], outputs[4], outputs[5], outputs[6],
|
448 |
+
outputs[7], outputs[8], outputs[9], outputs[10], outputs[11], outputs[12], outputs[13],
|
449 |
+
"Audio processing completed",
|
450 |
+
update_progress_html("Audio processing completed", 100)
|
451 |
+
)
|
452 |
+
|
453 |
+
except Exception as e:
|
454 |
+
print(f"process_audio error: {str(e)}")
|
455 |
+
import traceback
|
456 |
+
traceback.print_exc()
|
457 |
+
return (
|
458 |
+
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
459 |
+
f"Error occurred: {str(e)}",
|
460 |
+
update_progress_html("Error occurred", 0)
|
461 |
+
)
|
462 |
|
463 |
def ensemble_audio_fn(files, method, weights, progress=gr.Progress()):
|
464 |
try:
|
465 |
if len(files) < 2:
|
466 |
+
return None, "Minimum two files required"
|
467 |
|
468 |
valid_files = [f for f in files if os.path.exists(f)]
|
469 |
if len(valid_files) < 2:
|
470 |
+
return None, "Valid files not found"
|
471 |
|
472 |
+
output_dir = os.path.join(BASE_DIR, "ensembles")
|
473 |
os.makedirs(output_dir, exist_ok=True)
|
474 |
|
475 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
|
485 |
weights_list = [str(w) for w in map(float, weights.split(','))]
|
486 |
ensemble_args += ["--weights", *weights_list]
|
487 |
|
488 |
+
progress(0, desc="Starting ensemble process", total=100)
|
489 |
result = subprocess.run(
|
490 |
["python", "ensemble.py"] + ensemble_args,
|
491 |
capture_output=True,
|
492 |
text=True
|
493 |
)
|
494 |
|
|
|
495 |
start_time = time.time()
|
496 |
+
total_estimated_time = 10.0 # Adjust based on actual ensemble duration
|
497 |
+
elapsed_time = 0
|
498 |
+
while elapsed_time < total_estimated_time:
|
499 |
elapsed_time = time.time() - start_time
|
500 |
+
progress_value = (elapsed_time / total_estimated_time) * 100
|
501 |
+
progress_value = clamp_percentage(progress_value)
|
502 |
+
progress(progress_value, desc=f"Ensembling progress: {progress_value}%")
|
503 |
+
time.sleep(0.1)
|
504 |
|
505 |
+
progress(100, desc="Finalizing ensemble output")
|
506 |
+
log = f"Success: {result.stdout}" if not result.stderr else f"Error: {result.stderr}"
|
507 |
return output_path, log
|
508 |
|
509 |
except Exception as e:
|
510 |
+
return None, f"Critical error: {str(e)}"
|
511 |
finally:
|
512 |
+
progress(100, desc="Ensemble process completed")
|
513 |
+
|
514 |
+
|
515 |
+
def auto_ensemble_process(
|
516 |
+
auto_input_audio_file,
|
517 |
+
selected_models,
|
518 |
+
auto_chunk_size,
|
519 |
+
auto_overlap,
|
520 |
+
export_format,
|
521 |
+
auto_use_tta,
|
522 |
+
auto_extract_instrumental,
|
523 |
+
auto_ensemble_type,
|
524 |
+
_state,
|
525 |
+
auto_use_apollo=True,
|
526 |
+
auto_apollo_normal_model="Apollo Universal Model",
|
527 |
+
auto_apollo_chunk_size=19,
|
528 |
+
auto_apollo_overlap=2,
|
529 |
+
auto_apollo_method="normal_method",
|
530 |
+
auto_use_matchering=False,
|
531 |
+
auto_matchering_passes=1,
|
532 |
+
apollo_midside_model=None,
|
533 |
+
progress=gr.Progress(track_tqdm=True)
|
534 |
+
):
|
535 |
+
"""Process audio with multiple models and ensemble the results, saving output to Google Drive."""
|
536 |
try:
|
537 |
+
# Check Google Drive connection and setup directories
|
538 |
+
setup_directories()
|
539 |
+
|
540 |
if not selected_models or len(selected_models) < 1:
|
541 |
+
yield None, i18n("no_models_selected"), update_progress_html(i18n("error_occurred"), 0)
|
542 |
+
return
|
543 |
|
544 |
+
if auto_input_audio_file is None:
|
545 |
existing_files = os.listdir(INPUT_DIR)
|
546 |
if not existing_files:
|
547 |
+
yield None, i18n("no_input_audio_provided"), update_progress_html(i18n("error_occurred"), 0)
|
548 |
+
return
|
549 |
audio_path = os.path.join(INPUT_DIR, existing_files[0])
|
550 |
else:
|
551 |
+
audio_path = auto_input_audio_file.name if hasattr(auto_input_audio_file, 'name') else auto_input_audio_file
|
552 |
+
|
553 |
+
# Copy input file to INPUT_DIR
|
554 |
+
input_filename = os.path.basename(audio_path)
|
555 |
+
dest_path = os.path.join(INPUT_DIR, input_filename)
|
556 |
+
shutil.copy(audio_path, dest_path)
|
557 |
+
print(f"Input file copied: {dest_path}")
|
558 |
+
|
559 |
+
# Parse apollo method
|
560 |
+
if auto_apollo_method in ["2", 2]:
|
561 |
+
auto_apollo_method = "mid_side_method"
|
562 |
+
elif auto_apollo_method in ["1", 1]:
|
563 |
+
auto_apollo_method = "normal_method"
|
564 |
+
print(f"Parsed auto_apollo_method: {auto_apollo_method}")
|
565 |
+
|
566 |
+
corrected_auto_chunk_size = int(auto_apollo_chunk_size)
|
567 |
+
corrected_auto_overlap = int(auto_apollo_overlap)
|
568 |
+
print(f"Corrected values - auto_apollo_chunk_size: {corrected_auto_chunk_size}, auto_apollo_overlap: {corrected_auto_overlap}")
|
569 |
+
|
570 |
+
# Setup temporary directories
|
571 |
auto_ensemble_temp = os.path.join(BASE_DIR, "auto_ensemble_temp")
|
572 |
os.makedirs(auto_ensemble_temp, exist_ok=True)
|
|
|
573 |
clear_directory(auto_ensemble_temp)
|
574 |
|
575 |
all_outputs = []
|
576 |
total_models = len(selected_models)
|
577 |
+
model_progress_range = 60
|
578 |
+
model_progress_per_step = model_progress_range / total_models if total_models > 0 else 0
|
|
|
579 |
|
580 |
for i, model in enumerate(selected_models):
|
581 |
+
clean_model_name = clean_model(model)
|
582 |
+
print(f"Processing model {i+1}/{total_models}: Original={model}, Cleaned={clean_model_name}")
|
583 |
+
model_output_dir = os.path.join(auto_ensemble_temp, clean_model_name)
|
584 |
os.makedirs(model_output_dir, exist_ok=True)
|
585 |
|
586 |
+
current_progress = i * model_progress_per_step
|
587 |
+
current_progress = clamp_percentage(current_progress)
|
588 |
+
yield None, i18n("loading_model").format(i+1, total_models, clean_model_name), update_progress_html(
|
589 |
+
i18n("loading_model_progress").format(i+1, total_models, clean_model_name, current_progress),
|
590 |
+
current_progress
|
591 |
+
)
|
592 |
+
|
593 |
+
model_type, config_path, start_check_point = get_model_config(clean_model_name, auto_chunk_size, auto_overlap)
|
594 |
+
print(f"Model configuration: model_type={model_type}, config_path={config_path}, start_check_point={start_check_point}")
|
595 |
|
596 |
cmd = [
|
597 |
"python", INFERENCE_PATH,
|
|
|
600 |
"--start_check_point", start_check_point,
|
601 |
"--input_folder", INPUT_DIR,
|
602 |
"--store_dir", model_output_dir,
|
603 |
+
"--chunk_size", str(auto_chunk_size),
|
604 |
+
"--overlap", str(auto_overlap),
|
605 |
+
"--export_format", f"{export_format.split()[0].lower()} FLOAT"
|
606 |
]
|
607 |
+
if auto_use_tta:
|
608 |
cmd.append("--use_tta")
|
609 |
+
if auto_extract_instrumental:
|
610 |
cmd.append("--extract_instrumental")
|
611 |
|
612 |
print(f"Running command: {' '.join(cmd)}")
|
613 |
+
process = subprocess.Popen(
|
614 |
+
cmd,
|
615 |
+
stdout=subprocess.PIPE,
|
616 |
+
stderr=subprocess.PIPE,
|
617 |
+
text=True,
|
618 |
+
bufsize=1,
|
619 |
+
universal_newlines=True
|
620 |
+
)
|
621 |
+
|
622 |
+
stderr_output = ""
|
623 |
+
for line in process.stdout:
|
624 |
+
print(line.strip())
|
625 |
+
if "Progress:" in line:
|
626 |
+
try:
|
627 |
+
percentage = float(re.search(r"Progress: (\d+\.\d+)%", line).group(1))
|
628 |
+
model_percentage = (percentage / 100) * model_progress_per_step
|
629 |
+
current_progress = (i * model_progress_per_step) + model_percentage
|
630 |
+
current_progress = clamp_percentage(current_progress)
|
631 |
+
yield None, i18n("loading_model").format(i+1, total_models, clean_model_name), update_progress_html(
|
632 |
+
i18n("loading_model_progress").format(i+1, total_models, clean_model_name, current_progress),
|
633 |
+
current_progress
|
634 |
+
)
|
635 |
+
except (AttributeError, ValueError) as e:
|
636 |
+
print(f"Progress parsing error: {e}")
|
637 |
+
|
638 |
+
for line in process.stderr:
|
639 |
+
stderr_output += line
|
640 |
+
print(line.strip())
|
641 |
+
|
642 |
+
process.wait()
|
643 |
+
if process.returncode != 0:
|
644 |
+
print(f"Error: {stderr_output}")
|
645 |
+
yield None, i18n("model_failed").format(clean_model_name, stderr_output), update_progress_html(
|
646 |
+
i18n("error_occurred"), 0
|
647 |
+
)
|
648 |
+
return
|
649 |
+
|
650 |
+
gc.collect()
|
651 |
+
if torch.cuda.is_available():
|
652 |
+
torch.cuda.empty_cache()
|
653 |
+
|
654 |
+
current_progress = (i + 1) * model_progress_per_step
|
655 |
+
current_progress = clamp_percentage(current_progress)
|
656 |
+
yield None, i18n("completed_model").format(i+1, total_models, clean_model_name), update_progress_html(
|
657 |
+
i18n("completed_model_progress").format(i+1, total_models, clean_model_name, current_progress),
|
658 |
+
current_progress
|
659 |
+
)
|
660 |
|
661 |
model_outputs = glob.glob(os.path.join(model_output_dir, "*.wav"))
|
662 |
if not model_outputs:
|
663 |
+
raise FileNotFoundError(i18n("model_output_failed").format(clean_model_name))
|
664 |
all_outputs.extend(model_outputs)
|
665 |
|
666 |
+
# Select compatible files for ensemble
|
667 |
+
preferred_type = 'instrumental' if auto_extract_instrumental else 'vocals'
|
668 |
+
ensemble_files = [output for output in all_outputs if preferred_type.lower() in output.lower()]
|
669 |
+
print(f"Selected ensemble files: {ensemble_files}")
|
670 |
+
if len(ensemble_files) < 2:
|
671 |
+
print(f"Warning: Insufficient {preferred_type} files ({len(ensemble_files)}). Falling back to all outputs.")
|
672 |
+
ensemble_files = all_outputs
|
673 |
+
if len(ensemble_files) < 2:
|
674 |
+
raise ValueError(i18n("insufficient_files_for_ensemble").format(len(ensemble_files)))
|
675 |
+
|
676 |
+
# Enhanced outputs with Apollo (if enabled)
|
677 |
+
if auto_use_apollo:
|
678 |
+
yield None, i18n("enhancing_with_apollo").format(0, len(all_outputs)), update_progress_html(
|
679 |
+
i18n("waiting_for_files"), 60
|
680 |
+
)
|
681 |
+
|
682 |
+
all_outputs = process_with_apollo(
|
683 |
+
output_files=all_outputs,
|
684 |
+
output_dir=auto_ensemble_temp,
|
685 |
+
apollo_chunk_size=corrected_auto_chunk_size,
|
686 |
+
apollo_overlap=corrected_auto_overlap,
|
687 |
+
apollo_method=auto_apollo_method,
|
688 |
+
apollo_normal_model=auto_apollo_normal_model,
|
689 |
+
apollo_midside_model=apollo_midside_model,
|
690 |
+
output_format=export_format.split()[0].lower(),
|
691 |
+
progress=progress,
|
692 |
+
total_progress_start=60,
|
693 |
+
total_progress_end=90
|
694 |
+
)
|
695 |
+
|
696 |
+
# Perform ensemble
|
697 |
+
yield None, i18n("performing_ensemble"), update_progress_html(
|
698 |
+
i18n("performing_ensemble"), 90
|
699 |
+
)
|
700 |
+
|
701 |
+
quoted_files = [f'"{f}"' for f in ensemble_files]
|
702 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
703 |
+
output_path = os.path.join(AUTO_ENSEMBLE_OUTPUT, f"auto_ensemble_output_{timestamp}.wav")
|
704 |
+
|
705 |
ensemble_cmd = [
|
706 |
+
"python", ENSEMBLE_PATH,
|
707 |
"--files", *quoted_files,
|
708 |
+
"--type", auto_ensemble_type,
|
709 |
"--output", f'"{output_path}"'
|
710 |
]
|
711 |
|
712 |
+
print(f"Running ensemble command: {' '.join(ensemble_cmd)}")
|
713 |
+
try:
|
714 |
+
process = subprocess.Popen(
|
715 |
+
" ".join(ensemble_cmd),
|
716 |
+
shell=True,
|
717 |
+
stdout=subprocess.PIPE,
|
718 |
+
stderr=subprocess.PIPE,
|
719 |
+
text=True,
|
720 |
+
bufsize=1,
|
721 |
+
universal_newlines=True
|
722 |
+
)
|
723 |
+
|
724 |
+
stdout_output = ""
|
725 |
+
stderr_output = ""
|
726 |
+
for line in process.stdout:
|
727 |
+
stdout_output += line
|
728 |
+
print(f"Ensemble stdout: {line.strip()}")
|
729 |
+
for line in process.stderr:
|
730 |
+
stderr_output += line
|
731 |
+
print(f"Ensemble stderr: {line.strip()}")
|
732 |
+
|
733 |
+
process.wait()
|
734 |
+
if process.returncode != 0:
|
735 |
+
print(f"Ensemble subprocess failed with code {process.returncode}: {stderr_output}")
|
736 |
+
yield None, i18n("ensemble_error").format(stderr_output), update_progress_html(
|
737 |
+
i18n("error_occurred"), 0
|
738 |
+
)
|
739 |
+
return
|
740 |
+
|
741 |
+
print(f"Checking if output file exists: {output_path}")
|
742 |
+
if not os.path.exists(output_path):
|
743 |
+
raise RuntimeError(f"Ensemble output file not created at {output_path}. Stdout: {stdout_output}, Stderr: {stderr_output}")
|
744 |
+
|
745 |
+
except Exception as e:
|
746 |
+
print(f"Ensemble command execution failed: {str(e)}")
|
747 |
+
yield None, i18n("ensemble_error").format(str(e)), update_progress_html(
|
748 |
+
i18n("error_occurred"), 0
|
749 |
+
)
|
750 |
+
return
|
751 |
+
|
752 |
+
# Apply Matchering (if enabled)
|
753 |
+
if auto_use_matchering and os.path.exists(output_path):
|
754 |
+
yield None, i18n("applying_matchering"), update_progress_html(
|
755 |
+
i18n("applying_matchering"), 98
|
756 |
+
)
|
757 |
|
758 |
+
try:
|
759 |
+
# Find clean segment
|
760 |
+
segment_start, segment_end, segment_audio = find_clear_segment(audio_path)
|
761 |
+
segment_path = os.path.join(tempfile.gettempdir(), "matchering_segment.wav")
|
762 |
+
save_segment(segment_audio, 44100, segment_path)
|
763 |
+
|
764 |
+
# Master the ensemble output
|
765 |
+
mastered_output_path = os.path.join(AUTO_ENSEMBLE_OUTPUT, f"auto_ensemble_output_{timestamp}_mastered.wav")
|
766 |
+
print(f"Running Matchering: reference={segment_path}, target={output_path}, output={mastered_output_path}")
|
767 |
+
mastered_output = run_matchering(
|
768 |
+
reference_path=segment_path,
|
769 |
+
target_path=output_path,
|
770 |
+
output_path=mastered_output_path,
|
771 |
+
passes=auto_matchering_passes,
|
772 |
+
bit_depth=24
|
773 |
+
)
|
774 |
+
|
775 |
+
# Verify mastered output
|
776 |
+
if not os.path.exists(mastered_output_path):
|
777 |
+
raise RuntimeError(f"Matchering failed to create output at {mastered_output_path}")
|
778 |
+
|
779 |
+
# Clean up segment file
|
780 |
+
if os.path.exists(segment_path):
|
781 |
+
os.remove(segment_path)
|
782 |
+
|
783 |
+
output_path = mastered_output_path
|
784 |
+
print(f"Matchering completed: {mastered_output_path}")
|
785 |
+
except Exception as e:
|
786 |
+
print(f"Matchering error: {str(e)}")
|
787 |
+
yield None, i18n("error").format(f"Matchering failed: {str(e)}"), update_progress_html(
|
788 |
+
i18n("error_occurred"), 0
|
789 |
+
)
|
790 |
+
return
|
791 |
+
|
792 |
+
yield None, i18n("finalizing_ensemble_output"), update_progress_html(
|
793 |
+
i18n("finalizing_ensemble_output"), 98
|
794 |
+
)
|
795 |
|
796 |
if not os.path.exists(output_path):
|
797 |
+
raise RuntimeError(i18n("ensemble_file_creation_failed").format(output_path))
|
798 |
+
|
799 |
+
# Verify write permissions for Google Drive directory
|
800 |
+
try:
|
801 |
+
print(f"Verifying write permissions for {AUTO_ENSEMBLE_OUTPUT}")
|
802 |
+
test_file = os.path.join(AUTO_ENSEMBLE_OUTPUT, "test_write.txt")
|
803 |
+
with open(test_file, "w") as f:
|
804 |
+
f.write("Test")
|
805 |
+
os.remove(test_file)
|
806 |
+
print(f"Write permissions verified for {AUTO_ENSEMBLE_OUTPUT}")
|
807 |
+
except Exception as e:
|
808 |
+
print(f"Write permission error for {AUTO_ENSEMBLE_OUTPUT}: {str(e)}")
|
809 |
+
yield None, i18n("error").format(f"Write permission error: {str(e)}"), update_progress_html(
|
810 |
+
i18n("error_occurred"), 0
|
811 |
+
)
|
812 |
+
return
|
813 |
+
|
814 |
+
# Verify file in Google Drive
|
815 |
+
print(f"Final output file: {output_path}")
|
816 |
+
if IS_COLAB:
|
817 |
+
drive_output_path = os.path.join("/content/drive/MyDrive/ensemble_output", os.path.basename(output_path))
|
818 |
+
print(f"Checking if file exists in Google Drive: {drive_output_path}")
|
819 |
+
if not os.path.exists(drive_output_path):
|
820 |
+
print(f"File not found in Google Drive, copying from local path: {output_path}")
|
821 |
+
shutil.copy(output_path, drive_output_path)
|
822 |
+
print(f"Copied to Google Drive: {drive_output_path}")
|
823 |
+
|
824 |
+
yield output_path, i18n("success_output_created") + f" Saved to {drive_output_path if IS_COLAB else output_path}", update_progress_html(
|
825 |
+
i18n("ensemble_completed"), 100
|
826 |
+
)
|
827 |
+
|
828 |
except Exception as e:
|
829 |
+
print(f"auto_ensemble_process error: {str(e)}")
|
830 |
+
import traceback
|
831 |
+
traceback.print_exc()
|
832 |
+
yield None, i18n("error").format(str(e)), update_progress_html(
|
833 |
+
i18n("error_occurred"), 0
|
834 |
+
)
|
835 |
finally:
|
836 |
shutil.rmtree(auto_ensemble_temp, ignore_errors=True)
|
837 |
+
gc.collect()
|
838 |
+
if torch.cuda.is_available():
|
839 |
+
torch.cuda.empty_cache()
|
requirements.txt
CHANGED
@@ -19,7 +19,6 @@ torch_audiomentations
|
|
19 |
httpx
|
20 |
gradio
|
21 |
google-api-python-client
|
22 |
-
validators
|
23 |
pytube
|
24 |
tqdm
|
25 |
psutil
|
@@ -32,4 +31,9 @@ rotary_embedding_torch
|
|
32 |
noisereduce
|
33 |
loralib
|
34 |
hyper_connections==0.1.11
|
35 |
-
pyngrok
|
|
|
|
|
|
|
|
|
|
|
|
19 |
httpx
|
20 |
gradio
|
21 |
google-api-python-client
|
|
|
22 |
pytube
|
23 |
tqdm
|
24 |
psutil
|
|
|
31 |
noisereduce
|
32 |
loralib
|
33 |
hyper_connections==0.1.11
|
34 |
+
pyngrok
|
35 |
+
matchering==2.0.6
|
36 |
+
pyloudnorm
|
37 |
+
gdown
|
38 |
+
validators
|
39 |
+
requests
|