Spaces:
Running on Zero
Running on Zero
File size: 11,833 Bytes
cb5f078 86fb0e9 cb5f078 86fb0e9 7e8e229 86fb0e9 7e8e229 cb5f078 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 c6a2c55 fc527e7 4c6ff29 fc527e7 4c6ff29 fc527e7 4c6ff29 fc527e7 4c6ff29 fc527e7 c6a2c55 fc527e7 7e8e229 fc527e7 c6a2c55 4c6ff29 fc527e7 c6a2c55 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 fc527e7 7e8e229 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | ---
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.
|