Library / SDK
marcomusy/pianoplayer avatar
marcomusy/pianoplayer

PianoPlayer searches a score for the fingering that costs the least effort

Automatic fingering generator for piano scores

900 stars99 forksPythonMIT

At a glance

What is it?
PianoPlayer is a Python tool that reads MusicXML, MuseScore, MIDI and PIG files and writes an annotated score with a computed fingering for one or both hands. It suits a pianist, teacher or student who wants a starting fingering to argue with, and it is not a substitute for a human fingering tradition.
Who is it for?
PianoPlayer suits a pianist, teacher or student who wants a quick, mechanically derived fingering for a score they already own, especially for the legato and crossing decisions that are tedious to work out by hand.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 124 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A cost function, not a fingering table

PianoPlayer is described as an automatic fingering generator for MusicXML and MIDI scores, and the README is careful about what it produces. It searches for a low-effort fingering sequence for one or both hands. That phrasing matters, because a low-effort sequence is the output of a search over a cost function, not a lookup in a table of canonical fingerings.

The difference is visible in the options. The command line exposes a depth setting for the combinatorial search, with a documented range of 5 to 9, and the default is auto. There is also a colorize-by-cost option, which colors annotated notes and fingerings from green to red based on the computed cost, and a separate colorize-hands option that colors by which hand plays the note.

So the tool does two things that a printed fingering edition cannot. It tells you which notes are the expensive ones under its own model, and it lets you set how far the search goes. A higher depth means a larger search space and a fingering that is more likely to be locally optimal across a wider stretch of the piece.

What the tool does not claim is that the result is the fingering a particular teacher would give. There is no mention of a fingering tradition, a school of playing, or a comparison with published editions. The output is a defensible starting point produced by a search, and the README's own framing, a low-effort sequence, is the honest description of what that means.

Input formats, output formats and the anchoring behaviour

The set of accepted inputs is broad. The CLI lists valid file formats as MusicXML, compressed MusicXML, MuseScore, MIDI and PIG, with the extensions .xml, .mxl, .mscz, .mscx, .mid, .midi and .txt. PIG is a text format published with a piano fingering dataset, and the README links to it, so a corpus of already-fingered data can be read as input rather than only produced as output.

The output depends on the input family. MusicXML and MuseScore inputs default to output.xml, an annotated score, while MIDI and PIG inputs default to annotated tabular output in output.txt. That split is a sensible one, since a MIDI file carries no notation to write fingering into.

The behaviour that will matter most to a practising musician is the handling of pre-fingered notes. The README states that if a note already has a fingering mark, PianoPlayer keeps it and uses it as an anchor for the following optimization, and that in the output score these anchored fingers are rendered as circled numbers. This is the feature that turns the tool from a generator into an editor. A teacher with a half-marked-up score can keep the decisions they have already made and let the search fill in the rest, and the visual distinction between circled and plain numbers keeps the human contribution legible in the annotated file.

For the visualisation side, the README says to install the latest MuseScore or any other MusicXML renderer to see the annotated score, and the project points at a vedo repository under the same author for the 3D view.

Installing it, including the parts you probably do not need

The package is on PyPI and the base install is a single command:

bash
pip install pianoplayer

The optional extras are where the real decisions are, and the README names them explicitly:

bash
pip install "pianoplayer[visual]"  # 3D rendering with vedo
pip install "pianoplayer[midi]"    # MIDI input support
pip install "pianoplayer[sound]"   # enable playback
pip install "pianoplayer[all]"     # all optional extras

The base dependency is deliberately small, just rich at 13.0.0 or later, which is the terminal output library. Everything else sits behind a flag: vedo for 3D rendering, pretty_midi for MIDI input, pygame for playback, pyinstaller for the standalone build, and a web group with fastapi, uvicorn and python-multipart. The repository carries a webapi package and the setuptools configuration includes it in the distribution, so a browser front end over the same engine is part of the project rather than a separate idea.

The README also gives a beginner-friendly path. On Windows it recommends Anaconda and its Anaconda Prompt for people new to Python, and for a plain Python install it asks for 3.10 or newer with the Add Python to PATH option enabled during installation, then pip install pianoplayer followed by pianoplayer --help to confirm the entry point works. The project metadata requires Python 3.10 or newer and declares the console script pianoplayer.

For a machine without a Python environment, the build extra produces a standalone executable through a script in the repository, with the output landing at dist/pianoplayer on Linux and macOS and dist/pianoplayer.exe on Windows.

Routing hands to staves is the part to check first

Before any fingering is computed, the tool has to decide which staff belongs to which hand, and the CLI options and the routing notes together explain how that works.

The defaults are automatic. The --auto-routing option resolves part and staff routing automatically and is the default, and --manual-routing uses the explicit -rpart, -lpart, --rstaff and --lstaff values instead. The run summary shows what was chosen.

The rules for the automatic path are stated in the README. In 2-part piano scores, the hands are selected by the part number, with -rpart defaulting to 0 and -lpart to 1. In 1-part, 2-staff piano scores, the hands are selected by staff, with the right hand on staff 1 and the left hand on staff 2. The --rstaff and --lstaff options take a staff number for single-part MusicXML, and the default for both is auto.

