separate
#!/usr/bin/env python3
"""
╔══════════════════════════════════════════════╗
║ StemSplit — Separador de audio con IA ║
║ Powered by Spleeter (Deezer, gratis) ║
╚══════════════════════════════════════════════╝
USO:
python separar_audio.py cancion.mp3
python separar_audio.py cancion.mp3 --stems 4
python separar_audio.py cancion.mp3 --stems 5
MODOS:
2 pistas → voz + instrumental (más rápido)
4 pistas → voz + batería + bajo + otros
5 pistas → voz + batería + bajo + piano + otros
"""
import sys
import os
import subprocess
import argparse
# ─── Colores para la terminal ─────────────────────────────────────────────────
R = "\033[91m" # rojo
G = "\033[92m" # verde
Y = "\033[93m" # amarillo
C = "\033[96m" # cyan
B = "\033[1m" # bold
E = "\033[0m" # reset
def print_banner():
print(f"""
{C}{B}
┌─────────────────────────────────────┐
│ 🎵 StemSplit — Spleeter │
│ Separador de audio con IA │
└─────────────────────────────────────┘
{E}""")
def install_dependencies():
"""Instala spleeter y ffmpeg si no están disponibles."""
print(f"{Y}[*] Verificando dependencias...{E}")
# Verificar spleeter
try:
import spleeter
print(f"{G}[✓] Spleeter ya está instalado{E}")
except ImportError:
print(f"{Y}[*] Instalando Spleeter (puede tardar 1-2 minutos la primera vez)...{E}")
subprocess.check_call([
sys.executable, "-m", "pip", "install",
"spleeter", "--quiet", "--no-warn-script-location"
])
print(f"{G}[✓] Spleeter instalado correctamente{E}")
# Verificar ffmpeg
result = subprocess.run(["ffmpeg", "-version"],
capture_output=True, text=True)
if result.returncode == 0:
print(f"{G}[✓] FFmpeg disponible{E}")
else:
print(f"\n{R}[!] FFmpeg no encontrado.{E}")
print(f" {B}Instálalo con:{E}")
print(f" • Windows: https://ffmpeg.org/download.html")
print(f" • Mac: brew install ffmpeg")
print(f" • Ubuntu: sudo apt install ffmpeg\n")
sys.exit(1)
def separar(audio_path: str, num_stems: int, output_dir: str):
"""Ejecuta la separación con Spleeter."""
if not os.path.exists(audio_path):
print(f"{R}[!] No se encontró el archivo: {audio_path}{E}")
sys.exit(1)
nombre = os.path.splitext(os.path.basename(audio_path))[0]
print(f"\n{C}[*] Archivo: {B}{audio_path}{E}")
print(f"{C}[*] Modelo: {B}{num_stems} pistas{E}")
print(f"{C}[*] Salida: {B}{output_dir}/{nombre}{E}\n")
stem_labels = {
2: ["vocals (voz)", "accompaniment (instrumental)"],
4: ["vocals (voz)", "drums (batería)", "bass (bajo)", "other (otros)"],
5: ["vocals (voz)", "drums (batería)", "bass (bajo)", "piano", "other (otros)"],
}
print(f"{Y}[*] Separando en: {', '.join(stem_labels[num_stems])}{E}")
print(f"{Y}[*] Procesando... (puede tardar según la duración del audio){E}\n")
# Ejecutar spleeter como subproceso para mejor compatibilidad
cmd = [
sys.executable, "-m", "spleeter", "separate",
audio_path,
"-p", f"spleeter:{num_stems}stems",
"-o", output_dir,
"--codec", "mp3",
"--bitrate", "320k",
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"{R}[!] Error de Spleeter:{E}")
print(result.stderr[-2000:]) # últimas líneas del error
sys.exit(1)
# Mostrar archivos generados
out_folder = os.path.join(output_dir, nombre)
print(f"\n{G}{B}[✓] ¡Separación completada!{E}")
print(f"\n{B}Archivos generados en: {out_folder}/{E}")
if os.path.exists(out_folder):
tracks = sorted(os.listdir(out_folder))
for track in tracks:
size = os.path.getsize(os.path.join(out_folder, track))
size_mb = size / 1e6
print(f" {G}→{E} {track:35s} {size_mb:.1f} MB")
else:
print(f" {Y}(buscando archivos en: {output_dir}){E}")
print(f"\n{C}💡 Tip: Abre los archivos con VLC, Audacity o cualquier reproductor.{E}")
def main():
print_banner()
parser = argparse.ArgumentParser(
description="Separa un audio en sus pistas individuales usando IA (Spleeter)",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Ejemplos:
python separar_audio.py cancion.mp3
python separar_audio.py cancion.mp3 --stems 4
python separar_audio.py cancion.mp3 --stems 5 --output mis_pistas
"""
)
parser.add_argument("audio",
help="Ruta al archivo de audio (MP3, WAV, FLAC, OGG, etc.)")
parser.add_argument("--stems", type=int, choices=[2, 4, 5], default=2,
help="Número de pistas a separar (2=voz+instrumental, 4=+drums+bass, 5=+piano)")
parser.add_argument("--output", type=str, default="pistas_separadas",
help="Carpeta de salida (default: pistas_separadas)")
# Si no se pasan argumentos, mostrar ayuda interactiva
if len(sys.argv) == 1:
print(f"{Y}No se especificó archivo. Modo interactivo:{E}\n")
audio = input(f" {B}Ruta al archivo de audio:{E} ").strip().strip('"')
print(f"\n {B}¿Cuántas pistas separar?{E}")
print(f" 1 → 2 pistas: voz + instrumental {Y}(recomendado, más rápido){E}")
print(f" 2 → 4 pistas: voz + batería + bajo + otros")
print(f" 3 → 5 pistas: voz + batería + bajo + piano + otros")
opcion = input(f"\n Elige [1/2/3] (Enter = 1): ").strip()
stems_map = {"1": 2, "2": 4, "3": 5, "": 2}
stems = stems_map.get(opcion, 2)
output = "pistas_separadas"
install_dependencies()
separar(audio, stems, output)
return
args = parser.parse_args()
install_dependencies()
separar(args.audio, args.stems, args.output)
if __name__ == "__main__":
main()
Comentarios
Publicar un comentario