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

[**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>

Simularéis 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 pedagógica es que el **servidor** es solo el distribuidor (Icecast2), y los **clientes** pueden ser tanto emisores (con FFMPEG) como receptores (con VLC o navegador), cubriendo así el ciclo completo de RA7 y RA8.
{% 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>

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

Abre el firewall:

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

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

```
http://192.168.1.10: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
```

#### <mark style="color:$danger;">Explicación:</mark>

* <mark style="color:$danger;">`-re`</mark> <mark style="color:$danger;"></mark><mark style="color:$danger;">= reproduce en tiempo real (como si fuera una radio)</mark>
* <mark style="color:$danger;">`-i input.mp3`</mark> <mark style="color:$danger;"></mark><mark style="color:$danger;">= archivo de entrada</mark>
* <mark style="color:$danger;">`-c:a libmp3lame`</mark> <mark style="color:$danger;"></mark><mark style="color:$danger;">= codifica en MP3</mark>
* <mark style="color:$danger;">`-b:a 128k`</mark> <mark style="color:$danger;"></mark><mark style="color:$danger;">= bitrate del audio</mark>
* <mark style="color:$danger;">`-f mp3`</mark> <mark style="color:$danger;"></mark><mark style="color:$danger;">= formato del stream</mark>

> 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 [seccció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
   ```

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>

***

#### 🎙️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 (RA8.2) <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** (que ya tienen instalado de la práctica anterior).
