audio-denoise / README.md
Azuredraco's picture
Despliegue desde GitHub
c6a2c55 verified
|
Raw History Blame Contribute Delete
11.8 kB

A newer version of the Gradio SDK is available: 6.31.0

Upgrade
metadata
title: Audio Denoise
emoji: 🎙️
colorFrom: blue
colorTo: green
sdk: gradio
sdk_version: 6.9.0
python_version: '3.12'
app_file: app.py
pinned: false
short_description: Limpieza de voz y control de entregas de audio

🎙️ Limpieza y control de voz — documentación técnica

¿Vas a usar la app? Todo lo que necesitas está en la pestaña ❓ Ayuda de la propia app. Este documento es para mantenerla: cómo está hecha, cómo crear proyectos nuevos y cómo publicarla.

La app reduce el ruido de grabaciones de voz sin perder naturalidad y comprueba que cada audio cumple la especificación técnica de un cliente (un perfil). Si no cumple, genera la versión corregida y un informe en Excel. Funciona en Hugging Face con ZeroGPU; si no hay cuota de GPU, sigue en CPU automáticamente.


1. Publicar cambios en Hugging Face

El código vive en GitHub y el Space es una copia que se actualiza con un botón.

  1. Los cambios tienen que estar en la rama main de GitHub. Si vienen en otra rama, primero hay que fusionar el pull request con Merge pull request.
  2. En GitHub: Actions → Desplegar en Hugging Face → Run workflow → Run workflow.
  3. Al cabo de un minuto aparece ✅. El Space se reconstruye solo: con cambios en requirements.txt o packages.txt tarda 5–10 minutos; si no, menos de uno.

Configuración, una sola vez (ya hecha):

Dónde Qué
GitHub → Settings → Secrets and variables → Actions → Secrets HF_TOKEN: token de Hugging Face de tipo Write
GitHub → … → Variables (opcional) HF_SPACE: si no existe, se usa Azuredraco/audio-denoise

Alternativa desde el PC: python scripts/deploy_hf.py --space Azuredraco/audio-denoise. Usa el token de hf auth login o el de la variable de entorno HF_TOKEN.

El Space queda como copia exacta del repositorio, sin tests/, scripts/ ni .github/.

Versión para Windows

Cada vez que entra un cambio en main, GitHub construye solo la versión de escritorio (workflow Versión para Windows). La prueba en un Windows real y la publica en https://huggingface.co/Azuredraco/limpieza-de-voz-windows. El Space tiene un enlace a esa página. Tarda unos 15–20 minutos. También se puede lanzar a mano desde Actions → Versión para Windows → Run workflow.

  • Instalador Instalar-Limpieza-de-voz.exe: no pide permisos de administrador. Crea accesos directos en el escritorio y en el menú Inicio, y al ejecutar uno nuevo actualiza encima.
  • Portable Limpieza-de-voz-portable.zip: se descomprime y se abre con Iniciar.bat.
  • Lleva dentro su propio Python 3.11, las dependencias (PyTorch CPU) y los modelos: funciona sin internet. Ocupa ~1 GB instalado.
  • Por dentro es la misma app (app.py) en 127.0.0.1. desktop/iniciar.py la arranca y abre el navegador; la ventana negra es el servidor.
  • Ficheros: desktop/ (lanzador, prueba de humo, icono, script de Inno Setup y publicación) y requirements-desktop.txt.

El repositorio de GitHub es privado, por eso el instalador se publica en Hugging Face: así se descarga sin necesidad de cuenta.


