ASesYusuf1 commited on
Commit
c1683bf
·
verified ·
1 Parent(s): 610ed41

Upload 102 files

Browse files
.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
- .DS_Store
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 torch
6
- from urllib.parse import quote
 
 
 
 
 
 
 
 
 
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
- if not validators.url(url):
16
- return None, "❌ Invalid URL", None, None, None, None
 
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("✅ Cookie file updated!")
25
  except Exception as e:
26
- print(f"⚠️ Cookie installation error: {str(e)}")
27
 
28
  wav_path = None
29
  download_success = False
 
 
 
 
 
 
 
 
 
 
30
 
31
- if download_type == 'drive':
 
32
  try:
33
- file_id = re.search(r'/d/([^/]+)', url).group(1) if '/d/' in url else url.split('id=')[-1]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- wav_path = output_path
 
 
 
38
  download_success = True
39
  else:
40
- raise Exception("File size zero or file not created")
41
  except Exception as e:
42
- error_msg = f"❌ Google Drive download error: {str(e)}"
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
- wav_path = os.path.splitext(temp_path)[0] + '.wav'
64
- if os.path.exists(wav_path):
 
 
 
 
65
  download_success = True
66
  else:
67
- raise Exception("WAV conversion failed")
68
  except Exception as e:
69
- error_msg = f"❌ Download error: {str(e)}"
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
- "🎉 Downloaded successfully!",
80
  wav_path,
81
  wav_path,
82
  wav_path,
83
  wav_path
84
  )
85
- return None, "❌ Download failed", None, None, None, None
 
 
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
- __author__ = 'Roman Solovyev (ZFTurbo): https://github.com/ZFTurbo/'
 
 
 
 
 
 
3
 
4
  import os
5
- import librosa
6
- import soundfile as sf
7
- import numpy as np
8
  import argparse
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- def stft(wave, nfft, hl):
12
- wave_left = np.asfortranarray(wave[0])
13
- wave_right = np.asfortranarray(wave[1])
14
- spec_left = librosa.stft(wave_left, n_fft=nfft, hop_length=hl)
15
- spec_right = librosa.stft(wave_right, n_fft=nfft, hop_length=hl)
16
- spec = np.asfortranarray([spec_left, spec_right])
17
- return spec
18
-
19
-
20
- def istft(spec, hl, length):
21
- spec_left = np.asfortranarray(spec[0])
22
- spec_right = np.asfortranarray(spec[1])
23
- wave_left = librosa.istft(spec_left, hop_length=hl, length=length)
24
- wave_right = librosa.istft(spec_right, hop_length=hl, length=length)
25
- wave = np.asfortranarray([wave_left, wave_right])
26
- return wave
27
-
28
-
29
- def absmax(a, *, axis):
30
- dims = list(a.shape)
31
- dims.pop(axis)
32
- indices = list(np.ogrid[tuple(slice(0, d) for d in dims)]) # Tuple yerine list
33
- argmax = np.abs(a).argmax(axis=axis)
34
- insert_pos = (len(a.shape) + axis) % len(a.shape)
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
- mod_track = []
85
- for i in range(pred_track.shape[0]):
86
- if algorithm == 'avg_wave':
87
- mod_track.append(pred_track[i] * weights[i])
88
- elif algorithm in ['median_wave', 'min_wave', 'max_wave']:
89
- mod_track.append(pred_track[i])
90
- elif algorithm in ['avg_fft', 'min_fft', 'max_fft', 'median_fft']:
91
- spec = stft(pred_track[i], nfft=2048, hl=1024)
92
- if algorithm in ['avg_fft']:
93
- mod_track.append(spec * weights[i])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  else:
95
- mod_track.append(spec)
96
- pred_track = np.array(mod_track)
97
-
98
- if algorithm in ['avg_wave']:
99
- pred_track = pred_track.sum(axis=0)
100
- pred_track /= np.array(weights).sum().T
101
- elif algorithm in ['median_wave']:
102
- pred_track = np.median(pred_track, axis=0)
103
- elif algorithm in ['min_wave']:
104
- pred_track = np.array(pred_track)
105
- pred_track = lambda_min(pred_track, axis=0, key=np.abs)
106
- elif algorithm in ['max_wave']:
107
- pred_track = np.array(pred_track)
108
- pred_track = lambda_max(pred_track, axis=0, key=np.abs)
109
- elif algorithm in ['avg_fft']:
110
- pred_track = pred_track.sum(axis=0)
111
- pred_track /= np.array(weights).sum()
112
- pred_track = istft(pred_track, 1024, final_length)
113
- elif algorithm in ['min_fft']:
114
- pred_track = np.array(pred_track)
115
- pred_track = lambda_min(pred_track, axis=0, key=np.abs)
116
- pred_track = istft(pred_track, 1024, final_length)
117
- elif algorithm in ['max_fft']:
118
- pred_track = np.array(pred_track)
119
- pred_track = absmax(pred_track, axis=0)
120
- pred_track = istft(pred_track, 1024, final_length)
121
- elif algorithm in ['median_fft']:
122
- pred_track = np.array(pred_track)
123
- pred_track = np.median(pred_track, axis=0)
124
- pred_track = istft(pred_track, 1024, final_length)
125
- return pred_track
126
-
127
-
128
- def ensemble_files(args):
129
- parser = argparse.ArgumentParser()
130
- parser.add_argument("--files", type=str, required=True, nargs='+', help="Path to all audio-files to ensemble")
131
- parser.add_argument("--type", type=str, default='avg_wave', help="One of avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, min_fft, max_fft")
132
- parser.add_argument("--weights", type=float, nargs='+', help="Weights to create ensemble. Number of weights must be equal to number of files")
133
- parser.add_argument("--output", default="res.wav", type=str, help="Path to wav file where ensemble result will be stored")
134
- if args is None:
135
- args = parser.parse_args()
136
- else:
137
- args = parser.parse_args(args)
138
-
139
- print('Ensemble type: {}'.format(args.type))
140
- print('Number of input files: {}'.format(len(args.files)))
141
- if args.weights is not None:
142
- weights = args.weights
143
- else:
144
- weights = np.ones(len(args.files))
145
- print('Weights: {}'.format(weights))
146
- print('Output file: {}'.format(args.output))
147
- data = []
148
- for f in args.files:
149
- if not os.path.isfile(f):
150
- print('Error. Can\'t find file: {}. Check paths.'.format(f))
151
- exit()
152
- print('Reading file: {}'.format(f))
153
- wav, sr = librosa.load(f, sr=None, mono=False)
154
- # wav, sr = sf.read(f)
155
- print("Waveform shape: {} sample rate: {}".format(wav.shape, sr))
156
- data.append(wav)
157
- data = np.array(data)
158
- res = average_waveforms(data, weights, args.type)
159
- print('Result shape: {}'.format(res.shape))
160
- sf.write(args.output, res.T, sr, 'FLOAT')
 
 
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
  if __name__ == "__main__":
