Hi all!
I built audioproxy because every project I touched that used user submitted audio ended up needing variants (previews, downloads, waveform data, …), and rather than prerendering them, storing them in a database entry and
running the job queue that requires, I wanted a solution that is totally agnostic of where the audio is stored (locally or in a bucket), where it is delivered, and in what format.
In short: the URL is the entire API.
GET /{signature}/f:opus/br:96/t:0:30/fade:1:1/plain/s3://masters/track.wav
renders a signed 30-second Opus preview on demand - critically, it streams the first bytes while ffmpeg is still encoding - and because a URL fully describes its variant, every later request is served range-capable from the variant store, and CDNs can cache it as immutable.
The Elixir side is deliberately boring OTP:
• ffmpeg as a supervised subprocess (Port, argv lists only, no shell)
• presigned-URL inputs, so source bytes never cross the BEAM
• render coalescing via Registry: N concurrent requests for one variant share a single encode
• counting semaphore for backpressure (429 with Retry-After)
• Plug + Bandit
One Debian container, no database.
Waveform data ( f:peaks ) is just another output format, audiowaveform-compatible, cached exactly like audio.
The explorer on the landing page runs against a real deployment: the waveform you see is the proxy’s own peaks output, and the cache badge shows real MISS/HIT timings (first render vs. ~30 ms from the store).
Feedback very welcome, especially on the OTP shape and anything that looks un-idiomatic!
Docs: https://docs.audioproxy.dev
Live demo (runs against a real deployment): https://audioproxy.dev
Hex: audio_proxy | Hex






















