--- 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. ```yaml 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) ```bash 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](https://rustup.rs) 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](https://github.com/Rikorose/DeepFilterNet) (H. Schröter et al.), reducción de ruido. - [DNSMOS](https://github.com/microsoft/DNS-Challenge/tree/master/DNSMOS) (Microsoft), calidad percibida.