Backend AI music generation orchestration framework (FastAPI + Celery) focused on pluggable
music/audio providers. The repository intentionally ships with a working mock provider plus
stub provider adapters you can implement for your own local model runner or a hosted SaaS API.
- FastAPI API to create and query generation jobs.
- Celery worker to execute jobs asynchronously (or synchronously in “eager” mode).
- Provider registry to select a generation backend (
mock,local_musicgen,stable_audio,elevenlabs). - Storage backends for outputs (
localfilesystem ors3/MinIO). - Audio post-processing (optional
.wav→.mp3viaffmpeg).
This mode uses SQLite + synchronous Celery tasks (no Redis/worker needed) and is the fastest way
to verify the end-to-end flow with the built-in mock provider.
python -m pip install -e ".[dev]"
export OMA_DATABASE_URL="sqlite+pysqlite:///./oma.db"
export OMA_CELERY_TASK_ALWAYS_EAGER=true
export OMA_PROVIDER_DEFAULT=mock
export OMA_STORAGE_BACKEND=local
export OMA_LOCAL_STORAGE_PATH=./data
export OMA_USE_FFMPEG=false
oma serveCreate a job:
curl -X POST http://localhost:8000/jobs -H 'content-type: application/json' \
-d '{"prompt":"lofi piano beat"}'The provided docker-compose.yml starts:
api(FastAPI)worker(Celery)postgresredis
docker compose up --buildCustomize configuration:
- Edit
.env.exampledirectly (Compose loads it viaenv_file) - Or copy it to
.envand updatedocker-compose.ymlto use.env
Run migrations (PostgreSQL):
docker compose run --rm api alembic -c alembic.ini upgrade headThe CLI is a thin wrapper that creates jobs and runs the API server.
oma serve
oma generate "lofi piano beat"
oma job list
oma job get <job_id>Endpoints:
GET /health→ health checkGET /providers→ known provider names from the registryPOST /jobs→ create a generation job ({"prompt": "...", "provider": "mock"})GET /jobs/{id}→ poll job status and output URL/metadata
At a high level, job execution is:
- Request: client calls
POST /jobs(oroma generate). - Plan: the planner picks a provider and generation settings from the prompt
(
open_music_agent/agent/planner.py). - Queue: the API enqueues a Celery task (
open_music_agent/jobs/tasks.py). - Generate: the worker loads the provider adapter and calls
provider.generate(...)(open_music_agent/agent/music_agent.py). - Process: generated audio is optionally analyzed/converted (e.g. WAV → MP3)
(
open_music_agent/audio/processor.py). - Store: the result is uploaded via the configured storage backend
(
open_music_agent/storage/__init__.py). - Persist: the job row is updated with
status,output_url,content_type, andmetadata(open_music_agent/db/models.py).
The “agent” here is intentionally small: it routes and orchestrates providers, post-processing, and storage. It does not embed any proprietary model weights or vendor SDK assumptions.
The registry is defined in open_music_agent/providers/registry.py:
mock(works out of the box; used by tests)local_musicgen(stub)stable_audio(stub)elevenlabs(stub)
Only mock is implemented in-repo. The other providers raise ProviderError until you implement
them for your environment and credentials.
- Default provider:
OMA_PROVIDER_DEFAULT(used when the prompt does not trigger a special route) - Per-request provider: pass
providerinPOST /jobs
The planner currently routes prompts containing "vocal"/"voice" to stable_audio and uses the
default provider for everything else (open_music_agent/agent/planner.py).
All providers implement the MusicProvider protocol (open_music_agent/providers/base.py):
name: strgenerate(prompt: str, *, duration_seconds: int) -> GeneratedAudio
GeneratedAudio.path must point to a file on disk; the agent will post-process it and then upload it.
To add a new provider:
- Create
open_music_agent/providers/<your_provider>.pyimplementingMusicProvider - Register it in
open_music_agent/providers/registry.py - Add any needed configuration to
open_music_agent/config.py(env vars are prefixed withOMA_) - Add example env vars to
.env.example
Configure storage with:
OMA_STORAGE_BACKEND=localandOMA_LOCAL_STORAGE_PATH=...OMA_STORAGE_BACKEND=s3plusOMA_S3_BUCKET, and optionally:OMA_S3_ENDPOINT_URL,OMA_S3_ACCESS_KEY_ID,OMA_S3_SECRET_ACCESS_KEY,OMA_S3_PUBLIC_BASE_URL
If OMA_S3_PUBLIC_BASE_URL is set, the stored output URL is an HTTP URL; otherwise it is an
s3://bucket/key URL.
If OMA_USE_FFMPEG=true and ffmpeg is available in PATH (or via OMA_FFMPEG_PATH), .wav
outputs are converted to .mp3. When disabled or unavailable, the original provider output is used.
Install dev tools:
python -m pip install -e ".[dev]"Run checks:
ruff check .
mypy open_music_agent
pytest -q