> ## Índice de la documentación
> Consulta el índice completo de la documentación en: https://developer.rhombus.com/llms.txt
> Úsalo para descubrir todas las páginas disponibles antes de seguir explorando.

# Recuperar audio del Audio Gateway A100

> Descarga audio grabado de un Rhombus A100 Audio Gateway usando la API: obtén manifiestos MPD de DASH, recupera segmentos y reproduce audio mediante WAN VOD.

> **Note**: Esta página se tradujo automáticamente. Si encuentras errores o tienes sugerencias, [escríbenos](mailto:support@rhombus.com).

En esta guía, aprenderás a recuperar **audio grabado** de un Rhombus **A100 Audio Gateway** usando la API de Rhombus. Vas a:

1. Llamar a la API para obtener las plantillas de URI de medios
2. Generar un token de sesión federado para la reproducción por WAN
3. Descargar el MPD de DASH y los segmentos de audio
4. Opcionalmente convertir el audio Opus/WebM resultante usando ffmpeg

Rhombus expone el acceso a los medios mediante **plantillas de URI** en lugar de devolver los bytes de audio sin procesar directamente desde una única respuesta REST.

## Requisitos previos

> **Note**: Todas las llamadas a la API en esta guía usan los siguientes encabezados de autenticación:
>
> ```http
> Content-Type: application/json
> x-auth-scheme: api-token
> x-auth-apikey: YOUR_API_KEY
> ```
>
> URL base: `https://api2.rhombussystems.com`

**Necesitarás:**

- Un UUID del A100 Audio Gateway (cadena de estilo DeviceFacetUuid / RUUID de Rhombus)
- Audio grabado que exista y esté disponible (determinado por las licencias de tu dispositivo y la configuración de grabación)
- Un cliente capaz de:
  - Realizar solicitudes HTTP
  - Analizar XML (para el manifiesto MPD)
  - Escribir los bytes binarios de los segmentos en disco

## Pasos de implementación

