Time mark engraver
Appearance
When working with LilyPond’s MIDI output, it can be tedious to find the exact elapsed time from the start of the score to an arbitrary point—especially when the music contains multiple tempo changes. Counting measures and doing tempo math is error-prone; inspecting the MIDI file manually is possible but time-consuming.
To solve this, Jean wrote a small custom engraver that allows you to insert time marks directly into the music. At any point in the score you can add \timeMark, and LilyPond will compute the elapsed time up to that position and display it (2m15s e.g.).
Use case
This is useful when you need to:
- align score events with audio/video cues,
- locate timestamps for MIDI-driven playback or mockups,
- find “time since start” at a few key musical points without counting or math,
- work reliably across complex tempo maps (rit., accel., metric modulations, etc.).
\version "2.24.4" % source: https://lists.gnu.org/archive/html/lilypond-user/2024-03/msg00127.html % credits: 2024 - Jean Abou Samra #(define (Custom_engraver!! context) (define (format-time seconds) ; ex.: 2m15s (let ((minutes (euclidean-quotient seconds 60)) (rest (euclidean-remainder seconds 60))) (string-append (if (zero? minutes) "" (format #f "~am" minutes)) (format #f "~as" (round rest))))) (let ((wholes-per-minute 15) (last-time ZERO-MOMENT) (total-time 0) (marks '())) (make-engraver ((process-music engraver) (let* ((new-time (ly:context-current-moment context)) (time-delta (ly:moment-main (ly:moment-sub new-time last-time))) (new-wholes-per-minute (and=> (ly:context-property context 'tempoWholesPerMinute #f) ly:moment-main))) (set! total-time (+ total-time (* 60 (/ time-delta wholes-per-minute)))) (set! last-time new-time) (when new-wholes-per-minute (set! wholes-per-minute new-wholes-per-minute)))) (acknowledgers ((text-mark-interface engraver grob source-engraver) (set! marks (cons grob marks)))) ((process-acknowledged engraver) (for-each (lambda (grob) (when (assq-ref (ly:grob-property grob 'details) 'time-mark) (ly:grob-set-property! grob 'text (format-time total-time)))) marks) (set! marks '()))))) \layout { \context { \Score \consists #Custom_engraver!! } } timeMark = \tweak details.time-mark ##t \tweak color "red" \textEndMark "Abracadabra" { c'1 \timeMark \tempo 4 = 120 c'4 8. 16 2 \timeMark \tempo 4 = 180 c'2 2 \timeMark \repeat unfold 180 c'4 \timeMark }