This article was co-authored with generative AI. Facts have been checked against public documentation where feasible, but errors may remain. Please verify primary sources before relying on this for important decisions.
Conclusion (Stated Up Front)
MusicXML-to-MEI conversion can be done mechanically. The easiest approach is to use Verovio: read MusicXML with loadData() and write out MEI with getMEI(). You can invoke the same processing from the CLI, Python, or Node.
There is one caveat, though. This conversion is not a "byte-for-byte equivalent conversion" but a process that re-encodes the score's semantic content as MEI. Notes, measures, lyrics, and bibliographic metadata are well preserved, but xml:ids are reassigned and layout information is reinterpreted. It is important to use it understanding that it is not a reversible conversion (a round-trip does not restore the original).
In this article, using real data published under CC0 (Schubert's "Heidenröslein") as the subject, I actually run the conversion and confirm what is preserved and how.
What Actually Differs Between MusicXML and MEI
Both are formats that "represent a score in XML," but their origins and aims differ.
- MusicXML — an interchange format between notation software. MuseScore / Finale / Sibelius / Dorico all support import and export (Sibelius historically used the Dolet plugin in some versions), making it the de facto industry standard. It is strong on "how to print this note."
- MEI (Music Encoding Initiative) — an encoding format for scholarly music materials. Developed by a community of librarians, musicologists, and technologists. It is strong on humanities-oriented description, such as parallel presentation of variant readings (
<app>/<rdg>), correspondence to the source material, and critical editing, and shares its design philosophy with TEI (text encoding).
In other words, "moving a score created in notation software (MusicXML) to MEI in order to place it on a research data platform" is a typical motivation for conversion. When you want to handle the score and text (lyrics, editorial notes) as a unit, moving toward MEI starts to make sense.
That is, the flow is "convert a score created in notation software (MusicXML) to MEI with Verovio, and use it for both rendering and research description."
The Easiest Approach: Verovio
Verovio is an MEI rendering library developed by RISM Digital Center, but it can also be used as a converter from various formats to MEI. It accepts MusicXML (including compressed .mxl), Humdrum, ABC, PAE, EsAC, and others as input, and can output MEI via its internal model.
There are multiple entry points.
- CLI:
verovio -t mei input.musicxml -o output.mei - Python:
pip install verovio(some environments need a prebuilt wheel) - Node:
npm install verovio(a WASM build, so no native compilation needed)
This time I used the Node (WASM) version, which installs regardless of environment.
Actually Converting
The subject is Schubert's "Heidenröslein" D.257 from the OpenScore Lieder Corpus (CC0). Being a song, it contains score + lyrics, making it well suited for seeing how text is preserved through conversion.
1. Obtain the Material
The OpenScore GitHub mirror places the original MuseScore file (.mscz) alongside the compressed MusicXML (.mxl) generated from it. This time I use the .mxl. Since .mxl is a ZIP inside, first extract the actual XML.
curl -sL "https://raw.githubusercontent.com/OpenScore/Lieder/main/scores/Schubert,_Franz/Op.3/3_Heidenr%C3%B6slein,_D.257/lc30321236.mxl" -o heidenroslein.mxl
# .mxl is a ZIP. META-INF/container.xml points to the actual file (score.xml)
unzip -o heidenroslein.mxl
The contents of the .mxl look like this.
META-INF/container.xml ← describes the location of the actual file (full-path="score.xml")
score.xml ← the MusicXML itself (score-partwise)
2. Convert to MEI with Verovio
Here is a minimal script that writes it out with Node (WASM). It is also possible to read the .mxl directly without extracting, but here I pass the already-extracted score.xml.
// convert.mjs
import fs from 'node:fs'
import createVerovioModule from 'verovio/wasm'
import { VerovioToolkit } from 'verovio/esm'
const xml = fs.readFileSync('score.xml', 'utf8')
const mod = await createVerovioModule()
const tk = new VerovioToolkit(mod)
console.log('verovio version:', tk.getVersion())
tk.loadData(xml) // read MusicXML with auto-detection
const mei = tk.getMEI() // write out the MEI string
fs.writeFileSync('heidenroslein.mei', mei)
node convert.mjs
Execution result (measured on hand):
verovio version: 6.2.0-43f8060
loadData ok: 1
pages: 1
MEI bytes: 97077
meiversion: 6.0-dev
measures: 16 notes: 196 syllables(lyrics): 138
Reading the MusicXML (score-partwise), it output MEI containing 16 measures, 196 notes, and 138 lyric syllables. For the CLI crowd, it is one line.
verovio -t mei score.xml -o heidenroslein.mei
3. Check the Output MEI
At the beginning (meiHead), the bibliographic information from the MusicXML side is carried over as-is. You can see that the title, composer, lyricist (Goethe), and even the CC0 distribution source remain.
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="6.0-dev">
<meiHead>
<fileDesc>
<titleStmt>
<title>Heidenröslein, D.257</title>
<respStmt>
<persName role="composer">Franz Schubert</persName>
<persName role="lyricist">Johann Wolfgang von Goethe</persName>
</respStmt>
</titleStmt>
<pubStmt>
<availability>
<distributor>OpenScore (CC0)</distributor>
</availability>
</pubStmt>
</fileDesc>
...
Lyrics are kept as <syl> (syllables) tied to notes, expressing even the position within a word (wordpos) and the connection (con). The advantage of moving toward MEI is that the score and text remain linked within a single document.
<syl con="d" wordpos="i">Kna</syl> <!-- start of the word -->
<syl con="s" wordpos="t">be</syl> <!-- end of the word -->
When rendered, these syllables line up directly below the notes (below is a portion of the vocal part and lyrics; "Sah ein Knab' ein Rös-lein…" with the words hyphenated into syllables).

Rendering the converted MEI directly with Verovio (renderToSVG()) produces a score like the following. Vocals + piano, with the lyrics through the third verse aligned to the notes, showing that the MEI mechanically converted from MusicXML holds up as a score as-is.

What Is "Preserved" and What "Changes" in the Conversion
Here are measurements comparing the same "Heidenröslein" MusicXML (after extraction) and MEI.
| Item | MusicXML (score.xml) | MEI (heidenroslein.mei) |
|---|---|---|
| File size | 111,496 bytes | 97,077 bytes |
| Score structure (measures, notes) | 16 measures | 16 measures, 196 notes |
| Lyrics | <lyric> 139 | <syl> 138 |
| Bibliographic metadata | preserved | carried over into <meiHead> |
What Is Preserved
- The substance of the music: the score itself, such as pitch, note value, measures, and voices
- Lyrics: almost as-is, including syllable division and position within a word (the 139→138 difference comes from things like the handling of sustained notes or rests)
- Bibliographic metadata: title, composer, lyricist, and license notice
What Changes / To Be Careful Of
xml:idis reassigned: new IDs are generated on each conversion. If you attach external annotations keyed on IDs, remapping is required- Layout is reinterpreted: line breaks, page breaks, and fine placement are reinterpreted by Verovio's notation engine. It does not guarantee "looks exactly like the original print"
- Schema version: the output above was
meiversion="6.0-dev"(development schema). If you pass it to a recipient that assumes a stable version (e.g., MEI 5.x), it is safer to insert a version specification or validation (withjing, etc.) - Not reversible: MusicXML→MEI→MusicXML does not return to the original XML. This is a "re-encoding of meaning," not "lossless interconversion"
This "changing" nature is not a flaw; it is important to understand that it is naturally so, precisely because the formats have different purposes. If you want faithful reproduction of the print, handle it as MusicXML; if you want to add research description, move to MEI, using each appropriately.
Conversion Methods Other Than Verovio
musicxml2mei(XSLT stylesheet) — a classic converter that the MEI community (music-encoding/encoding-tools) has published. It predates Verovio. However, its target is MEI 3.0 at the latest (current is MEI 5.x), and it requires timewise MusicXML as input (the commonscore-partwiseneeds pre-conversion). Check whether it fits your use case- MuseScore — can handle MusicXML via GUI/CLI. Direct MEI export depends on version and plugins
- Verovio can convert not only MusicXML but also Humdrum (
**kern), ABC, PAE to MEI (EsAC and MuseData go via Humdrum). If you have materials in these formats, it is a convenient entry point
Note that Verovio treats MusicXML as "input" only and does not support MEI→MusicXML export (its outputs are SVG, MEI, MIDI, Humdrum, PAE, etc.). If you want to go back to notation software, you need a separate tool (such as reading MEI in MuseScore).
A Practical Caution: The License Does Not Disappear in Conversion
Being technically convertible and being allowed to redistribute that data are separate matters. Even after conversion, the rights status of the original data carries over.
- This time's OpenScore Lieder is CC0. Since modification and redistribution are free, you can turn it into MEI, place it on your own platform, and publish it
- On the other hand, there are not a few scholarly datasets that are "open access (freely viewable and downloadable)" yet licensed as
All Rights Reserved. In this case, even if you convert the format to MEI, you cannot redistribute it (viewing in your own environment or using it for research is fine; public redistribution requires permission)
"Published = free to reuse" does not hold, so always check the license (the LICENSE file, the copyright records within the data, the site's terms of use) at the stage of selecting materials. If you have redistribution in view, it is safest to choose materials with an explicitly stated license, such as CC0 / CC BY.
Summary
- MusicXML → MEI can be mechanically converted with Verovio (
loadData→getMEI, common to CLI/Python/Node) - Notes, measures, lyrics, and bibliographic metadata are well preserved. For songs, the score and text can be moved into MEI while staying linked
- However, there is
xml:idreassignment, layout reinterpretation, and schema-version differences, and it is not a reversible conversion. Use each format appropriately depending on the purpose (print reproduction, or research description) - The license does not disappear even after conversion. If you have redistribution in view, choose CC0/CC BY materials
References
- Verovio — MEI rendering/conversion library (RISM Digital Center)
- Reference book for Verovio — input formats and API reference
- Music Encoding Initiative — MEI itself
- OpenScore Lieder Corpus (CC0) — the subject of this article



Comments
…