gelpi01 commited on
Commit
0cd3307
·
1 Parent(s): baab706

Detectar dinámicamente carpeta de stems de Demucs 6stems

Browse files
Files changed (1) hide show
  1. audio_pipeline.py +97 -12
audio_pipeline.py CHANGED
@@ -1,5 +1,3 @@
1
- # audio_pipeline.py
2
-
3
  import os
4
  import subprocess
5
  import sys
@@ -20,9 +18,8 @@ BASE_STEMS_DIR = "data/stems"
20
  def separar_audio_demucs_6stems(input_file, model="htdemucs_6s"):
21
  """
22
  Separa 6 stems con Demucs (vocals, drums, bass, guitar, piano, other),
23
- los guarda en data/stems/htdemucs_6s/<base>/ y devuelve esa ruta.
24
  """
25
- base = os.path.splitext(os.path.basename(input_file))[0]
26
  out_root = os.path.join(BASE_STEMS_DIR, model)
27
  os.makedirs(out_root, exist_ok=True)
28
 
@@ -37,10 +34,16 @@ def separar_audio_demucs_6stems(input_file, model="htdemucs_6s"):
37
  ]
38
  subprocess.run(cmd, check=True)
39
 
40
- stems_dir = os.path.join(out_root, base)
41
- if not os.path.isdir(stems_dir):
42
- raise FileNotFoundError(f"No se encontró el folder de stems en {stems_dir}")
43
- return stems_dir
 
 
 
 
 
 
44
 
45
  def limpiar_stems(stems_dir):
46
  """Aplica reducción de ruido a cada stem (_cleaned.wav)."""
@@ -52,19 +55,101 @@ def limpiar_stems(stems_dir):
52
  sf.write(ruta.replace(".wav", "_cleaned.wav"), reduced, sr)
53
 
54
  def combinar_stems_sin_vocales(stems_dir):
55
- """Mezcla todos los stems limpios excepto 'vocals' en base_instrumental.wav."""
56
- # buscamos *_cleaned.wav excepto vocals
57
  wavs = [
58
  f for f in os.listdir(stems_dir)
59
  if f.endswith("_cleaned.wav") and "vocals" not in f.lower()
60
  ]
61
  if not wavs:
62
- # fallback a stems originales sin vocals
63
  wavs = [
64
  f for f in os.listdir(stems_dir)
65
  if f.endswith(".wav") and "vocals" not in f.lower()
66
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
 
 
 
 
 
 
 
 
 
 
 
68
  signals = []
69
  for w in wavs:
70
  y, sr = librosa.load(os.path.join(stems_dir, w), sr=None)
@@ -76,7 +161,7 @@ def combinar_stems_sin_vocales(stems_dir):
76
  sf.write(os.path.join(stems_dir, "base_instrumental.wav"), mix, sr)
77
 
78
  def reducir_ruido(input_file, output_file, noise_duration=0.5):
79
- """Reduce ruido del WAV de entrada y guarda en output_file."""
80
  y, sr = librosa.load(input_file, sr=None)
81
  noise = y[:int(sr * noise_duration)]
82
  with np.errstate(divide='ignore', invalid='ignore'):
 
 
 
1
  import os
2
  import subprocess
3
  import sys
 
18
  def separar_audio_demucs_6stems(input_file, model="htdemucs_6s"):
19
  """
20
  Separa 6 stems con Demucs (vocals, drums, bass, guitar, piano, other),
21
+ los guarda en data/stems/<model>/<track_folder>/ y devuelve la ruta de ese folder.
22
  """
 
23
  out_root = os.path.join(BASE_STEMS_DIR, model)
24
  os.makedirs(out_root, exist_ok=True)
25
 
 
34
  ]
35
  subprocess.run(cmd, check=True)
36
 
37
+ # Demucs crea un subdirectorio con el nombre de la pista dentro de out_root
38
+ # Encuentra el primer subdirectorio que contenga archivos .wav
39
+ for entry in os.listdir(out_root):
40
+ candidate = os.path.join(out_root, entry)
41
+ if os.path.isdir(candidate):
42
+ # Verifica que tenga stems
43
+ wavs = [f for f in os.listdir(candidate) if f.endswith('.wav')]
44
+ if wavs:
45
+ return candidate
46
+ raise FileNotFoundError(f"No se encontró el folder de stems en {out_root}")
47
 
48
  def limpiar_stems(stems_dir):
49
  """Aplica reducción de ruido a cada stem (_cleaned.wav)."""
 
55
  sf.write(ruta.replace(".wav", "_cleaned.wav"), reduced, sr)
56
 
57
  def combinar_stems_sin_vocales(stems_dir):
58
+ """Mezcla todos los stems limpios excepto vocals en base_instrumental.wav."""
 
59
  wavs = [
60
  f for f in os.listdir(stems_dir)
61
  if f.endswith("_cleaned.wav") and "vocals" not in f.lower()
62
  ]
