Protección contra Loops de Audio Infinitos en tu Radio
Cuando configuramos la salida de audio en VM 111 para La MIX Radio, nos encontramos con un ruido ensordecedor que casi nos deja sordos. Ese sonido metálico y creciente es la señal clara de que necesitamos una protección contra loops de audio infinitos inmediata. No es un problema de software, sino de rutas de audio que se muerden la cola. En este artículo vemos cómo detectar estos fallos y cómo evitar que vuelvan a ocurrir en nuestro entorno de streaming.
El problema concreto de la retroalimentación digital
Un loop ocurre cuando la señal de salida de nuestra radio vuelve a entrar como señal de entrada. En una radio tradicional AM/FM, esto es el clásico pitido del micrófono cerca del monitor. En el mundo del streaming y los homelabs, esto pasa cuando un script de Python lee la salida del sistema y la retransmite al mismo servidor de Icecast.
Si no se resuelve, el audio se amplifica a sí mismo en milisegundos. El resultado es una onda cuadrada que satura todo el ancho de banda y puede bloquear el servidor. Además, cualquier oyente conectado recibirá un golpe de sonido que puede dañar sus altavoces o auriculares. Lo peor es que, una vez que el loop empieza, el sistema suele quedar colgado y requiere un reinicio manual de la VM o del contenedor.
Esto nos lleva a analizar qué herramientas tenemos a mano para evitar que el audio se retroalimente en our propia infraestructura de Proxmox.
Qué necesitas antes de empezar
Para implementar estas medidas en nuestro entorno, hemos utilizado los siguientes elementos:
- Un servidor Proxmox con una VM corriendo Debian (nuestra VM 111).
- Icecast2 instalado y configurado como servidor de streaming.
- Python 3 instalado para gestionar los scripts de automatización.
- Acceso root a la terminal para modificar los archivos de configuración de audio.
- Un bot de Telegram conectado vía n8n para recibir alertas de saturación.
Cómo resolvimos la protección contra loops de audio infinitos
La primera medida que tomamos fue separar físicamente las interfaces de audio virtuales. No podemos permitir que el flujo de salida sea el mismo que el de entrada. Para lograrlo, configuramos rutas distintas en el sistema operativo.
Primero, definimos un dispositivo de salida dedicado para el monitoreo que no sea capturado por los scripts de transmisión. Creamos un script de Python que monitorea los niveles de entrada en tiempo real. Si el nivel de decibelios sube por encima de un umbral crítico durante más de dos segundos, el script corta el flujo.
Para implementar este control, usamos el siguiente bloque de código en Python que analiza la amplitud de la señal:
import numpy as np
import sounddevice as sd
# Umbral de amplitud para detectar loops (0.9 es casi saturación total)
THRESHOLD = 0.9
# Tiempo en segundos para activar la protección
DURATION = 2
def audio_callback(indata, frames, time, status):
# Calculamos el valor máximo de la señal actual
volume_norm = np.max(np.abs(indata))
if volume_norm > THRESHOLD:
print("Alerta: Saturación detectada. Verificando loop...")
# Aquí dispararíamos la señal de corte al servidor Icecast
Una vez que el script detecta la saturación, necesitamos que la acción sea inmediata. No podemos esperar a que un humano reaccione. Por eso, conectamos este disparador con una instrucción que reinicia el proceso de envío de audio hacia el servidor de streaming.
En el caso de nginx, que usamos como proxy frente a Icecast, configuramos límites de tiempo de respuesta para evitar que una conexión colgada por un loop sature la tabla de procesos. Usamos la siguiente configuración de proxy para evitar que los buffers se llenen de ruido infinito:
server {
listen 80;
server_name lamixradio.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Desactivamos el buffering para que el audio fluya sin retrasos
proxy_buffering off;
# Evitamos que la conexión quede abierta eternamente en caso de loop
proxy_read_timeout 3600;
}
}
Después de ajustar el proxy, nos dimos cuenta de que el problema también podía venir de la automatización. Cuando usamos emily_gtts.py para generar locuciones, si el archivo de audio se reproduce en una carpeta que el script de streaming lee constantemente, se crea un ciclo infinito de reproducción.
Para solucionar esto, implementamos un sistema de «banderas» o archivos temporales. El script de streaming solo lee archivos que tengan el atributo de «listo para emitir». De esta forma, la protección contra loops de audio infinitos se vuelve estructural: el sistema no puede leer lo que todavía está escribiendo.
La mejor protección contra loops de audio infinitos no es un software caro, sino una arquitectura donde la entrada y la salida nunca se tocan en la misma capa lógica.
Errores que nos costaron tiempo
En el camino hacia un sistema estable, cometimos varios fallos que nos hicieron perder horas de sueño a las 2 de la mañana.
El primero fue confiar en el «auto-gain control» del sistema. Pensamos que el control automático de ganancia evitaría el loop, pero lo que hacía era comprimir el ruido ensordecedor, haciendo que el loop persistiera sin saturar el clip, pero manteniendo la retroalimentación.
El segundo error fue configurar el bot de Telegram para avisar en cada pico de volumen. Recibimos 500 notificaciones en un minuto durante un loop, lo que provocó que Telegram bloqueara temporalmente nuestro bot de n8n por exceso de peticiones.
El tercer fallo fue no reiniciar la VM 111 después de cambiar los drivers de ALSA. El sistema decía que la configuración estaba aplicada, pero el loop seguía activo porque el kernel mantenía el buffer antiguo en memoria.
Cómo saber que funciona
Para verificar que la protección está activa, hacemos una prueba controlada. Forzamos una entrada de audio saturada en un entorno aislado y observamos los logs de Python. Si el script detecta el umbral y corta el flujo en menos de dos segundos, el sistema es seguro. Además, comprobamos que el proxy de nginx no acumula procesos «zombie» cuando cortamos la transmisión bruscamente.
Qué sigue
Ahora que tenemos el audio bajo control, el siguiente paso es automatizar la recuperación. Estamos trabajando en un script que no solo corte la señal, sino que analice la fuente del ruido y reinicie solo el contenedor afectado en Proxmox sin interrumpir la música de fondo de La MIX Radio.