164
- ensemble_files(None)
 
 
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
- from helpers import update_model_dropdown, handle_file_upload, clear_old_output, save_uploaded_file, update_file_list
 
 
 
 
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ı (BASE_PATH yerine)
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; /* Metalik gümüş metin, profesyonel görünüm */
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: 80px 20px 20px; /* Logo için alan bırak */
62
- color: #ff4040; /* Kırmızı, dublaj temasına uygun */
63
- font-size: 2.5rem; /* Daha etkileyici ve büyük başlık */
64
- font-weight: 900; /* Daha kalın ve dramatik */
65
- text-shadow: 0 0 10px rgba(255, 64, 64, 0.5); /* Kırmızı gölge efekti */
66
- z-index: 1500; /* Tablerden üstte, logonun altında */
67
- }
68
-
69
- /* Metalik kırmızı parlama animasyonu */
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
- padding: 10px;
88
- color: #ff4040; /* Kırmızı metin, dublaj temasına uygun */
89
- font-size: 14px;
90
- margin-top: 20px;
91
- position: relative;
92
- z-index: 1001; /* Tablerden üstte, logodan düşük */
 
 
 
 
 
 
 
 
 
 
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; /* Koyu kırmızı, dublaj temasına uygun */
99
- border: 1px solid #ff4040 !important; /* Kırmızı sınır */
100
- color: #C0C0C0 !important; /* Metalik gümüş metin */
101
  border-radius: 8px !important;
102
  padding: 8px 16px !important;
103
- position: relative;
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; /* Daha belirgin kırmızı gölge */
111
- background: #ff4040 !important; /* Daha açık kırmızı hover efekti */
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; /* Kırmızı sınır */
137
- background: rgba(128, 0, 0, 0.5) !important; /* Koyu kırmızı, şeffaf */
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
- .compact-upload.horizontal.x-narrow button {
184
- padding: 3px 10px !important;
185
- font-size: 0.7em !important;
186
- height: 26px !important;
187
- min-width: 70px !important;
188
  }
189
-
190
- .compact-upload.horizontal.x-narrow .text-gray-500 {
191
- font-size: 0.65em !important;
192
- max-width: 140px !important;
 
 
193
  }