This is the single most likely source of a wrong result. A score that is laid out differently from the two cases above, or one where the staves are not the hands, will be routed incorrectly and will produce a fingering that looks plausible and is not. The escape hatch exists, and using --manual-routing with explicit part and staff numbers is the right response when the automatic summary shows the wrong assignment.

The other layout-sensitive option is --chord-note-stagger-s, which defaults to 0.05 and offsets the notes of a chord slightly so that a chord does not collapse into a single visual point once finger numbers are added.

Running it and reading the annotated result

The example invocation in the README is worth copying exactly, because it shows the flags that change the shape of the output:

bash
pianoplayer scores/bach_invention4.xml -n 10 -r -v -z -m

That annotates the first 10 measures for the right hand, opens the 3D playback, and then opens MuseScore. The measure count comes from -n with a default of 1000, and -s sets the starting measure, defaulting to 1, so a long score can be fingered in sections rather than in one pass.

The hand selection flags are -l for left only and -r for right only. A single hand is often the useful case, because the cost function is easier to check when only one hand has to be tracked.

Two flags control the environment rather than the fingering. -z disables sound and -v plays the 3D scene after processing, and the sound-off flag is worth remembering when running a batch overnight. -m opens the result in MuseScore, and the README notes that if the fingering numbers are not visible enough you can use the -b option, which shows the fingering numbers below the beam line instead of above the staff.

The GUI exists as well. Running pianoplayer with no filename opens a Tkinter window, and the flow is Import Score, then GENERATE, then Musescore to view the annotated result, with Quit closing it. The Musescore button is marked as Linux and macOS only, which is a small inconsistency with the CLI path, since the command line -m flag is not qualified that way in the option list.

There is also an Advanced panel in the GUI where auto hand routing can be disabled and the colorize options set, mirroring the command line.

A version 3 tool with a fast release line and MIT terms

The licence is MIT, with a LICENSE file at the repository root and the MIT badge in the README. For a tool whose output is a suggestion rather than a recording or a score, that is a low-friction choice, and the constraint that matters is the one on the input: a score you do not have the right to use is a problem regardless of the licence of the tool that reads it.

The release history is worth noting because it is recent and infrequent at the same time. The recent releases are 3.0.1 on 2026-03-01, 2.2.0 on 2021-01-24 and 2.1.0 on 2019-08-23, so the two older ones are separated by years and the third version is a fresh break. The version in the project metadata reads 3.0.2, which is the development version ahead of the 3.0.1 tag.

That 3.0.0 change is visible in the code rather than the notes. The optional dependencies carry lower bounds that place them in a recent generation, vedo at 2026.6.1 for the 3D rendering, pygame at 2.6.0 for playback, fastapi at 0.115.0 and uvicorn at 0.30.0 for the web group, and pyinstaller at 6.0.0 for the standalone build. The vedo fork the project points to is its own, not the upstream package, so the 3D view has local changes.

The last push to the repository was on 2026-06-21. The repository is not archived, but the gap between the 3.0.1 release in March and the last push in June means the published package and the branch are not the same thing, so anyone wanting a specific behaviour should check the tags rather than assume the branch matches PyPI.

The project also carries a Zenodo DOI badge and a CI badge, and the tooling around it is tidy for a research tool: pytest with quiet addopts and a tests path, ruff with a 100 character line length targeting py310, and a scores directory holding example inputs such as the Bach invention used in the example command.

Editorial conclusion

PianoPlayer suits a pianist, teacher or student who wants a quick, mechanically derived fingering for a score they already own, especially for the legato and crossing decisions that are tedious to work out by hand. It is the wrong tool for a performer who needs a fingering that matches a specific edition or a specific school of fingering, because the cost function is the author's own, and it is the wrong tool for a project that needs batch fingering over a whole repertoire without human review. Before you adopt it, read the output of one piece you already know how to play, check the routing summary to confirm the hands were assigned to the right staves, and read the MIT licence file in the repository root, which covers the code but says nothing about the scores you feed it.

Frequently asked questions

What file formats can PianoPlayer read?

MusicXML, compressed MusicXML, MuseScore, MIDI and PIG, with the extensions .xml, .mxl, .mscz, .mscx, .mid, .midi and .txt. MusicXML and MuseScore inputs produce an annotated score in output.xml by default, while MIDI and PIG inputs produce annotated tabular output in output.txt.

Does PianoPlayer overwrite fingering I have already written?

No. The README states that a note which already has a fingering mark is kept and used as an anchor for the following optimization, and in the output these anchored fingers are rendered as circled numbers so the human decisions stay visible.

How do I install PianoPlayer with 3D playback?

The base package installs with pip install pianoplayer, and the 3D rendering is an optional extra installed as pip install "pianoplayer[visual]", which pulls in vedo. Playback, MIDI input and a standalone executable have their own extras, and pianoplayer[all] installs everything.

How does PianoPlayer decide which staff is which hand?

Routing is automatic by default. In 2-part scores the hands are chosen by part number, and in 1-part 2-staff scores by staff, with the right hand on staff 1 and the left on staff 2. The --manual-routing option with -rpart, -lpart, --rstaff and --lstaff overrides that explicitly, and the run summary shows what was chosen.

Official sources

  1. Issues
  2. License: MIT
  3. marcomusy/pianoplayer on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/marcomusy-pianoplayer.svg)](https://hysenlabs.com/projects/marcomusy-pianoplayer)

Was this useful?