1. **Obtener los URIs de medios del A100 Audio Gateway**

   Llama al endpoint `getMediaUris` para recuperar las plantillas de URI de tu audio gateway.

   **Endpoint:** [`POST /api/audiogateway/getMediaUris`](https://developer.rhombus.com/api-reference/audiogateway-webservice/get-media-uris-for-audio-gateway)

   ```bash
   curl --request POST \
     --url https://api2.rhombussystems.com/api/audiogateway/getMediaUris \
     --header 'Content-Type: application/json' \
     --header 'x-auth-scheme: api-token' \
     --header 'x-auth-apikey: YOUR_API_KEY' \
     --data '{
       "gatewayUuid": "AAAAAAAAAAAAAAAAAAAAAA.v0"
     }'
   ```

   **Campos relevantes de la respuesta:**

   | Campo                    | Descripción                                                                                        |
   | ------------------------ | -------------------------------------------------------------------------------------------------- |
   | `wanVodMpdUriTemplate`   | Plantilla MPD de WAN VOD (úsala para audio grabado por WAN)                                        |
   | `wanLiveOpusUri`         | Transmisión Opus en vivo por WAN (WebSocket). No termina en `/ws`: añade `/ws` antes de conectarte |
   | `wanLiveMpdUri`          | URI MPD en vivo por WAN                                                                            |
   | `lanVodMpdUrisTemplates` | Plantillas de LAN VOD                                                                              |

   Los URI LAN (`lanLiveOpusUris`, `lanLiveMpdUris`, `lanVodMpdUrisTemplates`) los sirve el propio gateway, que por diseño solo acepta tokens federados. Consulta [Streaming por LAN](https://developer.rhombus.com/es/implementations/lan-streaming) para la autenticación y el formato del WebSocket de audio bidireccional.

   El socket Opus en vivo (`wanLiveOpusUri` más `/ws`) transporta la escucha y el audio bidireccional. Desde un servidor, autentícalo con los encabezados de tu clave de API o con un access token de OAuth (`Authorization: Bearer <token>`); en un navegador, usa un token federado como parámetros de consulta. Un token de OAuth necesita el scope `read` para escuchar y el scope `physical` para enviar audio de habla: el audio enviado sin `physical` cierra el socket con el código `1008`. Si la credencial se elimina o revoca, o su rol cambia, el socket abierto se cierra con el código `1008` en 60 segundos o menos.

2. **Generar un token de sesión federado**

   Desde un servidor, puedes obtener el MPD por WAN y sus segmentos con los encabezados de tu clave de API (`x-auth-scheme: api-token` y `x-auth-apikey`) en cada solicitud, o con `Authorization: Bearer <token>` para un access token de OAuth con el scope `read`. Esta guía usa en su lugar un token de sesión federado de corta duración, añadido como parámetros de consulta, que también funciona en reproductores que no pueden enviar encabezados. (Esos mismos dos valores también funcionan como encabezados).

   **Endpoint:** [`POST /api/org/generateFederatedSessionToken`](https://developer.rhombus.com/api-reference/org-webservice/generate-federated-session-token)

   ```bash
   curl --request POST \
     --url https://api2.rhombussystems.com/api/org/generateFederatedSessionToken \
     --header 'Content-Type: application/json' \
     --header 'x-auth-scheme: api-token' \
     --header 'x-auth-apikey: YOUR_API_KEY' \
     --data '{
       "durationSec": 60
     }'
   ```

   **Respuesta:** Devuelve `federatedSessionToken` y `expiresAtMs`, el momento en que expira el token en milisegundos Unix.

   > **Warning**: No uses `domain` en un token que usarás desde un servidor. Un token generado con `domain` solo funciona en solicitudes cuyo `Origin` (o, cuando no hay `Origin`, `Referer`) es exactamente ese origen, como `https://app.example.com`. Las solicitudes del lado del servidor no envían ninguno de los dos, así que todas las solicitudes del MPD y de los segmentos fallan con 403 `DOMAIN_NOT_ALLOWED`. `domain` debe ser un origen absoluto; un valor como `.rhombussystems.com` se rechaza al generar el token (400). Consulta [El campo domain](https://developer.rhombus.com/es/authentication/federated-tokens#el-campo-domain).

   > **Tip**: `durationSec` vale 3600 (una hora) de forma predeterminada y no puede superar 86400 (24 horas). Para una descarga que tarda más de lo que dura el token, genera un token nuevo antes del `expiresAtMs` de la respuesta, como hace el ejemplo completo de abajo.

3. **Construir la URL del MPD de WAN VOD**

   Toma el `wanVodMpdUriTemplate` del Paso 1 y realiza la sustitución de cadenas:

   - Reemplaza `{START_TIME}` con la hora de inicio solicitada (en segundos)
   - Reemplaza `{DURATION}` con la duración solicitada (en segundos)

   > **Warning**: **Las unidades de las marcas de tiempo importan.**
   >
   > Los endpoints de audio de Rhombus usan **segundos desde la época** (`startTimeSec`, `durationSec`). Si tus marcas de tiempo están almacenadas en milisegundos, conviértelas:
   >
   > ```text
   > startTimeSec = startTimeMs / 1000
   > durationSec = durationMs / 1000
   > ```

4. **Obtener el MPD con el token federado**

   Añade los parámetros de consulta de autenticación a tu URL del MPD:

   ```text
   <mpdUri>?x-auth-scheme=federated-token&x-auth-ft=<TOKEN>
   ```

   Este MPD es un manifiesto DASH que describe cómo obtener el segmento de inicialización y los segmentos de audio posteriores. En el host de WAN, las URL de segmento del MPD llevan los mismos parámetros de consulta, así que un reproductor DASH que recibe esta URL no necesita nada más.

5. **Descargar y unir los segmentos**

   Si construyes tú mismo las URL de los segmentos, como hace esta guía, descárgalos en orden, añadiendo los mismos parámetros de consulta `?x-auth-scheme=federated-token&x-auth-ft=<TOKEN>` que usaste para el MPD: los segmentos se sirven desde el mismo host de WAN y usan la misma autenticación:

   1. **Segmento de inicialización** (p. ej., `seg_init_audio.hdr`)
   2. **Segmentos de medios** (p. ej., `seg_1.webm`, `seg_2.webm`, ...)

   > **Info**: Cada segmento dura **2 segundos**. Calcula el número de segmentos:
   >
   > ```text
   > numSegments = durationSec / 2
   > ```

   Escribe los bytes del encabezado de inicialización seguidos de los bytes de cada segmento para producir un archivo de audio WebM/Opus válido (48 kHz, mono).

---

## Ejemplo completo en Python

Este ejemplo implementa el flujo de trabajo completo descrito anteriormente:

```python
import time

import requests

BASE_URL = "https://api2.rhombussystems.com"
API_KEY = "YOUR_API_KEY"

HEADERS = {
    "Content-Type": "application/json",
    "x-auth-scheme": "api-token",
    "x-auth-apikey": API_KEY,
}


class FederatedToken:
    """Un token de sesión federado para acceso por WAN (sin domain: uso desde servidor), que se vuelve a generar antes de expirar."""

    def __init__(self, duration_sec: int = 3600):
        self.duration_sec = duration_sec  # 86400 (24 horas) como máximo
        self.token = None
        self.expires_at_ms = 0

    def query(self) -> str:
        # Genera un token nuevo cuando falta menos de un minuto para expiresAtMs
        if time.time() * 1000 > self.expires_at_ms - 60_000:
            url = f"{BASE_URL}/api/org/generateFederatedSessionToken"
            resp = requests.post(url, headers=HEADERS, json={"durationSec": self.duration_sec})
            resp.raise_for_status()
            body = resp.json()
            self.token = body["federatedSessionToken"]
            self.expires_at_ms = body["expiresAtMs"]
        return f"?x-auth-scheme=federated-token&x-auth-ft={self.token}"


def get_audio_gateway_media_uris(gateway_uuid: str) -> dict:
    """Obtiene las plantillas de URI de medios para un audio gateway."""
    url = f"{BASE_URL}/api/audiogateway/getMediaUris"
    resp = requests.post(url, headers=HEADERS, json={"gatewayUuid": gateway_uuid})
    resp.raise_for_status()
    return resp.json()


def build_mpd_uri(template: str, start_time_sec: int, duration_sec: int) -> str:
    """Sustituye los marcadores de posición en la plantilla de URI del MPD."""
    return template.replace("{START_TIME}", str(start_time_sec)).replace(
        "{DURATION}", str(duration_sec)
    )


def download_wan_vod_audio(
    gateway_uuid: str, start_time_sec: int, duration_sec: int, out_path: str
):
    """Descarga audio grabado de un Rhombus A100 Audio Gateway."""
    # Paso 1: Obtener los URIs de medios
    media = get_audio_gateway_media_uris(gateway_uuid)
    mpd_template = media["wanVodMpdUriTemplate"]

    # Paso 2: Generar el token federado (se renueva antes de expirar)
    ft = FederatedToken(duration_sec=3600)

    # Paso 3: Construir la URL del MPD
    mpd_uri = build_mpd_uri(mpd_template, start_time_sec, duration_sec)

    # Paso 4: Obtener el MPD (autenticado mediante la cadena de consulta)
    mpd_resp = requests.get(mpd_uri + ft.query())
    mpd_resp.raise_for_status()

    # Paso 5: Descargar el segmento de inicialización y los segmentos de medios.
    # Este script construye las URL de los segmentos en lugar de leerlas del
    # MPD, así que añade el token a cada una. (Enviar los encabezados de la API
    # key en cada solicitud también funciona.)
    init_uri = mpd_uri.replace("file.mpd", "seg_init_audio.hdr")
    num_segments = duration_sec // 2

    with open(out_path, "wb") as f:
        # Descargar el segmento de inicialización
        init_resp = requests.get(init_uri + ft.query())
        init_resp.raise_for_status()
        f.write(init_resp.content)

        # Descargar los segmentos de medios
        for i in range(1, int(num_segments) + 1):
            seg_uri = mpd_uri.replace("file.mpd", f"seg_{i}.webm")
            seg_resp = requests.get(seg_uri + ft.query())
            seg_resp.raise_for_status()
            f.write(seg_resp.content)


if __name__ == "__main__":
    gateway_uuid = "AAAAAAAAAAAAAAAAAAAAAA.v0"
    start_time_sec = 1700000000  # Ejemplo: 14 de noviembre de 2023
    duration_sec = 60  # 1 minuto (máx.: 86400 segundos / 24 horas)

    download_wan_vod_audio(
        gateway_uuid=gateway_uuid,
        start_time_sec=start_time_sec,
        duration_sec=duration_sec,
        out_path="rhombus_audio.webm",
    )
    print("Wrote rhombus_audio.webm")
```

## Convertir audio con ffmpeg

El audio descargado está en formato **Opus/WebM** (48 kHz, mono). Puedes convertirlo a otros formatos usando ffmpeg:

```bash WAV (16-bit PCM)
ffmpeg -i rhombus_audio.webm -acodec pcm_s16le rhombus_audio.wav
```

```bash MP3
ffmpeg -i rhombus_audio.webm rhombus_audio.mp3
```

## Solución de problemas

**Manifiestos vacíos o segmentos faltantes**

**Causa:** La sustitución de la plantilla usa unidades de tiempo incorrectas.

**Solución:** Si tus marcas de tiempo están en milisegundos pero la plantilla espera segundos, conviértelas:

```python
start_time_sec = start_time_ms // 1000
duration_sec = duration_ms // 1000
```

**La reescritura del MPD no coincide con tu plantilla**

**Causa:** El código asume que el nombre del archivo MPD es `file.mpd`.

**Solución:** Si tu plantilla usa un nombre de archivo diferente, ajusta la lógica de reemplazo de cadenas:

```python
# Lógica actual
init_uri = mpd_uri.replace("file.mpd", "seg_init_audio.hdr")

# Ajusta para que coincida con tu nombre de archivo real
init_uri = mpd_uri.replace("your_filename.mpd", "seg_init_audio.hdr")
```

**403 en el MPD o en los segmentos**

**Causa:** El token se generó con un `domain` (403 `DOMAIN_NOT_ALLOWED`), o el rol de la clave que lo generó no puede ver el audio grabado del gateway.

**Solución:** Para uso desde un servidor, genera el token sin `domain`, con una clave cuyo rol pueda ver el gateway, o envía en su lugar los encabezados de tu clave de API. Consulta [Medios y transmisiones](https://developer.rhombus.com/es/authentication/media#solución-de-problemas).

**El token expira antes de que se complete la descarga**

**Causa:** La descarga tarda más de lo que dura el token. Las solicitudes fallan entonces con 401 `CREDENTIAL_EXPIRED`. Un token también deja de funcionar, con un 401, si se revoca o si se elimina la clave de API que lo generó.

**Solución:** Un token dura 24 horas como máximo, así que no dependas de un `durationSec` más largo. Genera un token nuevo antes del `expiresAtMs` de la respuesta de generación y úsalo para los segmentos restantes, como hace `FederatedToken` en el ejemplo completo.

## Referencia de la API

Los siguientes endpoints se usan en esta guía. Visita la pestaña [API Reference](https://developer.rhombus.com/api-reference/audiogateway-webservice/get-media-uris-for-audio-gateway) para ver los esquemas completos de solicitud y respuesta.

- [`POST /api/audiogateway/getMediaUris`](https://developer.rhombus.com/api-reference/audiogateway-webservice/get-media-uris-for-audio-gateway) — Obtener los URIs de medios del Audio Gateway
- [`POST /api/org/generateFederatedSessionToken`](https://developer.rhombus.com/api-reference/org-webservice/generate-federated-session-token) — Generar un token de sesión federado
