CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-verovio

A fast, portable and lightweight library for engraving Music Encoding Initiative (MEI) music scores into SVG

Overview
Eval results
Files

format-conversion.mddocs/

Format Conversion

This document covers converting between music notation formats including MEI, Humdrum, MIDI, and Plaine & Easie Code, as well as exporting and saving loaded documents.

Capabilities

MEI Export

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

Humdrum Conversion

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

Humdrum Buffer Management

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.
        """

Usage Examples

MEI Export with Options

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})

MEI to Humdrum Conversion

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)

Humdrum Filtering

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()

Humdrum to MIDI

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)

Multi-Format Export Pipeline

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")

Working with Humdrum Buffer

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()

Format Conversion Chain

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")

Batch Format Conversion

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')

Preserving Metadata in Conversion

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)

Round-Trip Conversion Testing

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

docs

advanced.md

data-access.md

format-conversion.md

index.md

loading-config.md

rendering.md

tile.json