Hello list,

ly2video generates a horizontal scrolling video from one large png.  I
am trying to modify ly2video to produce a different kind of video that
looks like this:

https://www.youtube.com/watch?v=Jb5qj6rQv14

It involves multiple 'snippets' of sheet music that are all the same
width.  To get there I used a custom paper size:

#(set! paper-alist (cons '("vid-line" . (cons (* 90 mm) (* 26 mm)))
paper-alist))

\paper {
        #(set-paper-size "vid-line")
}

When I run lilypond to output pngs, I get nicely formatted music
snippets in multiple pngs.  I can then scale them to the video width
using python to create pngs and eventually a video.

On a side note it would be nicer to specify the resolution of the image
I need (so I don't have to scale), but these options:

#(ly:set-option 'png-width 1920)
#(ly:set-option 'png-height 300)

Don't seem to work.

The main issues I have relate to the page numbers.

The first issue is that lilypond produces files like: video-page1.png
and video-page10.png.  This requires a natural sorting algorithm that's
not built into python.  It can be done, but if lilypond could take a
format specifier that was 3 digits long to produce video-page001.png,
it would make things easier.

The second issue is that the space-time-dumper in ly2video produces
what I need, but there are no page transitions indicated.  I can
probably work out the transitions from when the x coordinate wraps, but
it would be nice to have the page change show up in the spacetime info
output.  Ideally with the page number.

I put together a rather complicated mwe for anyone able to help.  It's
two files.  I kept the spacetime dumper code in a separate file.

The output will be noisy.  On linux you can run it like this:

lilypond --png mwe.ly | grep ly2video > spacetime.txt

to dump the spacetime info to a file.

Thanks,
Stef



\include "dump-spacetime-info.ly"

#(define drumtable '(
      (bassdrum () #f -3)
      (snare () #f 1)
      (hihat cross #f 5)
))

drumMusic = \drummode {
	<<
	{ hh8[ hh] <hh sn>[ hh] hh[ hh] <hh sn>[ hh] }
	\\
	{ bd4 s4 bd4 s4 }
	>>
} 

theMusic = \new DrumStaff {
	\set DrumStaff.drumStyleTable = #(alist->hash-table drumtable)
	% TODO: figure out how to relocate tempo mark so that it doesn't
	% impact the vertical height of staves.
%	\tempo 4 = 100
	\repeat unfold 40 \drumMusic
}

\score {
	\unfoldRepeats { \theMusic }

	\layout {
		\context {
			\Score
			\omit BarNumber

			% make only the first clef visible
			\override Clef #'break-visibility = #'#(#f #f #f)

			% make only the first time signature visible
			\override KeySignature #'break-visibility = #'#(#f #f #f)
		}
	}

	\midi {

	}
}

#(set! paper-alist (cons '("vid-line" . (cons (* 90 mm) (* 26 mm))) paper-alist))
\paper {
	#(set-paper-size "vid-line")
	print-page-number = ##f
	% remove indentation
	indent = 0.0
	short-indent = 0.0

	% This hack tries to keep the staves in the same vertical place
	% otherwise the vertical position flucuates due to the height of the
	% tallest beam.
	top-system-spacing.basic-distance = #7
}

% is there a better way to unset the entire header block?
\header {
	print-all-headers = ##f
	title = ##f
	composer = ##f
	copyright = ##f
	tagline = ##f
}

% increase png resolution
#(ly:set-option 'resolution 300)

% setting this option doesn't work like the command line option.
%#(ly:set-option 'backend 'png)

% pngalpha doesn't work.
%#(ly:set-option 'pixmap-format "pngalpha")

% does not work
%#(ly:set-option 'png-width 1920)
%#(ly:set-option 'png-height 300)

% lilypond --png ../mwe.ly | grep ly2video > spacetime.txt

\version "2.20.0"

% Huge thanks to Jan Nieuwenhuizen for helping me with this!

#(define (grob-get-ancestor-with-interface grob interface axis)
  (let ((parent (ly:grob-parent grob axis)))
   (if (null? parent)
    #f
    (if (grob::has-interface parent interface)
     parent
     (grob-get-ancestor-with-interface parent interface axis)))))

#(define (grob-get-paper-column grob)
  (grob-get-ancestor-with-interface grob 'paper-column-interface X))

#(define (dump-spacetime-info grob)
  (let* ((extent       (ly:grob-extent grob grob X))
         (system       (ly:grob-system grob))
         (x-extent     (ly:grob-extent grob system X))
         (left         (car x-extent))
         (right        (cdr x-extent))
         (paper-column (grob-get-paper-column grob))
         (time         (ly:grob-property paper-column 'when 0))
         (cause        (ly:grob-property grob 'cause))
         (origin       (ly:event-property cause 'origin))
         (location     (ly:input-file-line-char-column origin))
         (file         (list-ref location 0))
         (line         (list-ref location 1))
         (char         (list-ref location 2))
         (column       (list-ref location 3))
         (drum-type    (ly:event-property cause 'drum-type))
         (pitch        (if (null? drum-type)
                           (ly:event-property cause 'pitch)
                          (ly:assoc-get drum-type midiDrumPitches)))
         (midi-pitch   (if (ly:pitch? pitch) (+ 0.0 (ly:pitch-tones pitch)) "no pitch")))
   (if #f (format #t "\nly2video: # pitch ~a drum-type ~a ~a" pitch drum-type (null? drum-type)))
   (if (not (equal? (ly:grob-property grob 'transparent) #t))
    (format #t "\nly2video: (~23,16f, ~23,16f) pitch ~d:~a:~a @ ~23,16f from ~a:~3d:~d"
                left right
                (if (ly:pitch? pitch) (ly:pitch-octave pitch) 0)
                (if (ly:pitch? pitch) (ly:pitch-notename pitch) "?")
                (if (ly:pitch? pitch) (ly:pitch-alteration pitch) "?")
                (+ 0.0 (ly:moment-main time) (* (ly:moment-grace time) (/ 9 40)))
                file line char))))

#(define (dump-spacetime-info-barline grob)
  (let* ((extent       (ly:grob-extent grob grob X))
         (system       (ly:grob-system grob))
         (x-extent     (ly:grob-extent grob system X))
         (left         (car x-extent))
         (right        (cdr x-extent))
         (paper-column (grob-get-paper-column grob))
         (time         (ly:grob-property paper-column 'when 0))
         (cause        (ly:grob-property grob 'cause)))
   (if (not (equal? (ly:grob-property grob 'transparent) #t))
    (format #t "\nly2videoBar: (~23,16f, ~23,16f) @ ~23,16f"
                left right
                (+ 0.0 (ly:moment-main time) (* (ly:moment-grace time) (/ 9 40)))
                ))))

\layout {
  \context {
    \DrumVoice
    \override NoteHead.after-line-breaking = #dump-spacetime-info
  }
  \context {
    \DrumStaff
    \override BarLine.after-line-breaking = #dump-spacetime-info-barline
  }
  \context {
    \Voice
    \override NoteHead.after-line-breaking = #dump-spacetime-info
  }
  \context {
    \Staff
    \override BarLine.after-line-breaking = #dump-spacetime-info-barline
  }
  \context {
    \ChordNames
    \override ChordName.after-line-breaking = #dump-spacetime-info
  }
}

Reply via email to