# Icecast - música, vídeo, RSS en streamingnotepad

[**Icecast**](https://icecast.org/docs/) es un servidor de streaming multimedia de código abierto desarrollado y mantenido por la **Fundación Xiph.org**, publicado bajo licencia GNU GPLv2 y disponible de forma totalmente gratuita. Fue creado en 1998 con el objetivo de ofrecer una alternativa libre a los servidores de radio por internet comerciales de la época.

#### ¿Qué hace exactamente? <a href="#qu-hace-exactamente" id="qu-hace-exactamente"></a>

Icecast actúa como **intermediario entre el emisor y los oyentes/espectadores**: recibe un flujo de audio o vídeo de una fuente (llamada *source*) y lo redistribuye simultáneamente a todos los clientes conectados. La analogía más directa es una **emisora de radio**: hay una cabina de emisión (la fuente) y miles de radios que reciben la señal (los clientes), pero ningún cliente habla directamente con otro.​

Sus características principales son:​

* Soporta múltiples formatos: **MP3, OGG Vorbis, Opus, OGG Theora, WebM, AAC**
* Permite tener varios **mountpoints** simultáneos (varios canales en el mismo servidor)
* Incluye un **panel de administración web** accesible desde el navegador (puerto 8000)
* Puede autenticar usuarios tanto emisores como receptores
* Es compatible con reproductores estándar como **VLC, Winamp, navegadores web**

La arquitectura de Icecast es la siguiente:

```
[Fuente/Emisor] ──push──▶ [Servidor Icecast2] ──stream──▶ [Cliente 1]
   (FFMPEG, Ices2)          puerto 8000                    [Cliente 2]
                                                           [Cliente N]
```

Por otro lado está **FFmpeg** que, [como hemos visto](https://apuntes-alex.gitbook.io/apuntes-sistemas-y-redes/servicios/multimedia-services/ffmpeg-y-yt-dlp), es una colección de herramientas y bibliotecas de código abierto que permite **grabar, convertir (transcodificar) y hacer streaming** de prácticamente cualquier formato de audio y vídeo que existe.&#x20;

## Implementación de servidor Multimedia con Icecast2 + FFMPEG <a href="#gua-servidor-multimedia-con-icecast2--ffmpeg-ra7" id="gua-servidor-multimedia-con-icecast2--ffmpeg-ra7"></a>

### Escenario del laboratorio <a href="#escenario-del-laboratorio" id="escenario-del-laboratorio"></a>

Simularemos una **plataforma de streaming corporativa** de la empresa `empresa.local`. El esquema de máquinas es el siguiente, con una red NAT o interna:

<table><thead><tr><th width="131.88885498046875">Máquina</th><th width="197.888916015625">SO</th><th width="267.666748046875">Rol</th><th>IP ejemplo</th></tr></thead><tbody><tr><td><code>servidor</code></td><td>Ubuntu Server 24.04</td><td>Icecast2 (audio + vídeo)</td><td>192.168.1.10</td></tr><tr><td><code>cliente1</code></td><td>Ubuntu Desktop 24.04</td><td>VLC + navegador (receptor)</td><td>192.168.1.20</td></tr><tr><td><code>cliente2</code></td><td>Ubuntu Desktop 24.04</td><td>FFMPEG (emisor/fuente)</td><td>192.168.1.21</td></tr></tbody></table>

{% hint style="info" %}
La idea de esto es que el **servidor** es solo el distribuidor (Icecast2), mientras que los **clientes** pueden ser tanto emisores (con FFMPEG) como receptores (con VLC o navegador).
{% endhint %}

### PARTE 1 — Instalación y configuración de Icecast2 <a href="#parte-1--instalacin-y-configuracin-de-icecast2-ser" id="parte-1--instalacin-y-configuracin-de-icecast2-ser"></a>

Vamos con el servidor ubuntu, donde instalaremos este servidor de streaming:

#### Paso 1: Instalar Icecast2 <a href="#paso-1-instalar-icecast2" id="paso-1-instalar-icecast2"></a>

```bash
sudo apt update && sudo apt install -y icecast2
```

Durante la instalación aparece un asistente de configuración. Selecciona **Sí** y rellena:

* **Hostname:** `servidor.empresa.local`
* **Source password:** `source123` (la usará FFMPEG para publicar)
* **Relay password:** `relay123`
* **Admin password:** `admin123`

Si quieres saltarte el asistente y configurar manualmente después:

```bash
sudo dpkg-reconfigure icecast2
```

#### Paso 2: Configurar `/etc/icecast2/icecast.xml` <a href="#undefined" id="undefined"></a>

Este archivo es&#x20;

```bash
sudo nano /etc/icecast2/icecast.xml
```

Ajusta o verifica estas secciones clave:

```xml
<icecast>
  <location>Empresa Local</location>
  <admin>admin@empresa.local</admin>

  <!-- Límite de clientes simultáneos -->
  <limits>
    <clients>100</clients>
    <sources>10</sources>
    <threadpool>5</threadpool>
    <queue-size>524288</queue-size>
    <client-timeout>30</client-timeout>
    <header-timeout>15</header-timeout>
    <source-timeout>10</source-timeout>
  </limits>

  <!-- Contraseñas -->
  <authentication>
    <source-password>source123</source-password>
    <relay-password>relay123</relay-password>
    <admin-user>admin</admin-user>
    <admin-password>admin123</admin-password>
  </authentication>

  <!-- Nombre del servidor -->
  <hostname>192.168.1.10</hostname>

  <!-- Puerto principal -->
  <listen-socket>
    <port>8000</port>
  </listen-socket>

  <!-- Directorio web de Icecast -->
  <paths>
    <basedir>/usr/share/icecast2</basedir>
    <logdir>/var/log/icecast2</logdir>
    <webroot>/usr/share/icecast2/web</webroot>
    <adminroot>/usr/share/icecast2/admin</adminroot>
    <alias source="/" dest="/status.xsl"/>
  </paths>

  <!-- Logs -->
  <logging>
    <accesslog>access.log</accesslog>
    <errorlog>error.log</errorlog>
    <loglevel>3</loglevel>
  </logging>
</icecast>
```

#### Paso 3: Activar y arrancar Icecast2 <a href="#paso-3-activar-y-arrancar-icecast2" id="paso-3-activar-y-arrancar-icecast2"></a>

Si no esta arrancado por defecto:

```bash
sudo systemctl enable icecast2
sudo systemctl start icecast2
sudo systemctl status icecast2
```

Abre el firewall si está activado:

```bash
sudo ufw allow 8000/tcp
```

Verifica desde el navegador del cliente que el panel de control de Icecast es accesible:

```
http://<IP>:8000
```

Deberías ver la página de estado de Icecast2 con los mountpoints vacíos todavía.

***

### PARTE 2 — Instalar FFMPEG en los clientes <a href="#parte-2--instalar-ffmpeg-en-los-clientes" id="parte-2--instalar-ffmpeg-en-los-clientes"></a>

En **Ubuntu Desktop** (cliente1 y cliente2):

```bash
sudo apt install -y ffmpeg vlc
```

Verifica la instalación:

```bash
ffmpeg -version
```

***

### PARTE 3 — Streaming de Audio  :radio: <a href="#parte-3--streaming-de-audio-ra7" id="parte-3--streaming-de-audio-ra7"></a>

#### :musical\_note: Emitir un stream de audio con FFMPEG <a href="#paso-4-emitir-un-stream-de-audio-con-ffmpeg" id="paso-4-emitir-un-stream-de-audio-con-ffmpeg"></a>

Desde el **cliente2** (el emisor), usamos un fichero de audio como fuente.&#x20;

Puedes crear o descarga un fichero de prueba:

```bash
# Genera un tono de prueba de 60 segundos si no tienes fichero
ffmpeg -f lavfi -i "sine=frequency=440:duration=60" /tmp/prueba_audio.mp3
```

Y ahora emitir el stream hacia Icecast2:

```bash
# Stream MP3
ffmpeg -re -i /tmp/prueba_audio.mp3 \
  -vn \
  -acodec libmp3lame \
  -ab 128k \
  -ar 44100 \
  -content_type audio/mpeg \
  -f mp3 \
  icecast://source:source123@192.168.1.10:8000/radio.mp3
```

#### Explicación:

* `-re` = reproduce en tiempo real (como si fuera una radio)
* `-i input.mp3` = archivo de entrada
* `-vn` = no video, lo ignora
* `-acodec libmp3lame` = codifica en MP3
* `-ab 128k` = bitrate del audio
* `-f mp3` = formato del stream
* `-ar 44100` = establece la tasa de muestreo de audio
* `-content_type audio/mpeg` = le indica que tipo de contenido va a recibir (el MIME)

> De la cadena de conexión, cambia:
>
> * `source123` → tu contraseña de **source** en `icecast.xml`
> * `IP`→ IP local o pública de tu servidor
> * `/radio.mp3` → el mount point definido

O bien pudieras enviar toda una carpeta en loop:

```bash
ffmpeg -re -stream_loop -1 -i "$(find ~/Music -type f -name '*.mp3' | shuf -n 1)" \
  -c:a libmp3lame -b:a 128k \
  -content_type audio/mpeg \
  -f mp3 \
   icecast://source:source123@192.168.1.10:8000/radio.mp3
```

{% hint style="info" %}
Esto tomará una canción al azar en bucle infinito (puedes combinarlo con scripts para rotación aleatoria).
{% endhint %}

También, para emitir en formato **OGG/Vorbis** (libre y sin patentes):

```bash
ffmpeg -re -i /tmp/prueba_audio.mp3 \
  -vn \
  -acodec libvorbis \
  -ab 128k \
  -content_type application/ogg \
  -f ogg \
  icecast://source:source123@192.168.1.10:8000/radio.ogg
```

Para revisar el stream ves a la [sección más abajo](#paso-5-escuchar-el-stream-de-audio-ra75--ra76-1).&#x20;

<details>

<summary>Script para crear una "radio casera"</summary>

Aquí tienes un **script Bash listo para lanzar automáticamente un stream de audio a Icecast usando FFmpeg**, ideal para una radio casera o personal:

{% code title="stream\_radio.sh" %}

```bash
#!/bin/bash

# CONFIGURACIÓN DEL STREAM
ICECAST_HOST="192.168.1.10"
ICECAST_PORT="8000"
ICECAST_PASSWORD="source123"
ICECAST_MOUNT="/stream.mp3"

# CONFIGURACIÓN DE AUDIO
BITRATE="128k"
CODEC="libmp3lame"
CONTENT_TYPE="audio/mpeg"
FORMAT="mp3"

# DIRECTORIO CON MÚSICA
MUSIC_DIR="$HOME/Music"

# LOGO
echo "🎵 Iniciando stream de radio con FFmpeg..."

# COMPROBAR FFmpeg
if ! command -v ffmpeg &> /dev/null; then
    echo "❌ FFmpeg no está instalado."
    exit 1
fi

# COMPROBAR QUE HAY MÚSICA
if [ ! -d "$MUSIC_DIR" ]; then
    echo "❌ No se encontró el directorio de música: $MUSIC_DIR"
    exit 1
fi

# INICIAR EL STREAM (loop aleatorio)
while true; do
    echo "🔁 Reproduciendo nuevo archivo..."
    FILE=$(find "$MUSIC_DIR" -type f \( -iname "*.mp3" -o -iname "*.ogg" \) | shuf -n 1)
    
    if [ -z "$FILE" ]; then
        echo "⚠️ No se encontraron archivos de audio."
        sleep 10
        continue
    fi

    echo "🎧 Reproduciendo: $FILE"
    
    ffmpeg -re -i "$FILE" \
        -c:a $CODEC -b:a $BITRATE \
        -content_type $CONTENT_TYPE \
        -f $FORMAT \
        icecast://source:$ICECAST_PASSWORD@$ICECAST_HOST:$ICECAST_PORT$ICECAST_MOUNT

    echo "🛑 FFmpeg se detuvo. Reiniciando en 5 segundos..."
    sleep 5
done
```

{% endcode %}

A estas alturas deberias saber usar el script pero por si acaso:

1. **Guarda el script:**

   ```bash
   nano stream_radio.sh
   ```

   (Pega el contenido y guarda con `Ctrl+O`, `Enter`, `Ctrl+X`)
2. **Hazlo ejecutable:**

   ```bash
   chmod +x stream_radio.sh
   ```
3. **Ejecuta el script:**

   ```bash
   ./stream_radio.sh
   ```
4. 🎧 Abre en tu móvil o navegador:

   ```
   http://<tu_ip_local>:8000/stream.mp3
   ```

Ahora, desde cliente, descarga un sonido corto con `yt-dlp` y envialo por streaming con `ffmpeg` al seridor de cast para ver el resultado.

Algunos extras que puedes añadir:

* Auto-stop tras X canciones o tiempo.
* Logs de reproducción.
* Añadir jingles entre canciones.
* Transiciones suaves con `ffmpeg` (fundido cruzado).

</details>

<details>

<summary>PRACTICA en clase: Radio del centro</summary>

A partir de un servidor de IceCast vamos a habilitar la posibilidad de escuchar canciones, primero ejecutaremos este script sobre la carpeta de `/home/usuario/Music`:&#x20;

```bash
#!/bin/bash

# ============================================================
#  STREAM_RADIO.SH — Servidor de radio para clase ASIR
#  Reproduce en bucle los ficheros de Music/ hacia Icecast2
# ============================================================

# CONFIGURACIÓN DEL SERVIDOR ICECAST
ICECAST_HOST="192.168.1.10"
ICECAST_PORT="8000"
ICECAST_PASSWORD="source123"
ICECAST_MOUNT="/radio.mp3"

# CONFIGURACIÓN DE AUDIO
BITRATE="128k"
CODEC="libmp3lame"
CONTENT_TYPE="audio/mpeg"
FORMAT="mp3"
SAMPLE_RATE="44100"

# DIRECTORIO CON MÚSICA (los alumnos suben aquí sus ficheros)
MUSIC_DIR="$HOME/Music"

# FICHERO DE LOG
LOG_FILE="$HOME/stream_radio.log"

# ============================================================
# FUNCIONES AUXILIARES
# ============================================================

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

show_banner() {
    echo "=============================================="
    echo "  _____ ______ _____   "
    echo " |_   _|  ____|  __ \  " 
    echo "   | | | |__  | |__) | "
    echo "   | | |  __| |  ___/  "
    echo "  _| |_| |    | |      "
    echo " |_____|_|    |_|      "       
    echo "=============================================="
    echo "  🎵  RADIO EMPRESA.LOCAL — Stream con FFMPEG"
    echo "  📡  Servidor : $ICECAST_HOST:$ICECAST_PORT"
    echo "  🎚️  Mountpoint: $ICECAST_MOUNT"
    echo "  📁  Carpeta  : $MUSIC_DIR"
    echo "  🌐  Escuchar : http://$ICECAST_HOST:$ICECAST_PORT$ICECAST_MOUNT"
    echo "=============================================="
}

# ============================================================
# COMPROBACIONES PREVIAS
# ============================================================

show_banner

# Comprobar FFmpeg
if ! command -v ffmpeg &> /dev/null; then
    echo "❌ ERROR: FFmpeg no está instalado."
    echo "   Instálalo con: sudo apt install -y ffmpeg"
    exit 1
fi

# Comprobar que existe el directorio de música
if [ ! -d "$MUSIC_DIR" ]; then
    log "❌ No se encontró el directorio: $MUSIC_DIR"
    log "   Créalo con: mkdir -p $MUSIC_DIR"
    exit 1
fi

log "✅ Comprobaciones superadas. Iniciando stream..."
log "   Los alumnos pueden subir ficheros con:"
log "   scp audio.mp3 ubuntu@$ICECAST_HOST:$MUSIC_DIR/"

# ============================================================
# BUCLE PRINCIPAL DE STREAMING
# ============================================================

while true; do

    # Buscar todos los ficheros de audio en la carpeta (MP3 y OGG)
    mapfile -t FILES < <(find "$MUSIC_DIR" -type f \( -iname "*.mp3" -o -iname "*.ogg" \) | sort)

    # Si no hay ficheros, esperar y reintentar
    if [ ${#FILES[@]} -eq 0 ]; then
        log "⚠️  No hay ficheros de audio en $MUSIC_DIR"
        log "   Esperando 15 segundos antes de reintentar..."
        sleep 15
        continue
    fi

    log "📋 Lista de reproducción actualizada: ${#FILES[@]} fichero(s) encontrado(s)"

    # Reproducir cada fichero de la lista en orden
    for FILE in "${FILES[@]}"; do
        FILENAME=$(basename "$FILE")
        log "▶️  Reproduciendo: $FILENAME"

        ffmpeg -re \
               -i "$FILE" \
               -vn \
               -c:a "$CODEC" \
               -b:a "$BITRATE" \
               -ar "$SAMPLE_RATE" \
               -content_type "$CONTENT_TYPE" \
               -f "$FORMAT" \
               -loglevel warning \
               "icecast://source:$ICECAST_PASSWORD@$ICECAST_HOST:$ICECAST_PORT$ICECAST_MOUNT"

        # Comprobar si FFmpeg terminó con error
        EXIT_CODE=$?
        if [ $EXIT_CODE -ne 0 ]; then
            log "⚠️  FFmpeg terminó con error (código $EXIT_CODE) en: $FILENAME"
            log "   Comprueba que Icecast2 está activo en el servidor."
            sleep 5
        else
            log "✅ Fichero completado: $FILENAME"
        fi
    done

    log "🔁 Lista completada. Reiniciando desde el principio..."
    log "   (Añade nuevos ficheros a $MUSIC_DIR para incluirlos en la próxima vuelta)"

done
```

Este script ejecutará en bucle todos los archivos que haya en la carpeta de Música.

Como pueden contribuir los alumnos a la radio? Simplemente se envia el archivo por scp a la carpeta del servidor:

```
scp /tmp/prueba_audio.mp3 <user>@<IP>:/home/<user>/Music/<alumno>.mp3
```

</details>

***

#### 🎙️Streaming de audio en vivo (micrófono)

Para el streaming en vivo (también tipo radio) pero que se puede usar para captar audios en directo puedes realizarlo con ALSA o bien a través de Pulse Audio.

Si es con **ALSA**, primero, encuentra tu dispositivo con:

```bash
arecord -l
```

Ejemplo para usar el dispositivo por defecto:

```bash
ffmpeg -f alsa -i default \
  -c:a libmp3lame -b:a 128k \
  -content_type audio/mpeg \
  -f mp3 \
  icecast://source:source123@192.168.1.10:8000/stream.mp3
```

Ahora bien, con **PulseAudio** seria:

```bash
ffmpeg -f pulse -i default \
  -c:a libmp3lame -b:a 128k \
  -content_type audio/mpeg \
  -f mp3 \
  icecast://source:source123@192.168.1.10:8000/stream.mp3
```

> También puedes hacer streaming de lo que esté **saliendo por tus altavoces** con `pulse` usando el **monitor** de tu tarjeta:

```bash
ffmpeg -f pulse -i "alsa_output.pci-0000_00_1f.3.analog-stereo.monitor" ...
```

{% hint style="info" %}
**Tip Extra: Metadata y título**

Puedes añadir información del stream con el parámetro `-metadata` por ejemplo:

```bash
ffmpeg -re -i input.mp3 \
  -c:a libmp3lame -b:a 128k \
  -content_type audio/mpeg \
  -f mp3 \
  -metadata title="Mi Radio FFMPEG" \
  icecast://source:hackme@localhost:8000/stream.mp3
```

{% endhint %}

***

#### Escuchar el stream de audio  <a href="#paso-5-escuchar-el-stream-de-audio-ra75--ra76" id="paso-5-escuchar-el-stream-de-audio-ra75--ra76"></a>

Para escuchar los streamings anteriores puedes hacerlo desde varias aplicaciones:

* **Desde VLC** (cliente1):

```
Medios → Abrir URL de red → http://192.168.1.10:8000/radio.mp3
```

* **Desde el navegador** (Firefox/Chromium en cliente1) — navega a:

```
http://192.168.1.10:8000/radio.mp3
```

* Desde el panel de Icecast para ver los mountpoints activos:

```
http://192.168.1.10:8000/status.xsl
```

***

### PARTE 4 — Streaming de Vídeo :video\_camera: <a href="#parte-4--streaming-de-vdeo-ra8" id="parte-4--streaming-de-vdeo-ra8"></a>

#### Paso 6: Preparar un fichero de vídeo de prueba <a href="#paso-6-preparar-un-fichero-de-vdeo-de-prueba" id="paso-6-preparar-un-fichero-de-vdeo-de-prueba"></a>

Si no tienes un vídeo, genera uno con FFMPEG:

```bash
# Vídeo de prueba: 60 segundos, resolución 640x480
ffmpeg -f lavfi -i testsrc=duration=60:size=640x480:rate=25 \
       -f lavfi -i sine=frequency=440:duration=60 \
       -c:v libtheora -q:v 7 \
       -c:a libvorbis -q:a 4 \
       /tmp/prueba_video.ogv
```

#### Paso 7: Emitir el stream de vídeo con FFMPEG <a href="#paso-7-emitir-el-stream-de-vdeo-con-ffmpeg-ra82" id="paso-7-emitir-el-stream-de-vdeo-con-ffmpeg-ra82"></a>

```bash
# Stream de vídeo OGG Theora + Vorbis hacia Icecast2
ffmpeg -re -i /tmp/prueba_video.ogv \
  -c:v libtheora \
  -q:v 5 \
  -c:a libvorbis \
  -q:a 4 \
  -content_type video/ogg \
  -f ogg \
  icecast://source:source123@192.168.1.10:8000/video.ogv
```

Para emitir en **WebM** (compatible con más navegadores modernos):

```bash
ffmpeg -re -i /tmp/prueba_video.ogv \
  -c:v libvpx \
  -b:v 500k \
  -c:a libvorbis \
  -q:a 4 \
  -content_type video/webm \
  -f webm \
  icecast://source:source123@192.168.1.10:8000/video.webm
```

#### Paso 8: Reproducir el stream de vídeo <a href="#paso-8-reproducir-el-stream-de-vdeo-ra83" id="paso-8-reproducir-el-stream-de-vdeo-ra83"></a>

De nuevo para reproducir el stream de video lo hariamos desde:

* **Desde VLC** (cliente1):

```
Medios → Abrir URL de red → http://192.168.1.10:8000/video.ogv
```

* **Desde el navegador** (Firefox soporta OGG Theora nativamente):

```
http://192.168.1.10:8000/video.ogv
```

***

### PARTE 5 — Sindicación RSS/Atom :newspaper: <a href="#parte-5--sindicacin-rssatom-ra77--ra85" id="parte-5--sindicacin-rssatom-ra77--ra85"></a>

Ya por último podemos montar un servicio de RSS, **RSS** (*Really Simple Syndication*) es un formato basado en **XML** que permite distribuir y suscribirse a contenidos de sitios web de forma automática, sin necesidad de visitar la página manualmente cada vez.​

### Cómo funciona técnicamente <a href="#cmo-funciona-tcnicamente" id="cmo-funciona-tcnicamente"></a>

El servidor publica un fichero de texto en formato XML (el **feed** o fuente), que contiene una lista estructurada de los últimos contenidos disponibles: título, descripción, fecha y enlace. El cliente usa un programa llamado **lector RSS** o **agregador** que consulta ese fichero periódicamente y muestra las novedades al usuario.

#### Paso 9: Crear un feed RSS para el stream <a href="#paso-9-crear-un-feed-rss-para-el-stream" id="paso-9-crear-un-feed-rss-para-el-stream"></a>

Crea manualmente un fichero XML de sindicación en el servidor que los clientes pueden suscribir:

```bash
sudo nano /usr/share/icecast2/web/feed.rss
```

Con el siguiente contenido:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Streams de Empresa Local</title>
    <link>http://192.168.1.10:8000</link>
    <description>Canal de streaming corporativo</description>

    <item>
      <title>Ràdio Empresa (MP3)</title>
      <description>Stream d'àudio en directe</description>
      <enclosure url="http://192.168.1.10:8000/radio.mp3"
                 type="audio/mpeg"/>
    </item>

    <item>
      <title>Canal Vídeo Empresa (OGV)</title>
      <description>Stream de vídeo corporatiu</description>
      <enclosure url="http://192.168.1.10:8000/video.ogv"
                 type="video/ogg"/>
    </item>

  </channel>
</rss>
```

El feed queda accesible en:

```
http://192.168.1.10:8000/feed.rss
```

Los alumnos pueden suscribirse desde **VLC** (Medios → Servicios de internet → Podcasts) o desde cualquier lector RSS como **Thunderbird**.