2. Perfiles de proyecto (perfiles/*.yaml)

Cada proyecto o cliente es un fichero YAML. Al crear uno nuevo, aparece solo en el desplegable «Proyecto».

Fichero Nombre en la app Uso
multiling_es-es_01.yaml MultiLing · voz femenina es-ES (40 min) Encargo MultiLing: WAV PCM, 48 kHz, ≥ 24 bits, SNR ≥ 50 dB. Sin recortes ni cambios de volumen (el cliente quiere la toma entera). Controla los 6 entregables y el objetivo de 40 min.
analizador_v4.yaml Proyecto 12 h 30 min · mismas reglas que el analizador v4 Las mismas reglas que el Analizador de audio v4 en HTML: WAV PCM 24 bits, 48 kHz, mono, pico ≤ −3 dBFS, RMS de voz −30…−20 dBFS, ruido ≤ −40 dB y silencios de 0,5–0,7 s.
asr_dialogo_dos_pistas.yaml ASR · diálogo a dos pistas Encargo ASR Dual-Track: WAV PCM 16 bits, 48 kHz, mono, espectro > 22 kHz, ruido de fondo ≤ −50 dBFS, voz > 5000 (escala 16 bits), sin saturación. Arranca en nivel «Solo formato» (el PDF pide sin procesado). Comprueba parejas de pistas (misma duración, sin voz cruzada).
libre.yaml Solo limpiar ruido · sin reglas de cliente Solo limpieza; conserva formato, frecuencia y canales.

Crear un perfil nuevo

Copia el que más se parezca, cámbiale el nombre al fichero y edita los valores. Todas las secciones son opcionales: lo que no pongas no se comprueba.

nombre: "Cliente X · audiolibro (10 h)"      # lo que se ve en el desplegable
descripcion: "WAV 24 bits · 44,1 kHz · …"    # resumen técnico de una línea
explicacion: |                               # lo que ve el usuario bajo el desplegable (Markdown)
  - **Qué pide el cliente:** …
  - **Qué hace la corrección:** …
orden: 3                                     # posición en el desplegable
procesar_siempre: false                      # true = limpiar aunque ya cumpla

formato:
  contenedor: WAV         # WAV | FLAC | AIFF
  pcm_entero: true        # exige PCM entero (no coma flotante)
  bits: 24                # exactamente 24…  (o bien)  bits_min: 24  → 24 o más
  frecuencia: 48000       # Hz; la corrección remuestrea
  ancho_banda_min_hz: 22000   # el espectro debe llegar más allá (detecta audio filtrado, comprimido o de 44,1 kHz)
  canales: 1              # 1 = exige mono (la casilla «Convertir a mono» sale marcada); null = sin requisito

niveles:
  pico_max_dbfs: -3.0     # techo de picos (se aplica limitador)
  rms_voz: {min: -30, max: -20, objetivo: -25}   # volumen medio de la voz; corrige al objetivo
  amplitud_voz_min: 5000  # muestra más alta de la voz en escala de 16 bits (0–32767)

ruido:
  snr_min_db: 50          # voz activa frente a ruido de las pausas
  ruido_relativo_max_db: -40   # primeros/últimos 0,4 s frente a la voz (criterio del analizador v4)
  ruido_fondo_max_dbfs: -50    # nivel absoluto del ruido de las pausas

silencios:                # null = no tocar inicio ni final
  min_s: 0.5
  max_s: 0.7
  objetivo_s: 0.6
  relleno: tono_sala      # tono_sala (ruido ambiente real, recomendado) | digital (ceros)

saturacion_max_muestras: 0
pistas_pareadas: false    # true = diálogo a dos pistas: comprueba duraciones idénticas y voz cruzada

procesado:                # valores por defecto de «Opciones avanzadas»
  reduccion_db: 24        # 12 Suave · 24 Natural · 36 Fuerte · null Máximo
  paso_alto_hz: 70        # null = sin filtro
  conservar_ultrasonidos: true
  salida: {contenedor: WAV, subtipo: PCM_24}   # null = como el original
  modo_defecto: ninja     # nivel de procesado inicial: formato | permitido | ninja (el usuario lo cambia en la app)

entregables:              # opcional: control de ficheros y duración total
  objetivo_total_s: 2400
  ficheros:
    - {nombre: "nonverbal_laughter", duracion_min_s: 30}
    - {nombre: "full recording_part 1", duracion_aprox_s: 760}

Los nombres de los entregables se comparan sin distinguir mayúsculas, extensión, espacios ni guiones bajos.


3. Cómo funciona

Cadena de corrección (pipeline.py)

  1. Canales: se conservan, salvo que se marque «Convertir a mono».
  2. Paso alto Butterworth de fase cero, a 70 Hz por defecto. Quita retumbes, golpes graves y DC.
  3. Remuestreo con SoX VHQ (fase lineal, sin desfase) a la frecuencia exigida.
  4. DeepFilterNet3 a 48 kHz, por bloques de 60 s con 5 s de contexto y fundido cruzado. Así los ficheros de 30 min o más tienen memoria acotada y llamadas a GPU cortas.
    • Si no se alcanza el ruido exigido, se escala la reducción: 24 → 36 dB → sin límite.
    • Como último recurso, un expansor de −15 dB solo en las pausas, con 100 ms de margen antes de la voz y 200 ms después.
  5. Más de 48 kHz: la banda > 20 kHz no pasa por el modelo. Se conserva del original mediante un cruce FIR complementario, con una ganancia que sigue la reducción aplicada en 12–20 kHz.
  6. Silencios inicial/final: recorte, o relleno con tono de sala (el tramo sin voz más silencioso de la propia toma, con fundidos de potencia constante).
  7. Nivel: ganancia hasta el RMS objetivo y limitador de picos con anticipación. El limitador es un mínimo deslizante suavizado, sin sobreoscilación garantizada.
  8. Escritura (dither TPDF si se baja a 16 bits) y nueva medición del fichero escrito: la columna «Después» es real.

Métricas (metrics.py, dnsmos.py)

  • Pico (dBFS) y pico real (dBTP, sobremuestreo ×4, por bloques).
  • RMS de voz entre la primera y la última voz, como el analizador v4.
  • Ruido relativo de los primeros/últimos 0,4 s frente a la voz.
  • SNR: voz activa frente a ruido de pausas.
  • Silencios: la detección de voz ignora clics y golpes de menos de 120 ms.
  • Saturación y LUFS (BS.1770-4; coeficientes verificados con la tabla ITU).
  • DNSMOS P.835 de Microsoft: SIG (voz), BAK (fondo) y OVRL (global), de 1 a 5. Usa como mucho 10 ventanas de 9 s repartidas por el audio. Es opcional («⭐ Poner nota de calidad al corregir», desmarcada por defecto) porque en CPUs modestas triplica el tiempo.

ZeroGPU

  • denoise_core.py coloca el modelo en cuda a nivel de módulo (patrón oficial de ZeroGPU) y decora la inferencia con @spaces.GPU y duración dinámica. Cada llamada cubre hasta 5 min de audio.
  • La GPU solo se usa con audios de 90 s o más. Para audios cortos, la espera de ZeroGPU (cola, asignación, comprobación de cuota) cuesta más que procesar en CPU.
  • Si una llamada falla (cuota, cola, timeout), el resto del fichero va por CPU con el mismo resultado. Durante 15 minutos no se vuelve a intentar con GPU, para no repetir la espera.
  • Si el original tiene mucho más ruido del permitido, la corrección empieza directamente por el escalón de reducción necesario. Así no se pasa el modelo varias veces.
  • Cuota diaria según la documentación de HF: 2 min sin sesión, 5 min con cuenta gratuita, 40 min con PRO.

Ficheros

Fichero Contenido
app.py Interfaz Gradio y textos de ayuda para el usuario
ui_html.py Tarjetas de resultados, CSS (móvil, modo claro/oscuro)
pipeline.py Analizar y corregir según un perfil
denoise_core.py DeepFilterNet3 + ZeroGPU + respaldo en CPU
dsp.py Remuestreo, filtros, detección de voz, silencios, limitador, expansor
metrics.py · dnsmos.py Mediciones
profiles.py · perfiles/ Carga de perfiles y comprobaciones
vad.py Detector de voz neuronal (Silero VAD) para los ruidos sueltos
pairs.py Parejas de pistas: misma duración y voz cruzada
report.py Informe Excel y CSV
audio_io.py Lectura (soundfile o ffmpeg) y escritura
models.py Descarga de modelos (DeepFilterNet3, DNSMOS, Silero VAD) verificada por SHA-256

4. Trabajo en local (Windows / PyCharm)

python -m venv .venv
.venv\Scripts\activate            # Linux/Mac: source .venv/bin/activate
pip install -r requirements-dev.txt
python app.py                     # http://localhost:7860
python -m pytest -q tests

deepfilternet 0.5.6 compila una parte en Rust si no hay paquete precompilado para tu sistema; en Windows hay que instalar Rust la primera vez. Las versiones están fijadas en requirements.txt: deepfilternet exige numpy < 2 y ZeroGPU exige torch ≥ 2.8. Los modelos se descargan la primera vez en ~/.cache/audio-denoise.

Créditos

  • DeepFilterNet (H. Schröter et al.), reducción de ruido.
  • DNSMOS (Microsoft), calidad percibida.