A fast, portable and lightweight library for engraving Music Encoding Initiative (MEI) music scores into SVG
This document covers converting between music notation formats including MEI, Humdrum, MIDI, and Plaine & Easie Code, as well as exporting and saving loaded documents.
Export the loaded document as MEI (Music Encoding Initiative) format.
class toolkit:
def getMEI(self, options: dict | None = None) -> str:
"""
Get the loaded document as MEI string.
Args:
options: Dictionary with output options:
- pageNo: int (1-based), export specific page, or all if 0/None
- scoreBased: bool, true for score-based MEI (default: True)
- basic: bool, true for basic MEI (default: False)
- removeIds: bool, remove unused @xml:id attributes (default: False)
Returns:
MEI data as string
"""
def saveFile(self, filename: str, options: dict | None = None) -> bool:
"""
Save the loaded document as MEI to a file.
Args:
filename: Output file path
options: Dictionary with output options (same as getMEI)
Returns:
True if file was successfully written, False otherwise
"""Convert between MEI and Humdrum formats, and filter Humdrum data.
class toolkit:
def convertMEIToHumdrum(self, meiData: str) -> str:
"""
Convert MEI data to Humdrum format.
Args:
meiData: MEI data as string
Returns:
Humdrum data as string
"""
def convertHumdrumToHumdrum(self, humdrumData: str) -> str:
"""
Filter and process Humdrum data.
Applies Humdrum filters to transform the data.
Args:
humdrumData: Humdrum data as string
Returns:
Filtered Humdrum data as string
"""
def convertHumdrumToMIDI(self, humdrumData: str) -> str:
"""
Convert Humdrum data to MIDI.
Args:
humdrumData: Humdrum data as string
Returns:
MIDI file as base64-encoded string
"""
def getHumdrumFile(self, filename: str) -> bool:
"""
Write the Humdrum buffer to a file.
Args:
filename: Output file path
Returns:
True if file was successfully written, False otherwise
"""Manage the internal Humdrum buffer for advanced workflows.
class toolkit:
def setHumdrumBuffer(self, contents: str) -> None:
"""
Set the internal Humdrum buffer.
Args:
contents: Humdrum data as string
"""
def getHumdrumBuffer(self) -> str:
"""
Get the contents of the internal Humdrum buffer.
Returns:
Humdrum buffer as string, or "[empty]" if not allocated
"""
def clearHumdrumBuffer(self) -> None:
"""
Clear the internal Humdrum buffer.
"""import verovio
tk = verovio.toolkit()
tk.loadFile("score.mei")
# Export full MEI
mei_full = tk.getMEI()
# Export specific page
mei_page1 = tk.getMEI(options={'pageNo': 1})
# Export as basic MEI (simplified structure)
mei_basic = tk.getMEI(options={'basic': True})
# Export with unused IDs removed
mei_clean = tk.getMEI(options={'removeIds': True})
# Save to file
tk.saveFile("output.mei")
# Save with options
tk.saveFile("page1.mei", options={'pageNo': 1, 'removeIds': True})import verovio
tk = verovio.toolkit()
# Load MEI file
with open("score.mei", "r") as f:
mei_data = f.read()
# Convert to Humdrum
humdrum_data = tk.convertMEIToHumdrum(mei_data)
# Save Humdrum output
with open("score.krn", "w") as f:
f.write(humdrum_data)import verovio
tk = verovio.toolkit()
# Load and filter Humdrum data
with open("score.krn", "r") as f:
humdrum_input = f.read()
# Apply filters (e.g., transposition, extraction)
humdrum_filtered = tk.convertHumdrumToHumdrum(humdrum_input)
# Save filtered result
with open("score_filtered.krn", "w") as f:
f.write(humdrum_filtered)
# Load the filtered data into toolkit for rendering
tk.loadData(humdrum_filtered)
svg = tk.renderToSVG()import verovio
import base64
tk = verovio.toolkit()
# Read Humdrum file
with open("score.krn", "r") as f:
humdrum_data = f.read()
# Convert to MIDI
midi_base64 = tk.convertHumdrumToMIDI(humdrum_data)
# Decode and save
midi_bytes = base64.b64decode(midi_base64)
with open("output.mid", "wb") as f:
f.write(midi_bytes)import verovio
def export_all_formats(input_file, base_output_name):
"""Export loaded notation to all available formats."""
tk = verovio.toolkit()
tk.loadFile(input_file)
# MEI
tk.saveFile(f"{base_output_name}.mei")
# SVG (all pages)
for page in range(1, tk.getPageCount() + 1):
tk.renderToSVGFile(f"{base_output_name}_page{page}.svg", pageNo=page)
# MIDI
tk.renderToMIDIFile(f"{base_output_name}.mid")
# PAE (Plaine & Easie)
tk.renderToPAEFile(f"{base_output_name}.pae")
# Timemap
tk.renderToTimemapFile(f"{base_output_name}_timemap.json")
# Humdrum
mei_data = tk.getMEI()
humdrum_data = tk.convertMEIToHumdrum(mei_data)
with open(f"{base_output_name}.krn", "w") as f:
f.write(humdrum_data)
print(f"Exported to all formats with base name: {base_output_name}")
# Usage
export_all_formats("input.mei", "output")import verovio
tk = verovio.toolkit()
# Load Humdrum data
with open("score.krn", "r") as f:
humdrum_str = f.read()
# Set buffer
tk.setHumdrumBuffer(humdrum_str)
# Retrieve buffer
buffer_content = tk.getHumdrumBuffer()
# Process buffer content
if buffer_content != "[empty]":
# Save to file
tk.getHumdrumFile("output.krn")
# Clear buffer when done
tk.clearHumdrumBuffer()import verovio
def convert_chain(input_file, input_format):
"""Demonstrate conversion chain through multiple formats."""
tk = verovio.toolkit()
# Set input format
tk.setInputFrom(input_format)
# Load original file
tk.loadFile(input_file)
# Convert to MEI (internal representation)
mei_data = tk.getMEI()
print(f"Converted {input_format} to MEI")
# Convert MEI to Humdrum
humdrum_data = tk.convertMEIToHumdrum(mei_data)
with open("converted.krn", "w") as f:
f.write(humdrum_data)
print("Converted MEI to Humdrum")
# Convert Humdrum back to MIDI
midi_data = tk.convertHumdrumToMIDI(humdrum_data)
print("Converted Humdrum to MIDI")
# Render SVG from original MEI
tk.loadData(mei_data)
svg = tk.renderToSVG()
with open("converted.svg", "w") as f:
f.write(svg)
print("Rendered MEI to SVG")
return {
'mei': mei_data,
'humdrum': humdrum_data,
'midi': midi_data,
'svg': svg
}
# Convert MusicXML through the chain
results = convert_chain("score.musicxml", "musicxml")import verovio
import os
from pathlib import Path
def batch_convert_to_mei(input_dir, output_dir, input_format='auto'):
"""Convert all files in directory to MEI format."""
tk = verovio.toolkit()
if input_format != 'auto':
tk.setInputFrom(input_format)
# Create output directory
Path(output_dir).mkdir(parents=True, exist_ok=True)
# Process all files
for filename in os.listdir(input_dir):
input_path = os.path.join(input_dir, filename)
if not os.path.isfile(input_path):
continue
try:
# Load file
if tk.loadFile(input_path):
# Generate output filename
base_name = os.path.splitext(filename)[0]
output_path = os.path.join(output_dir, f"{base_name}.mei")
# Save as MEI
tk.saveFile(output_path)
print(f"Converted: {filename} -> {base_name}.mei")
else:
print(f"Failed to load: {filename}")
print(f"Error: {tk.getLog()}")
except Exception as e:
print(f"Error processing {filename}: {e}")
# Convert all MusicXML files to MEI
batch_convert_to_mei("musicxml_files", "mei_output", input_format='musicxml')import verovio
tk = verovio.toolkit()
tk.loadFile("score.musicxml")
# Get MEI with full metadata
mei_with_metadata = tk.getMEI(options={
'scoreBased': True,
'basic': False,
'removeIds': False
})
# Save with metadata preserved
with open("converted_with_metadata.mei", "w") as f:
f.write(mei_with_metadata)
# Get simplified version
mei_simple = tk.getMEI(options={
'basic': True,
'removeIds': True
})
# Save simplified version
with open("converted_simple.mei", "w") as f:
f.write(mei_simple)import verovio
def test_round_trip(original_file):
"""Test round-trip conversion: Original -> MEI -> Humdrum -> MEI."""
tk = verovio.toolkit()
# Load original
tk.loadFile(original_file)
mei1 = tk.getMEI()
# Convert to Humdrum
humdrum = tk.convertMEIToHumdrum(mei1)
# Load Humdrum back
tk.loadData(humdrum)
# Get MEI again
mei2 = tk.getMEI()
# Compare (simplified comparison)
print(f"Original MEI length: {len(mei1)}")
print(f"Round-trip MEI length: {len(mei2)}")
# Save both for manual comparison
with open("mei_original.mei", "w") as f:
f.write(mei1)
with open("mei_roundtrip.mei", "w") as f:
f.write(mei2)
return mei1, mei2
# Test round-trip
test_round_trip("score.mei")Install with Tessl CLI
npx tessl i tessl/pypi-verovio