A production-ready backend for sheet music conversion using Audiveris and music21 with a well-documented API for frontend integration.
sheet-music-backend/
├── app/
│ ├── main.py (FastAPI entrypoint)
│ ├── processor.py (core logic)
│ └── schemas.py (Pydantic models)
├── scripts/
│ └── setup_audiveris.sh
├── docker/
│ └── Dockerfile
├── requirements.txt
└── README.md (API documentation)
-
POST /convert
- Description: Convert uploaded sheet music
- Request:
file: Sheet music image (PNG/JPG)
- Response:
{ "process_id": "uuid-string", "formats": { "midi": "/results/uuid-string/output.mid", "annotated_score": "/results/uuid-string/annotated.png", "musicxml": "/results/uuid-string/somefile.mxl" } }
-
GET /results/{process_id}/{filename}
- Description: Download processed files
- Parameters:
process_id: From conversion responsefilename: One of:output.mid,annotated.png, or original XML filename
- Response: File content with proper Content-Type
sequenceDiagram
Frontend->>Backend: POST /convert (image)
Backend->>Audiveris: Process image
Audiveris->>Backend: MusicXML
Backend->>music21: Parse and annotate
Backend->>music21: Generate MIDI
Backend->>music21: Generate annotated PNG
Backend->>Frontend: JSON with result URLs
Frontend->>Backend: GET result files
- Audiveris: Java-based OMR engine converts sheet images to MusicXML
- music21: Python library for music analysis and generation
- Conversion Steps:
- Image → MusicXML (via Audiveris)
- MusicXML → Annotated music21 Score
- Score → MIDI (playable audio)
- Score → Annotated PNG (visual sheet music)
midi: Playable audio file (standard MIDI format)annotated_score: Sheet music image with note names below each notemusicxml: Structured representation of the musical score
// Example frontend code (pseudo-code)
async function convertSheetMusic(file) {
// Step 1: Upload image
const formData = new FormData();
formData.append('file', file);
const conversionRes = await fetch('/convert', {
method: 'POST',
body: formData
});
const { process_id, formats } = await conversionRes.json();
// Step 2: Get results
const midiUrl = formats.midi;
const annotatedImageUrl = formats.annotated_score;
return {
midi: await fetch(midiUrl).then(r => r.blob()),
annotatedImage: await fetch(annotatedImageUrl).then(r => r.blob())
};
}- MIDI: Play using Web Audio API or libraries like Tone.js
- Annotated Image: Display directly in
tag
- MusicXML: Use for advanced music analysis if needed
- 400-series errors: Invalid requests
- 500-series errors: Processing failures
- Standard HTTP status codes used throughout
docker build -f docker/Dockerfile -t sheet-music-backend .docker run -p 8000:8000 sheet-music-backendcurl -X POST "http://localhost:8000/convert" \
-H "Content-Type: multipart/form-data" \
-F "file=@path/to/sheet-music.png"- Simple REST API: Only two endpoints to implement
- Stateless Design: Process ID based result retrieval
- Standard Formats: MIDI and PNG for easy integration
- Well-Documented Errors: Clear error responses
- CORS Enabled: Ready for web frontend integration
- Production-Ready: Containerized with proper timeouts
-
Install dependencies:
pip install -r requirements.txt
-
Run the application:
uvicorn app.main:app --reload
Once running, visit http://localhost:8000/docs for interactive API documentation.
This project is part of the ENSEMBLE project.