On-the-fly audio processing server. Think Thumbor / Imagor, but for audio.
Process audio files through URL parameters — apply effects, convert formats, slice, reverse, and stream the result back in real time.
# Default build with filesystem storage
cargo run
# Process audio via URL
curl "http://localhost:8080/unsafe/sample.mp3?reverse=true&fade_in=1&speed=0.8"
# Get audio metadata
curl "http://localhost:8080/meta/unsafe/sample.mp3"See MCP README
GET /unsafe/AUDIO_URL?effect1=value&effect2=value
The server fetches the audio, builds an FFmpeg filter chain from the query parameters, processes it, caches the result, and streams it back.
/HASH|unsafe/AUDIO?param1=value1¶m2=value2&...
HASH— URL signature hash, orunsafefor developmentAUDIO— audio URI (local file or remote URL)
Remote URLs should be percent-encoded so their own query strings survive (e.g. /unsafe/https%3A%2F%2Fexample.com%2Fsong.mp3%3Ftoken%3Dabc). Besides direct file URLs, these page links are resolved to the underlying audio:
- Audius track pages (
audius.co/<artist>/<track>) - Internet Archive items (
archive.org/details/<item>picks an audio file;archive.org/details/<item>/<file>fetches that file) - Dropbox share links (
dropbox.com/s/...,dropbox.com/scl/fi/...?rlkey=...) - Google Drive file links (
drive.google.com/file/d/<id>/view,/open?id=,/uc?id=) - OneDrive share links (
1drv.ms/...,onedrive.live.com/...,<tenant>.sharepoint.com/:u:/...) - GitHub file pages (
github.com/<owner>/<repo>/blob/<ref>/<path>)
Downloaded sources are cached for processor.remote_cache_ttl_secs (default 3600; 0 disables). For safety, remote fetches to loopback, private and link-local addresses are refused, including via redirects; set application.allow_private_remote_urls: true only for local development.
format— Output format (mp3, wav, etc.)codec— Audio codecsample_rate— Sample rate in Hzchannels— Number of audio channelsbit_rate— Bit rate in kbpsbit_depth— Bit depthquality— Encoding quality (0.0–1.0)compression_level— Compression level
start_time— Start time in secondsduration— Duration in secondsspeed— Playback speed multiplierreverse— Reverse audio (true/false)
volume— Volume adjustment multipliernormalize— Normalize audio levels (true/false)normalize_level— Target normalization level in dB
lowpass/highpass/bandpass— Filter cutoff frequenciesbass/treble— Boost/cut levelsecho/chorus/flanger/phaser/tremolo— Effect parameterscompressor— Compressor parametersnoise_reduction— Noise reduction parameters
fade_in/fade_out— Duration in secondscross_fade— Cross-fade duration in seconds
custom_filters— Custom FFmpeg filter parameterscustom_options— Custom FFmpeg optionstags— Metadata tags (astag_NAME=VALUE)
curl "http://localhost:8080/unsafe/sample1.mp3?tag_title=Preview"When tags are the only active change, the server copies compressed audio packets instead of decoding and re-encoding. This preserves the source codec and container, retains existing tags unless overridden, and avoids another lossy encoding pass. Explicit encoding settings, format conversions, trims, or filters still use the processing pipeline.
On /stream, Ogg remuxes are emitted incrementally. Other tags-only formats are finalized in memory before delivery so seek-back headers (including MP3 duration/gapless information) remain correct. Like the processing pipeline, remuxing keeps the selected audio stream, not other streams such as cover art.
curl "http://localhost:8080/params/unsafe/sample.mp3?reverse=true&fade_in=1"curl "http://localhost:8080/meta/unsafe/sample.mp3"- Local File System (
filesystemfeature — default) - AWS S3 / MinIO (
s3feature) - Google Cloud Storage (
gcsfeature)
cargo build --features filesystem # default
cargo build --features gcs
cargo build --features s3
cargo build --features "filesystem,gcs"Uses YAML config files + environment variable overrides.
config/base.yml— Base configurationconfig/local.yml— Developmentconfig/production.yml— Production
Environment variables: APP_SECTION__KEY=value (e.g., APP_APPLICATION__PORT=8080)
See architecture docs for details.
just dev # Run with auto-reload
just test # Run tests
just bench # Run benchmarks
just lint # Clippy
just fmt # Format
just check # Full check: fmt, lint, build, test