Audio API

All routes are below /api/audio/. Public clients use https://svnm.loca.zone; the intended proxy forwards to the loopback service at 127.0.0.1:52525. This is configuration intent, not a claim of current availability. (audio-service/__main__.py:24-30, audio-service/__main__.py:521-550)

Routes

Method and routeContract
GET /api/audio/healthProcess liveness; returns {"status":"ok"}
GET /api/audio/readyProvider readiness; 200 when Edge is available, otherwise degraded payload with 503
GET /api/audio/capabilitiesVersion 1 independent Edge/Freesound availability and reasons
GET /api/audio/voices?locale=<locale>Edge voice list
POST /api/audio/speechEdge synthesis; returns audio/mpeg
GET /api/audio/freesound/search?q=<query>&results=<count>Normalized Freesound metadata results
GET /api/audio/freesound/preview/<sound-id>Proxied audio plus X-Preview-Identity

(audio-service/__main__.py:338-411, audio-service/__main__.py:439-513, audio-service/__main__.py:542-548)

Headers and origin

If Origin is present, it must exactly equal the configured public origin. voices, speech, and both Freesound routes require X-SVG-Animator-Request: 1; health, ready, and capabilities do not. Speech additionally requires exact Content-Type: application/json. Successful middleware responses add X-Content-Type-Options: nosniff and Cache-Control: no-store. (audio-service/__main__.py:309-329, audio-service/__main__.py:439-447)

Request limits

Speech text is 1–180 characters; voiceId is required and at most 120 characters; locale is at most 35. Rate is 0.5–2, pitch 0–2, and volume 0–1. Freesound query length is 1–120 and results count is 1–20. Preview byte ranges are rejected. Request bodies are capped at 8192 bytes, and synthesized/preview responses use the configured maximum, default 16 MiB. (audio-service/__main__.py:26-30, audio-service/__main__.py:414-465, audio-service/__main__.py:468-513, audio-service/__main__.py:530-537)

Health semantics

Health proves only the aiohttp process answers. Ready and capabilities probe Edge and Freesound independently with per-provider deadlines, cached state, coalesced in-flight work, and rate limits. Missing Freesound credentials is an unavailable capability, not a leaked secret or fabricated success. (audio-service/__main__.py:338-396)