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

data-access.mddocs/

Data Query and Access

This document covers querying element attributes, timing information, MIDI values, page locations, and other data from loaded music notation documents.

Capabilities

Element Attributes

Access attributes of specific elements in the loaded document.

class toolkit:
    def getElementAttr(self, xmlId: str) -> dict:
        """
        Get all attributes of an element as a dictionary.

        Returns all attributes, including those not directly supported
        by Verovio.

        Args:
            xmlId: The @xml:id of the element

        Returns:
            Dictionary with all element attributes
        """

    def getNotatedIdForElement(self, xmlId: str) -> str:
        """
        Get the ID of the notated (original) element.

        When elements are expanded (e.g., due to repeats), this returns
        the ID of the original notated element.

        Args:
            xmlId: The @xml:id of an element (notated or expanded)

        Returns:
            ID string of the notated element
        """

    def getExpansionIdsForElement(self, xmlId: str) -> list:
        """
        Get IDs of all elements (notated and expanded) for a given element.

        When notation includes repeats or other expansions, this returns
        the IDs of both the notated element and all its expanded instances.

        Args:
            xmlId: The @xml:id of an element

        Returns:
            List containing all related IDs
        """

Page Location

Find which page contains a specific element.

class toolkit:
    def getPageWithElement(self, xmlId: str) -> int:
        """
        Get the page number where an element is rendered.

        Takes into account current layout options.

        Args:
            xmlId: The @xml:id of the element

        Returns:
            Page number (1-based) where element appears, or 0 if not found
        """

Timing Information

Query temporal information for elements.

class toolkit:
    def getElementsAtTime(self, millisec: int) -> dict:
        """
        Get IDs of elements being played at a specific time.

        Args:
            millisec: Time in milliseconds

        Returns:
            Dictionary with page number and list of note IDs being played
        """

    def getTimeForElement(self, xmlId: str) -> int:
        """
        Get the playback time for an element.

        renderToMIDI() must be called before using this method.

        Args:
            xmlId: The @xml:id of the element

        Returns:
            Time in milliseconds when element is played
        """

    def getTimesForElement(self, xmlId: str) -> dict:
        """
        Get detailed timing information for a note element.

        Returns score time and real time values for onset, offset,
        and tied duration.

        Args:
            xmlId: The @xml:id of a note element

        Returns:
            Dictionary with timing information:
            - scoreTimeOnset: Score time onset
            - scoreTimeOffset: Score time offset
            - scoreTimeTiedDuration: Score time tied duration
            - realTimeOnsetMilliseconds: Real time onset in ms
            - realTimeOffsetMilliseconds: Real time offset in ms
            - realTimeTiedDurationMilliseconds: Real time tied duration in ms
        """

MIDI Information

Access MIDI values for musical elements.

class toolkit:
    def getMIDIValuesForElement(self, xmlId: str) -> dict:
        """
        Get MIDI values for an element.

        renderToMIDI() must be called before using this method.

        Args:
            xmlId: The @xml:id of the element

        Returns:
            Dictionary with MIDI values (pitch, velocity, channel, etc.)
        """

Descriptive Features

Extract features for music information retrieval tasks.

class toolkit:
    def getDescriptiveFeatures(self, options: dict | None = None) -> dict:
        """
        Extract descriptive features from the loaded document.

        Features are tailored for implementing incipit search and
        other music information retrieval tasks.

        Args:
            options: Dictionary with feature extraction options, optional

        Returns:
            Dictionary with requested features
        """

Usage Examples

Finding Elements on a Page

import verovio

tk = verovio.toolkit()
tk.loadFile("score.mei")

# Find which page contains a specific note
note_id = "note-123"
page_num = tk.getPageWithElement(note_id)

if page_num > 0:
    print(f"Note {note_id} is on page {page_num}")

    # Render that page
    svg = tk.renderToSVG(pageNo=page_num)
else:
    print(f"Note {note_id} not found")

Element Attribute Inspection

import verovio

tk = verovio.toolkit()
tk.loadFile("score.mei")

# Get all attributes of an element
element_id = "note-456"
attributes = tk.getElementAttr(element_id)

print(f"Attributes of {element_id}:")
for attr_name, attr_value in attributes.items():
    print(f"  {attr_name}: {attr_value}")

# Check specific attributes
if 'pname' in attributes:
    print(f"Pitch name: {attributes['pname']}")
if 'oct' in attributes:
    print(f"Octave: {attributes['oct']}")

Playback Synchronization

import verovio
import time

tk = verovio.toolkit()
tk.loadFile("score.mei")

# Render to MIDI first (required for timing queries)
tk.renderToMIDI()

# Simulate playback - highlight notes at current time
playback_time_ms = 0
duration_ms = 10000  # 10 seconds