194
-
195
- /* Sekmeler İçin Ortak Stiller */
196
- .gr-tab {
197
- background: rgba(128, 0, 0, 0.5) !important; /* Koyu kırmızı, şeffaf */
198
- border-radius: 12px 12px 0 0 !important;
199
- margin: 0 5px !important;
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
- .gr-tab-selected {
206
- background: #800000 !important; /* Koyu kırmızı */
207
- box-shadow: 0 4px 12px rgba(255, 64, 64, 0.7) !important; /* Daha belirgin kırmızı gölge */
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
- /* Manuel Ensemble Özel Stilleri */
213
- .compact-header {
214
- font-size: 0.95em !important;
215
- margin: 0.8rem 0 0.5rem 0 !important;
216
- color: #C0C0C0 !important; /* Metalik gümüş metin */
 
 
217
  }
218
-
219
- .compact-grid {
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
- # Arayüz tasarımı
 
 
 
 
 
341
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
342
- with gr.Column():
343
- # Logo (PNG olarak, dublaj temasına uygun)
344
- logo_html = """
345
- <div class="logo-container">
346
- <img src="/content/gk_logo.png" alt="" class="logo-img">
347
- </div>
 
 
348
  """
349
- gr.HTML(logo_html)
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("Audio Separation", elem_id="separation_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("📥 Input & Model", open=True):
364
  with gr.Tabs():
365
- with gr.Tab("🖥 Upload"):
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
- with gr.Tab("📂 Path"):
373
- file_path_input = gr.Textbox(placeholder="/path/to/audio.wav")
374
 
375
  with gr.Row():
376
  model_category = gr.Dropdown(
377
- label="Category",
378
- choices=list(MODEL_CONFIGS.keys()),
379
- value="Vocal Models"
380
- )
381
- model_dropdown = gr.Dropdown(
382
- label="Model",
383
- choices=list(MODEL_CONFIGS["Vocal Models"].keys())
384
  )
 
385
 
386
- with gr.Accordion("⚙ Settings", open=False):
 
 
 
 
 
 
387
  with gr.Row():
388
- export_format = gr.Dropdown(
389
- label="Format",
390
- choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
391
- value='wav FLOAT'
392
- )
393
- chunk_size = gr.Dropdown(
394
- label="Chunk Size",
395
- choices=[352800, 485100],
396
- value=352800,
397
- info="Don't change unless you have specific requirements"
398
- )
 
 
399
 
400
  with gr.Row():
401
- overlap = gr.Slider(2, 50, step=1, label="Overlap", value=2)
402
- gr.Markdown("Recommended: 2-10 (Higher values increase quality but require more VRAM)")
403
- use_tta = gr.Checkbox(label="TTA Boost")
 
 
 
 
 
 
404
 
405
  with gr.Row():
406
- use_demud_phaseremix_inst = gr.Checkbox(label="Phase Fix")
407
- gr.Markdown("Advanced phase correction for instrumental tracks")
408
- extract_instrumental = gr.Checkbox(label="Instrumental")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
 
410
  with gr.Row():
411
- process_btn = gr.Button("🚀 Process", variant="primary")
412
- clear_old_output_btn = gr.Button("🧹 Reset", variant="secondary")
413
- clear_old_output_status = gr.Textbox(label="Status", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
 
415
- # Sağ Panel - Sonuçlar
416
  with gr.Column(scale=2, min_width=800):
417
  with gr.Tabs():
418
- with gr.Tab("🎧 Main"):
419
  with gr.Column():
420
- original_audio = gr.Audio(label="Original", interactive=False)
421
  with gr.Row():
422
- vocals_audio = gr.Audio(label="Vocals", show_download_button=True)
423
- instrumental_audio = gr.Audio(label="Instrumental", show_download_button=True)
 
424
 
425
- with gr.Tab("🔍 Details"):
426
  with gr.Column():
427
  with gr.Row():
428
- male_audio = gr.Audio(label="Male")
429
- female_audio = gr.Audio(label="Female")
430
- speech_audio = gr.Audio(label="Speech")
431
  with gr.Row():
432
- drum_audio = gr.Audio(label="Drums")
433
- bass_audio = gr.Audio(label="Bass")
434
  with gr.Row():
435
- other_audio = gr.Audio(label="Other")
436
- effects_audio = gr.Audio(label="Effects")
437
 
438
- with gr.Tab("⚙ Advanced"):
439
  with gr.Column():
440
  with gr.Row():
441
- phaseremix_audio = gr.Audio(label="Phase Remix")
442
- dry_audio = gr.Audio(label="Dry")
443
  with gr.Row():
444
- music_audio = gr.Audio(label="Music")
445
- karaoke_audio = gr.Audio(label="Karaoke")
446
- bleed_audio = gr.Audio(label="Bleed")
447
-
448
- with gr.Row():
449
- gr.Markdown("""
450
- <div style="
451
- background: rgba(245,245,220,0.15);
452
- padding: 1rem;
453
- border-radius: 8px;
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
- # Oto Ensemble Sekmesi
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(label="Upload file")
 
 
 
469
  auto_file_path_input = gr.Textbox(
470
- label="Or enter file path",
471
- placeholder="Enter full path to audio file",
472
  interactive=True
473
  )
474
 
475
- with gr.Accordion("⚙️ Advanced Settings", open=False):
476
  with gr.Row():
477
- auto_use_tta = gr.Checkbox(label="Use TTA", value=False)
478
- auto_extract_instrumental = gr.Checkbox(label="Instrumental Only")
479
 
480
  with gr.Row():
481
  auto_overlap = gr.Slider(
482
- label="Overlap",
483
  minimum=2,
484
  maximum=50,
485
  value=2,
486
  step=1
487
  )
488
  auto_chunk_size = gr.Dropdown(
489
- label="Chunk Size",
490
  choices=[352800, 485100],
491
  value=352800
492
  )
493
  export_format2 = gr.Dropdown(
494
- label="Output Format",
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
- auto_category_dropdown = gr.Dropdown(
504
- label="Model Category",
505
- choices=list(MODEL_CONFIGS.keys()),
506
- value="Vocal Models"
507
  )
508
 
509
- # Model seçimi (tek seferde)
510
- auto_model_dropdown = gr.Dropdown(
511
- label="Select Models from Category",
512
- choices=list(MODEL_CONFIGS["Vocal Models"].keys()),
513
- multiselect=True,
514
- max_choices=50,
515
- interactive=True
516
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
517
 
518
- # Seçilen modellerin listesi (ayrı kutucuk)
519
- selected_models = gr.Dropdown(
520
- label="Selected Models",
521
- choices=[],
522
- multiselect=True,
523
- interactive=False
524
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
  with gr.Row():
527
- add_btn = gr.Button("➕ Add Selected", variant="secondary")
528
- clear_btn = gr.Button("🗑️ Clear All", variant="stop")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
 
530
- # Ensemble Ayarları
531
  with gr.Group():
532
- gr.Markdown("### ⚡ Ensemble Settings")
533
  with gr.Row():
534
  auto_ensemble_type = gr.Dropdown(
535
- label="Method",
536
  choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
537
- 'avg_fft', 'median_fft', 'min_fft', 'max_fft'],
538
- value='avg_wave'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
540
 
541
- gr.Markdown("**Recommendation:** avg_wave and max_fft best results")
 
 
 
 
 
 
 
 
 
 
 
542
 
543
- auto_process_btn = gr.Button("🚀 Start Processing", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544
 
545
  with gr.Column():
546
  with gr.Tabs():
547
- with gr.Tab("🔊 Original Audio"):
548
  original_audio2 = gr.Audio(
549
- label="Original Audio",
550
  interactive=False,
551
  every=1,
552
  elem_id="original_audio_player"
553
  )
554
- with gr.Tab("🎚️ Ensemble Result"):
555
  auto_output_audio = gr.Audio(
556
- label="Output Preview",
557
  show_download_button=True,
558
  interactive=False
559
  )
560
-
561
- auto_status = gr.Textbox(
562
- label="Processing Status",
563
- interactive=False,
564
- placeholder="Waiting for processing...",
565
- elem_classes="status-box"
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
- # İndirme Sekmesi
624
- with gr.Tab("Download Sources"):
 
 
 
 
 
 
625
  with gr.Row():
626
  with gr.Column():
627
- gr.Markdown("### 🌐 Direct Links")
628
- direct_url_input = gr.Textbox(label="Audio File URL")
629
- direct_download_btn = gr.Button("⬇️ Download from URL", variant="secondary")
630
- direct_download_status = gr.Textbox(label="Download Status")
631
- direct_download_output = gr.File(label="Downloaded File", interactive=False)
632
 
633
  with gr.Column():
634
- gr.Markdown("### 🍪 Cookie Management")
635
  cookie_file = gr.File(
636
- label="Upload Cookies.txt",
637
  file_types=[".txt"],
638
  interactive=True,
639
  elem_id="cookie_upload"
640
  )
641
- gr.Markdown("""
642
- <div style="margin-left:15px; font-size:0.95em">
643
- **📌 Why Needed?**
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("📂 Input Sources", open=True):
674
  with gr.Row():
675
- refresh_btn = gr.Button("🔄 Refresh", variant="secondary", size="sm")
676
  ensemble_type = gr.Dropdown(
677
- label="Ensemble Algorithm",
678
  choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
679
- 'avg_fft', 'median_fft', 'min_fft', 'max_fft'],
680
  value='avg_wave'
681
  )
682
 
683
- # Dosya listesini belirli bir yoldan al
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="Available Files",
691
  multiselect=True,
692
  interactive=True,
693
  elem_id="file-dropdown"
694
  )
695
-
696
  weights_input = gr.Textbox(
697
- label="Custom Weights (comma separated)",
698
- placeholder="Example: 0.8, 1.2, 1.0, ...",
699
- info="Leave empty for equal weights"
700
  )
701
 
702
- # Sağ Panel - Sonuçlar
703
  with gr.Column(scale=2, min_width=800):
704
  with gr.Tabs():
705
- with gr.Tab("🎧 Result Preview"):
706
  ensemble_output_audio = gr.Audio(
707
- label="Ensembled Output",
708
  interactive=False,
709
  show_download_button=True,
710
  elem_id="output-audio"
711
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
 
713
- with gr.Tab("📋 Processing Log"):
714
- ensemble_status = gr.Textbox(
715
- label="Processing Details",
716
- interactive=False,
717
- elem_id="log-box"
718
- )
719
-
720
- with gr.Row():
721
- ensemble_process_btn = gr.Button(
722
- " Process Ensemble",
723
- variant="primary",
724
- size="sm",
725
- elem_id="process-btn"
726
- )
727
-
728
- gr.HTML("""
729
- <div class="footer">
730
- Presented by Gecekondu Production
731
- </div>
732
- """)
733
-
734
- def update_models(category):
735
- return gr.Dropdown(choices=list(MODEL_CONFIGS[category].keys()))
736
-
737
- def add_models(new_models, existing_models):
738
- if existing_models is None:
739
- existing_models = [] # None ise boş liste yap
740
- if new_models is None:
741
- new_models = [] # None ise boş liste yap
742
- updated = list(set(existing_models + new_models))
743
- return gr.Dropdown(choices=updated, value=updated)
744
-
745
- def clear_models():
746
- return gr.Dropdown(choices=[], value=[])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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(fn=update_models, inputs=auto_category_dropdown, outputs=auto_model_dropdown)
775
- add_btn.click(fn=add_models, inputs=[auto_model_dropdown, selected_models], outputs=selected_models)
776
- clear_btn.click(fn=clear_models, inputs=[], outputs=selected_models)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
 
778
  process_btn.click(
779
- fn=process_audio,
780
  inputs=[
781
  input_audio_file, model_dropdown, chunk_size, overlap, export_format,
782
- use_tta, use_demud_phaseremix_inst, extract_instrumental, gr.State(None), gr.State(None)
 
 
 
783
  ],
784
  outputs=[
785
  vocals_audio, instrumental_audio, phaseremix_audio, drum_audio, karaoke_audio,
786
- bass_audio, other_audio, effects_audio, speech_audio, bleed_audio, music_audio,
787
- dry_audio, male_audio, female_audio
 
788
  ]
789
  )
790
 
791
  auto_process_btn.click(
792
- fn=auto_ensemble_process,
793
  inputs=[
794
- auto_input_audio_file, selected_models, auto_chunk_size, auto_overlap, export_format2,
795
- auto_use_tta, auto_extract_instrumental, auto_ensemble_type, gr.State(None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
796
  ],
797
- outputs=[auto_output_audio, auto_status]
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
- return demo
 
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
- # Dizinleri oluştur
 
 
 
 
 
 
 
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
- """Loads a tuple from a YAML sequence."""
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 update_model_dropdown(category):
66
- """Kategoriye göre model dropdown'ını günceller."""
67
- return gr.Dropdown(choices=list(MODEL_CONFIGS[category].keys()), label="Model")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- """Deletes all files in the given directory."""
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(f"{f} could not be deleted: {e}")
91
 
92
  def clear_temp_folder(folder_path, exclude_items=None):
93
- """Safely clears contents of a directory while preserving specified items."""
94
  try:
95
  if not os.path.exists(folder_path):
96
- print(f"⚠️ Directory does not exist: {folder_path}")
97
  return False
98
  if not os.path.isdir(folder_path):
99
- print(f"⚠️ Path is not a directory: {folder_path}")
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(f"⚠️ Error deleting {item_path}: {str(e)}")
113
  return True
114
  except Exception as e:
115
- print(f"❌ Critical error: {str(e)}")
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 "❌ Old output folder does not exist"
123
  shutil.rmtree(old_output_folder)
124
  os.makedirs(old_output_folder, exist_ok=True)
125
- return "✅ Old outputs successfully cleared!"
126
  except Exception as e:
127
- return f"🔥 Error: {str(e)}"
128
 
129
  def shorten_filename(filename, max_length=30):
130
- """Shortens a filename to a specified maximum length."""
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
- """Removes special characters from a filename."""
138
  return re.sub(r'[^\w\-_\. ]', '', title).strip()
139
 
 
 
 
 
 
 
 
 
 
140
  def convert_to_wav(file_path):
141
- """Converts the audio file to WAV format."""
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(f"FFmpeg Error ({e.returncode}): {e.stderr.decode()}")
156
  return None
157
 
158
  def generate_random_port():
159
- """Generates a random port number."""
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
- """Saves an uploaded file to the specified directory."""
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(f"File saved successfully: {os.path.basename(target_path)}")
208
  return target_path
209
 
210
  def move_old_files(output_folder):
211
- """Moves old files to the old_output directory."""
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 librosa
 
 
 
 
 
 
 
 
 
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(f"Total files found: {len(mixture_paths)}. Using sample rate: {sample_rate}")
77
 
78
  instruments = prefer_target_instrument(config)[:]
79
- os.makedirs(args.store_dir, exist_ok=True)
80
 
81
- # Progress tracking
82
- total_files = len(mixture_paths)
83
- current_file = 0
 
 
 
 
 
 
 
 
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
- mix_orig = mix.copy()
93
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  if 'normalize' in config.inference:
95
  if config.inference['normalize'] is True:
96
- mix, norm_params = normalize_audio(mix)
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
- except Exception as e:
230
- print(f'Cannot read track: {path}')
231
- print(f'Error message: {str(e)}')
232
- continue
 
 
233
 
234
- print(f"Elapsed time: {time.time() - start_time:.2f} seconds.")
 
 
 
 
 
235
 
236
  def proc_folder(args):
237
- parser = argparse.ArgumentParser()
238
- parser.add_argument("--model_type", type=str, default='mdx23c',
239
- help="Model type (bandit, bs_roformer, mdx23c, etc.)")
240
- parser.add_argument("--config_path", type=str, help="Path to config file")
241
- parser.add_argument("--demud_phaseremix_inst", action='store_true', help="demud_phaseremix_inst")
242
- parser.add_argument("--start_check_point", type=str, default='',
243
- help="Initial checkpoint to valid weights")
244
- parser.add_argument("--input_folder", type=str, help="Folder with mixtures to process")
245
- parser.add_argument("--audio_path", type=str, help="Path to a single audio file to process") # Yeni argüman
246
- parser.add_argument("--store_dir", default="", type=str, help="Path to store results")
247
- parser.add_argument("--device_ids", nargs='+', type=int, default=0,
248
- help='List of GPU IDs')
249
- parser.add_argument("--extract_instrumental", action='store_true',
250
- help="Invert vocals to get instrumental if provided")
251
- parser.add_argument("--force_cpu", action='store_true',
252
- help="Force the use of CPU even if CUDA is available")
253
- parser.add_argument("--flac_file", action='store_true',
254
- help="Output flac file instead of wav")
255
- parser.add_argument("--export_format", type=str,
256
- choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
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('CUDA is available, use --force_cpu to disable it.')
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("Using device: ", device)
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("Instruments: {}".format(config.training.instruments))
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("Model load time: {:.2f} sec".format(time.time() - model_load_start_time))
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(f"Starting Localtunnel on port {port}...")
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(f"Share Link: {tunnel_url}")
57
- print(f"Password IP: {endpoint_ip}")
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(f"Starting Ngrok on port {port}...")
64
  try:
65
  ngrok.set_auth_token(ngrok_token)
66
  ngrok.kill()
67
  tunnel = ngrok.connect(port)
68
- print(f"Ngrok URL: {tunnel.public_url}")
69
 
70
  start_gradio(port, share=False)
71
  except Exception as e:
72
- print(f"Error starting ngrok: {e}")
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(f"Selected port: {port}")
80
 
81
  # Paylaşım yöntemine göre işlem yap
82
  if method == "gradio":
83
- print("Starting Gradio with built-in sharing...")
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("Error: Ngrok token is required for ngrok method!")
90
  sys.exit(1)
91
- start_ngrok(port, ngrok_token)
92
  else:
93
- print("Error: Invalid method! Use 'gradio', 'localtunnel', or 'ngrok'.")
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("\n🛑 Process stopped by user")
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
- "Other Models": {
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
- from clean_model import clean_model_name, shorten_filename, clean_filename
 
 
 
 
 
33
 
34
  import warnings
35
  warnings.filterwarnings("ignore")
36
 
37
- # BASE_DIR'i dinamik olarak güncel dizine ayarla
38
- BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # processing.py'nin bulunduğu dizin
39
- INFERENCE_PATH = os.path.join(BASE_DIR, "inference.py") # inference.py'nin tam yolu
40
- OUTPUT_DIR = os.path.join(BASE_DIR, "output") # Çıkış dizini BASE_DIR/output olarak güncellendi
41
- AUTO_ENSEMBLE_OUTPUT = os.path.join(BASE_DIR, "ensemble_output") # Ensemble çıkış dizini
42
-
43
- def extract_model_name(full_model_string):
44
- """Extracts the clean model name from a string."""
45
- if not full_model_string:
46
- return ""
47
- cleaned = str(full_model_string)
48
- if ' - ' in cleaned:
49
- cleaned = cleaned.split(' - ')[0]
50
- emoji_prefixes = ['✅ ', '👥 ', '🗣️ ', '🏛️ ', '🔇 ', '🔉 ', '🎬 ', '🎼 ', '✅(?) ']
51
- for prefix in emoji_prefixes:
52
- if cleaned.startswith(prefix):
53
- cleaned = cleaned[len(prefix):]
54
- return cleaned.strip()
55
-
56
- def run_command_and_process_files(model_type, config_path, start_check_point, INPUT_DIR, OUTPUT_DIR, extract_instrumental, use_tta, demud_phaseremix_inst, clean_model, progress=gr.Progress()):
 
 
 
 
 
 
 
 
 
 
 
 
57
  try:
58
- # inference.py'nin tam yolunu kullan
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- process = subprocess.Popen(
 
75
  cmd_parts,
76
- cwd=BASE_DIR, # Çalışma dizini olarak BASE_DIR kullan
77
- stdout=subprocess.PIPE,
78
- stderr=subprocess.PIPE,
79
  text=True,
80
- bufsize=1,
81
- universal_newlines=True
82
  )
83
 
84
- # Progress bar ile subprocess çıktısını izleme
85
- progress(0, desc="Starting audio separation...", total=100)
86
- progress_bar = tqdm(total=100, desc="Processing audio", unit="%", position=0, leave=False)
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
- process.wait()
106
- progress_bar.close()
107
- progress(100, desc="Separation complete!")
 
 
108
 
109
- filename_model = clean_model_name(clean_model)
 
 
 
 
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
- clean_base = base.strip('_- ')
118
- new_filename = f"{clean_base}_{filename_model}{ext}"
 
 
 
 
 
 
119
  new_file_path = os.path.join(folder, new_filename)
120
- os.rename(file_path, new_file_path)
 
 
 
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
- vocal_file = find_file('vocals')
134
- instrumental_file = find_file('instrumental')
135
- phaseremix_file = find_file('phaseremix')
136
- drum_file = find_file('drum')
137
- bass_file = find_file('bass')
138
- other_file = find_file('other')
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"An error occurred: {e}")
 
 
167
  return (None,) * 14
168
 
169
- finally:
170
- clear_directory(INPUT_DIR)
171
-
172
- def process_audio(input_audio_file, model, chunk_size, overlap, export_format, use_tta, demud_phaseremix_inst, extract_instrumental, clean_model, progress=gr.Progress(track_tqdm=True), *args, **kwargs):
173
- """Processes audio using the specified model and returns separated stems with progress."""
174
- if input_audio_file is not None:
175
- audio_path = input_audio_file.name
176
- else:
177
- existing_files = os.listdir(INPUT_DIR)
178
- if existing_files:
179
- audio_path = os.path.join(INPUT_DIR, existing_files[0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  else:
181
- print("No audio file provided and no existing file in input directory.")
182
- return [None] * 14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
- os.makedirs(OUTPUT_DIR, exist_ok=True)
185
- os.makedirs(OLD_OUTPUT_DIR, exist_ok=True)
186
- move_old_files(OUTPUT_DIR)
187
-
188
- clean_model_name_full = extract_model_name(model)
189
- print(f"Processing audio from: {audio_path} using model: {clean_model_name_full}")
190
-
191
- progress(0, desc="Starting audio separation...", total=100)
192
- model_type, config_path, start_check_point = get_model_config(clean_model_name_full, chunk_size, overlap)
193
-
194
- outputs = run_command_and_process_files(
195
- model_type=model_type,
196
- config_path=config_path,
197
- start_check_point=start_check_point,
198
- INPUT_DIR=INPUT_DIR,
199
- OUTPUT_DIR=OUTPUT_DIR,
200
- extract_instrumental=extract_instrumental,
201
- use_tta=use_tta,
202
- demud_phaseremix_inst=demud_phaseremix_inst,
203
- clean_model=clean_model_name_full,
204
- progress=progress
205
- )
206
-
207
- progress(100, desc="Audio processing completed!")
208
- return outputs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  def ensemble_audio_fn(files, method, weights, progress=gr.Progress()):
211
  try:
212
  if len(files) < 2:
213
- return None, "⚠️ Minimum 2 files required"
214
 
215
  valid_files = [f for f in files if os.path.exists(f)]
216
  if len(valid_files) < 2:
217
- return None, "Valid files not found"
218
 
219
- output_dir = os.path.join(BASE_DIR, "ensembles") # BASE_DIR üzerinden dinamik
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...", total=100)
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 # Tahmini toplam süre (saniye, gerçek süreye göre ayarlanabilir)
245
- for i in np.arange(0.1, 100.1, 0.1):
 
246
  elapsed_time = time.time() - start_time
247
- progress_value = min(i, (elapsed_time / total_estimated_time) * 100)
248
- time.sleep(0.001) # Çok küçük bir gecikme, gerçek işlem süresiyle değiştirilebilir
249
- progress(progress_value, desc=f"Ensembling... ({progress_value:.1f}%)")
 
250
 
251
- progress(100, desc="Finalizing ensemble output...")
252
- log = f" Success!\n{result.stdout}" if not result.stderr else f" Error!\n{result.stderr}"
253
  return output_path, log
254
 
255
  except Exception as e:
256
- return None, f"Critical Error: {str(e)}"
257
  finally:
258
- progress(100, desc="Ensemble process completed!")
259
-
260
- def auto_ensemble_process(input_audio_file, selected_models, chunk_size, overlap, export_format, use_tta, extract_instrumental, ensemble_type, _state, progress=gr.Progress(track_tqdm=True), *args, **kwargs):
261
- """Processes audio with multiple models and performs ensemble with progress."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  try:
 
 
 
263
  if not selected_models or len(selected_models) < 1:
264
- return None, " No models selected"
 
265
 
266
- if input_audio_file is None:
267
  existing_files = os.listdir(INPUT_DIR)
268
  if not existing_files:
269
- return None, " No input audio provided"
 
270
  audio_path = os.path.join(INPUT_DIR, existing_files[0])
271
  else:
272
- audio_path = input_audio_file.name
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
- total_steps = int(total_models * 10 + 20) # Her model için 10 adım + final adımlar, ondalık için tam sayı
282
-
283
- progress(0, desc="Starting ensemble process...", total=total_steps)
284
 
285
  for i, model in enumerate(selected_models):
286
- clean_model = extract_model_name(model)
287
- model_output_dir = os.path.join(auto_ensemble_temp, clean_model)
 
288
  os.makedirs(model_output_dir, exist_ok=True)
289
 
290
- progress(i * 10, desc=f"Loading model {i+1}/{total_models}: {model}...")
291
- model_type, config_path, start_check_point = get_model_config(clean_model, chunk_size, overlap)
 
 
 
 
 
 
 
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 use_tta:
302
  cmd.append("--use_tta")
303
- if extract_instrumental:
304
  cmd.append("--extract_instrumental")
305
 
306
  print(f"Running command: {' '.join(cmd)}")
307
- try:
308
- result = subprocess.run(cmd, capture_output=True, text=True)
309
- print(result.stdout)
310
- if result.returncode != 0:
311
- print(f"Error: {result.stderr}")
312
- return None, f"Model {model} failed: {result.stderr}"
313
- except Exception as e:
314
- return None, f"Critical error with {model}: {str(e)}"
315
-
316
- # Her model için gerçek süreye dayalı ilerleme (0.1'lik adımlarla)
317
- start_time = time.time()
318
- total_estimated_time = 1.0 # Tahmini toplam süre (saniye, gerçek süreye göre ayarlanabilir)
319
- for j in np.arange(0.1, 10.1, 0.1):
320
- elapsed_time = time.time() - start_time
321
- progress_value = (i * 10) + j
322
- progress_value = min(progress_value, (i * 10) + (elapsed_time / total_estimated_time) * 10)
323
- time.sleep(0.001) # Çok küçük bir gecikme, gerçek işlem süresiyle değiştirilebilir
324
- progress(progress_value, desc=f"Separating with {model} ({progress_value:.1f}%)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
 
326
  model_outputs = glob.glob(os.path.join(model_output_dir, "*.wav"))
327
  if not model_outputs:
328
- raise FileNotFoundError(f"{model} failed to produce output")
329
  all_outputs.extend(model_outputs)
330
 
331
- progress(total_models * 10 + 5, desc="Waiting for all files to be ready...")
332
- def wait_for_files(files, timeout=300):
333
- start = time.time()
334
- while time.time() - start < timeout:
335
- missing = [f for f in files if not os.path.exists(f)]
336
- if not missing:
337
- return True
338
- time.sleep(5)
339
- raise TimeoutError(f"Missing files: {missing[:3]}...")
340
-
341
- wait_for_files(all_outputs)
342
-
343
- progress(total_models * 10 + 10, desc="Performing ensemble...")
344
- quoted_files = [f'"{f}"' for f in all_outputs]
345
- timestamp = str(int(time.time()))
346
- output_path = os.path.join(AUTO_ENSEMBLE_OUTPUT, f"ensemble_{timestamp}.wav")
347
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  ensemble_cmd = [
349
- "python", "ensemble.py",
350
  "--files", *quoted_files,
351
- "--type", ensemble_type,
352
  "--output", f'"{output_path}"'
353
  ]
354
 
355
- result = subprocess.run(
356
- " ".join(ensemble_cmd),
357
- shell=True,
358
- capture_output=True,
359
- text=True,
360
- check=True
361
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
 
363
- # Ensemble için gerçek süreye dayalı ilerleme (0.1'lik adımlarla)
364
- start_time = time.time()
365
- total_estimated_time = 10.0 # Tahmini toplam süre (saniye, gerçek süreye göre ayarlanabilir)
366
- for i in np.arange(total_models * 10 + 11, total_steps - 0.1, 0.1):
367
- elapsed_time = time.time() - start_time
368
- progress_value = min(i, (elapsed_time / total_estimated_time) * (total_steps - (total_models * 10 + 10)) + (total_models * 10 + 10))
369
- time.sleep(0.001) # Çok küçük bir gecikme, gerçek işlem süresiyle değiştirilebilir
370
- progress(progress_value, desc=f"Ensembling... ({progress_value:.1f}%)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
  if not os.path.exists(output_path):
373
- raise RuntimeError("Ensemble dosyası oluşturulamadı")
374
-
375
- progress(total_steps, desc="Ensemble completed successfully!")
376
- return output_path, "✅ Success!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
  except Exception as e:
378
- return None, f" Error: {str(e)}"
 
 
 
 
 
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