63
  if not wavs:
 
64
  wavs = [
65
  f for f in os.listdir(stems_dir)
66
  if f.endswith(".wav") and "vocals" not in f.lower()
67
  ]
68
+ signals = []
69
+ for w in wavs:
70
+ y, sr = librosa.load(os.path.join(stems_dir, w), sr=None)
71
+ signals.append(y)
72
+ if not signals:
73
+ raise RuntimeError("No se encontraron stems para combinar.")
74
+ maxlen = max(len(s) for s in signals)
75
+ mix = sum(np.pad(s, (0, maxlen - len(s))) for s in signals) / len(signals)
76
+ sf.write(os.path.join(stems_dir, "base_instrumental.wav"), mix, sr)
77
+
78
+ def reducir_ruido(input_file, output_file, noise_duration=0.5):
79
+ """Reduce ruido y guarda el resultado."""
80
+ y, sr = librosa.load(input_file, sr=None)
81
+ noise = y[:int(sr * noise_duration)]
82
+ with np.errstate(divide='ignore', invalid='ignore'):
83
+ reduced = nr.reduce_noise(y=y, sr=sr, y_noise=noise)
84
+ reduced = np.nan_to_num(reduced)
85
+ sf.write(output_file, reduced, sr)
86
+ import os
87
+ import subprocess
88
+ import sys
89
+ import warnings
90
+ import torch
91
+
92
+ import librosa
93
+ import numpy as np
94
+ import soundfile as sf
95
+ import noisereduce as nr
96
+
97
+ # Suprime warnings de runtime (p.ej. invalid value encountered in divide)
98
+ warnings.filterwarnings("ignore", category=RuntimeWarning)
99
+
100
+ # Directorio base donde guardaremos todos los stems
101
+ BASE_STEMS_DIR = "data/stems"
102
+
103
+ def separar_audio_demucs_6stems(input_file, model="htdemucs_6s"):
104
+ """
105
+ Separa 6 stems con Demucs (vocals, drums, bass, guitar, piano, other),
106
+ los guarda en data/stems/<model>/<track_folder>/ y devuelve la ruta de ese folder.
107
+ """
108
+ out_root = os.path.join(BASE_STEMS_DIR, model)
109
+ os.makedirs(out_root, exist_ok=True)
110
+
111
+ device = "cuda" if torch.cuda.is_available() else "cpu"
112
+ cmd = [
113
+ sys.executable,
114
+ "-m", "demucs",
115
+ "-n", model,
116
+ "--out", out_root,
117
+ "--device", device,
118
+ input_file
119
+ ]
120
+ subprocess.run(cmd, check=True)
121
+
122
+ # Demucs crea un subdirectorio con el nombre de la pista dentro de out_root
123
+ # Encuentra el primer subdirectorio que contenga archivos .wav
124
+ for entry in os.listdir(out_root):
125
+ candidate = os.path.join(out_root, entry)
126
+ if os.path.isdir(candidate):
127
+ # Verifica que tenga stems
128
+ wavs = [f for f in os.listdir(candidate) if f.endswith('.wav')]
129
+ if wavs:
130
+ return candidate
131
+ raise FileNotFoundError(f"No se encontró el folder de stems en {out_root}")
132
+
133
+ def limpiar_stems(stems_dir):
134
+ """Aplica reducción de ruido a cada stem (_cleaned.wav)."""
135
+ for archivo in os.listdir(stems_dir):
136
+ if archivo.endswith(".wav"):
137
+ ruta = os.path.join(stems_dir, archivo)
138
+ y, sr = librosa.load(ruta, sr=None)
139
+ reduced = nr.reduce_noise(y=y, sr=sr)
140
+ sf.write(ruta.replace(".wav", "_cleaned.wav"), reduced, sr)
141
 
142
+ def combinar_stems_sin_vocales(stems_dir):
143
+ """Mezcla todos los stems limpios excepto vocals en base_instrumental.wav."""
144
+ wavs = [
145
+ f for f in os.listdir(stems_dir)
146
+ if f.endswith("_cleaned.wav") and "vocals" not in f.lower()
147
+ ]
148
+ if not wavs:
149
+ wavs = [
150
+ f for f in os.listdir(stems_dir)
151
+ if f.endswith(".wav") and "vocals" not in f.lower()
152
+ ]
153
  signals = []
154
  for w in wavs:
155
  y, sr = librosa.load(os.path.join(stems_dir, w), sr=None)
 
161
  sf.write(os.path.join(stems_dir, "base_instrumental.wav"), mix, sr)
162
 
163
  def reducir_ruido(input_file, output_file, noise_duration=0.5):
164
+ """Reduce ruido y guarda el resultado."""
165
  y, sr = librosa.load(input_file, sr=None)
166
  noise = y[:int(sr * noise_duration)]
167
  with np.errstate(divide='ignore', invalid='ignore'):