while playback_time_ms < duration_ms:
    # Get elements being played at current time
    elements = tk.getElementsAtTime(playback_time_ms)

    if elements.get('notes'):
        page = elements.get('page')
        note_ids = elements.get('notes')
        print(f"Time {playback_time_ms}ms: Page {page}, Notes: {note_ids}")

    time.sleep(0.1)
    playback_time_ms += 100

Detailed Timing Analysis

import verovio

tk = verovio.toolkit()
tk.loadFile("score.mei")
tk.renderToMIDI()

# Analyze timing for a note
note_id = "note-789"
times = tk.getTimesForElement(note_id)

print(f"Timing for {note_id}:")
print(f"  Score time onset: {times['scoreTimeOnset']}")
print(f"  Score time offset: {times['scoreTimeOffset']}")
print(f"  Real onset: {times['realTimeOnsetMilliseconds']} ms")
print(f"  Real offset: {times['realTimeOffsetMilliseconds']} ms")
print(f"  Duration: {times['realTimeTiedDurationMilliseconds']} ms")

# Calculate duration
duration = times['realTimeOffsetMilliseconds'] - times['realTimeOnsetMilliseconds']
print(f"  Calculated duration: {duration} ms")

MIDI Value Extraction

import verovio

tk = verovio.toolkit()
tk.loadFile("score.mei")
tk.renderToMIDI()

# Get MIDI values for analysis
note_id = "note-101"
midi_values = tk.getMIDIValuesForElement(note_id)

print(f"MIDI values for {note_id}:")
if 'pitch' in midi_values:
    print(f"  MIDI pitch: {midi_values['pitch']}")
if 'velocity' in midi_values:
    print(f"  Velocity: {midi_values['velocity']}")
if 'channel' in midi_values:
    print(f"  Channel: {midi_values['channel']}")

Working with Expanded Elements

import verovio

tk = verovio.toolkit()
tk.loadFile("score_with_repeats.mei")

# Get the notated (original) ID for an expanded element
expanded_id = "note-repeat-2-note-123"
notated_id = tk.getNotatedIdForElement(expanded_id)
print(f"Notated ID: {notated_id}")

# Get all expansion IDs for a notated element
expansion_ids = tk.getExpansionIdsForElement(notated_id)
print(f"All expansions: {expansion_ids}")

# Query attributes of the notated element
notated_attrs = tk.getElementAttr(notated_id)
print(f"Notated element attributes: {notated_attrs}")

Feature Extraction for Search

import verovio

tk = verovio.toolkit()
tk.loadFile("score.mei")

# Extract features for incipit search
features = tk.getDescriptiveFeatures()

print("Extracted features:")
for feature_name, feature_value in features.items():
    print(f"  {feature_name}: {feature_value}")

# Use features for music similarity comparison
# or incipit-based search

Building an Interactive Score Viewer

import verovio

class ScoreViewer:
    def __init__(self, filename):
        self.tk = verovio.toolkit()
        self.tk.loadFile(filename)
        self.tk.renderToMIDI()  # Enable timing queries

    def get_element_info(self, element_id):
        """Get comprehensive information about an element."""
        info = {
            'attributes': self.tk.getElementAttr(element_id),
            'page': self.tk.getPageWithElement(element_id),
            'times': self.tk.getTimesForElement(element_id),
            'midi': self.tk.getMIDIValuesForElement(element_id)
        }
        return info

    def highlight_elements_at_time(self, millisec):
        """Get elements to highlight during playback."""
        return self.tk.getElementsAtTime(millisec)

    def find_notated_element(self, expanded_id):
        """Find the original notated element for an expanded one."""
        return self.tk.getNotatedIdForElement(expanded_id)

# Usage
viewer = ScoreViewer("score.mei")
note_info = viewer.get_element_info("note-123")
print(f"Note is on page {note_info['page']}")
print(f"Note attributes: {note_info['attributes']}")

Timing-Based Element Lookup

import verovio

tk = verovio.toolkit()
tk.loadFile("score.mei")
tk.renderToMIDI()

# Find all elements played in a time range
start_time = 1000  # 1 second
end_time = 3000    # 3 seconds
interval = 100     # 100ms steps

elements_in_range = []
for t in range(start_time, end_time, interval):
    result = tk.getElementsAtTime(t)
    if result.get('notes'):
        elements_in_range.extend(result['notes'])

# Remove duplicates
unique_elements = list(set(elements_in_range))
print(f"Elements played between {start_time}-{end_time}ms:")
print(unique_elements)

# Get details for each element
for elem_id in unique_elements:
    attrs = tk.getElementAttr(elem_id)
    print(f"  {elem_id}: {attrs}")

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