Cameras
Retrieving Audio from A100 Audio Gateway
Download recorded audio from a Rhombus A100 Audio Gateway using the API — fetch DASH MPD manifests, retrieve segments, and play back audio over WAN VOD.
On this page
In this guide, you will learn how to retrieve recorded audio from a Rhombus A100 Audio Gateway using the Rhombus API. You will:
- Call the API to get media URI templates
- Generate a federated session token for WAN playback
- Download the DASH MPD and audio segments
- Optionally convert the resulting Opus/WebM audio using ffmpeg
Rhombus exposes media access through URI templates rather than returning raw audio bytes directly from a single REST response.
Prerequisites
All API calls in this guide use the following authentication headers:
Content-Type: application/json
x-auth-scheme: api-token
x-auth-apikey: YOUR_API_KEYBase URL: https://api2.rhombussystems.com
You will need:
- An A100 Audio Gateway UUID (Rhombus DeviceFacetUuid / RUUID style string)
- Recorded audio that exists and is available (determined by your device licensing and recording configuration)
- A client capable of:
- Making HTTP requests
- Parsing XML (for the MPD manifest)
- Writing binary segment bytes to disk
Implementation steps
- Get the A100 Audio Gateway Media URIs
Call the
getMediaUrisendpoint to retrieve the URI templates for your audio gateway.Endpoint:
POST /api/audiogateway/getMediaUrisbashcurl --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" }'Relevant response fields:
Field Description wanVodMpdUriTemplateWAN VOD MPD template (use this for recorded audio over WAN) wanLiveOpusUriWAN live Opus stream (WebSocket). It doesn't end in /ws: append/wsbefore you connectwanLiveMpdUriWAN live MPD URI lanVodMpdUrisTemplatesLAN VOD templates LAN URIs (
lanLiveOpusUris,lanLiveMpdUris,lanVodMpdUrisTemplates) are served by the gateway itself, which accepts only federated tokens, by design. See Streaming over LAN for authentication and the two-way audio WebSocket format.The live Opus socket (
wanLiveOpusUriplus/ws) carries listening and two-way talk. From a server, authenticate it with your API key headers or an OAuth access token (Authorization: Bearer <token>); in a browser, use a federated token as query parameters. An OAuth token needs thereadscope to listen and thephysicalscope to send talk audio: audio sent withoutphysicalcloses the socket with code1008. If the credential is deleted or revoked, or its role changes, the open socket closes with code1008within 60 seconds. - Generate a Federated Session Token
From a server, you can fetch the WAN MPD and its segments with your API key headers (
x-auth-scheme: api-tokenandx-auth-apikey) on every request, or withAuthorization: Bearer <token>for an OAuth access token with thereadscope. This guide uses a short-lived federated session token instead, appended as query parameters, which also works in players that can't send headers. (The same two values also work as headers.)Endpoint:
POST /api/org/generateFederatedSessionTokenbashcurl --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 }'Response: Returns
federatedSessionTokenandexpiresAtMs, the time the token expires in Unix milliseconds.WarningDon't set
domainon a token you use from a server. A token minted withdomainonly works on requests whoseOrigin(or, when there's noOrigin,Referer) is exactly that origin, such ashttps://app.example.com. Server-side requests send neither, so every MPD and segment request fails with 403DOMAIN_NOT_ALLOWED.domainmust be an absolute origin; a value such as.rhombussystems.comis refused when you mint (400). See The domain field.TipdurationSecdefaults to 3600 (one hour) and can't exceed 86400 (24 hours). For a download that takes longer than the token lasts, mint a new token before theexpiresAtMsin the response, as the complete example below does. - Build the WAN VOD MPD URL
Take the
wanVodMpdUriTemplatefrom Step 1 and perform string substitution:- Replace
{START_TIME}with your requested start time (in seconds) - Replace
{DURATION}with your requested duration (in seconds)
WarningTimestamp units matter.
Rhombus audio endpoints use seconds since epoch (
startTimeSec,durationSec). If your timestamps are stored in milliseconds, convert them:startTimeSec = startTimeMs / 1000 durationSec = durationMs / 1000 - Replace
- Fetch the MPD with the Federated Token
Append the authentication query parameters to your MPD URL:
<mpdUri>?x-auth-scheme=federated-token&x-auth-ft=<TOKEN>This MPD is a DASH manifest that describes how to fetch the init segment and subsequent audio segments. On the WAN host, the segment URLs in the MPD carry the same query parameters, so a DASH player given this URL needs nothing else.
- Download and Stitch Segments
If you build the segment URLs yourself, as this guide does, download them in order, appending the same
?x-auth-scheme=federated-token&x-auth-ft=<TOKEN>query parameters you used for the MPD — the segments are served from the same WAN host and use the same authentication:- Init segment (e.g.,
seg_init_audio.hdr) - Media segments (e.g.,
seg_1.webm,seg_2.webm, ...)
InfoSegments are 2 seconds each. Calculate the number of segments:
numSegments = durationSec / 2Write the init header bytes followed by each segment's bytes to produce a valid WebM/Opus audio file (48 kHz, mono).
- Init segment (e.g.,
Complete Python example
This example implements the full workflow described above:
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:
"""A federated session token for WAN access (no domain: server-side use), minted again before it expires."""
def __init__(self, duration_sec: int = 3600):
self.duration_sec = duration_sec # at most 86400 (24 hours)
self.token = None
self.expires_at_ms = 0
def query(self) -> str:
# Mint a new token when this one is within a minute of 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:
"""Get media URI templates for an 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:
"""Substitute placeholders in the MPD URI template."""
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
):
"""Download recorded audio from a Rhombus A100 Audio Gateway."""
# Step 1: Get media URIs
media = get_audio_gateway_media_uris(gateway_uuid)
mpd_template = media["wanVodMpdUriTemplate"]
# Step 2: Generate federated token (renewed before it expires)
ft = FederatedToken(duration_sec=3600)
# Step 3: Build MPD URL
mpd_uri = build_mpd_uri(mpd_template, start_time_sec, duration_sec)
# Step 4: Fetch MPD (authenticated via query string)
mpd_resp = requests.get(mpd_uri + ft.query())
mpd_resp.raise_for_status()
# Step 5: Download init segment and media segments.
# This script builds the segment URLs itself instead of reading them from
# the MPD, so it appends the token to each one. (Sending the API key
# headers on every request also works.)
init_uri = mpd_uri.replace("file.mpd", "seg_init_audio.hdr")
num_segments = duration_sec // 2
with open(out_path, "wb") as f:
# Download init segment
init_resp = requests.get(init_uri + ft.query())
init_resp.raise_for_status()
f.write(init_resp.content)
# Download media segments
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 # Example: November 14, 2023
duration_sec = 60 # 1 minute (max: 86400 seconds / 24 hours)
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")Converting audio with ffmpeg
The downloaded audio is in Opus/WebM format (48 kHz, mono). You can convert it to other formats using ffmpeg:
ffmpeg -i rhombus_audio.webm -acodec pcm_s16le rhombus_audio.wavffmpeg -i rhombus_audio.webm rhombus_audio.mp3Troubleshooting
Empty manifests or missing segments
Cause: Template substitution uses wrong time units.
Solution: If your timestamps are in milliseconds but the template expects seconds, convert them:
start_time_sec = start_time_ms // 1000
duration_sec = duration_ms // 1000MPD rewrite doesn't match your template
Cause: The code assumes the MPD filename is file.mpd.
Solution: If your template uses a different filename, adjust the string replacement logic:
# Current logic
init_uri = mpd_uri.replace("file.mpd", "seg_init_audio.hdr")
# Adjust to match your actual filename
init_uri = mpd_uri.replace("your_filename.mpd", "seg_init_audio.hdr")403 on the MPD or segments
Cause: The token was minted with a domain (403 DOMAIN_NOT_ALLOWED), or the role of the key that minted it can't view the gateway's recorded audio.
Solution: Mint the token without domain for server-side use, from a key whose role can view the gateway, or send your API key headers instead. See Media and streams.
Token expires before download completes
Cause: The download takes longer than the token lasts. Requests then fail with 401 CREDENTIAL_EXPIRED. A token also stops working, with a 401, if it's revoked or the API key that minted it is deleted.
Solution: A token lasts at most 24 hours, so don't rely on a longer durationSec. Mint a new token before the expiresAtMs in the mint response and use it for the remaining segments, as FederatedToken in the complete example does.
API reference
The following endpoints are used in this guide. Visit the API Reference tab for full request and response schemas.
POST /api/audiogateway/getMediaUris— Get Media URIs for Audio GatewayPOST /api/org/generateFederatedSessionToken— Generate Federated Session Token