Skip to content

Repository files navigation

open-music-agent

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.

What You Get

  • 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 (local filesystem or s3/MinIO).
  • Audio post-processing (optional .wav.mp3 via ffmpeg).

Quickstart (Local, No Docker)

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 serve

Create a job:

curl -X POST http://localhost:8000/jobs -H 'content-type: application/json' \
  -d '{"prompt":"lofi piano beat"}'

Docker Compose (Postgres + Redis + Worker)

The provided docker-compose.yml starts:

  • api (FastAPI)
  • worker (Celery)
  • postgres
  • redis
docker compose up --build

Customize configuration:

  • Edit .env.example directly (Compose loads it via env_file)
  • Or copy it to .env and update docker-compose.yml to use .env

Run migrations (PostgreSQL):

docker compose run --rm api alembic -c alembic.ini upgrade head

CLI

The 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>

API

Endpoints:

  • GET /health → health check
  • GET /providers → known provider names from the registry
  • POST /jobs → create a generation job ({"prompt": "...", "provider": "mock"})
  • GET /jobs/{id} → poll job status and output URL/metadata

How The Agent Works (Design)

At a high level, job execution is:

  1. Request: client calls POST /jobs (or oma generate).
  2. Plan: the planner picks a provider and generation settings from the prompt (open_music_agent/agent/planner.py).
  3. Queue: the API enqueues a Celery task (open_music_agent/jobs/tasks.py).
  4. Generate: the worker loads the provider adapter and calls provider.generate(...) (open_music_agent/agent/music_agent.py).
  5. Process: generated audio is optionally analyzed/converted (e.g. WAV → MP3) (open_music_agent/audio/processor.py).
  6. Store: the result is uploaded via the configured storage backend (open_music_agent/storage/__init__.py).
  7. Persist: the job row is updated with status, output_url, content_type, and metadata (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.

Providers (How To Configure / Extend)

Built-in Providers

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.

Selecting A Provider

  • Default provider: OMA_PROVIDER_DEFAULT (used when the prompt does not trigger a special route)
  • Per-request provider: pass provider in POST /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).

Implementing A Provider Adapter

All providers implement the MusicProvider protocol (open_music_agent/providers/base.py):

  • name: str
  • generate(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:

  1. Create open_music_agent/providers/<your_provider>.py implementing MusicProvider
  2. Register it in open_music_agent/providers/registry.py
  3. Add any needed configuration to open_music_agent/config.py (env vars are prefixed with OMA_)
  4. Add example env vars to .env.example

Storage Backends

Configure storage with:

  • OMA_STORAGE_BACKEND=local and OMA_LOCAL_STORAGE_PATH=...
  • OMA_STORAGE_BACKEND=s3 plus OMA_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.

Audio Processing (FFmpeg)

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.

Development

Install dev tools:

python -m pip install -e ".[dev]"

Run checks:

ruff check .
mypy open_music_agent
pytest -q

About

Backend AI music generation orchestration framework focused on pluggable music/audio providers

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages