Giter VIP home page Giter VIP logo

ly2video's Introduction

ly2video

ly2video is a Python script which converts music represented by a GNU LilyPond file into a video containing a horizontally scrolling music staff which is synchronized with a MIDI-generated audio rendering of the music.

It is also possible to synchronize the video of the scrolling music notation with a previously recorded audio track of the same music, such as a live performance, even when the audio uses tempo rubato or is not precisely metronomic.

Examples

Here are some examples of videos generated by ly2video.

Caveat emptor

Beware, here be dragons!

Unfortunately I don't currently have the time to work on ly2video much. These means that in some places bitrot has set in.

Having said that, I'll do my best to support anyone who is trying to get it working - please see below for how to get support.

Requirements

Please also read the Installation section below before you start installing anything!

Installation

Installing dependencies on openSUSE 12.2

Install the ffmpeg package from Packman via 1-click install (you can also find the button on this page), or via YaST and/or zypper.

You can ensure the remaining dependencies are installed via something like:

sudo zypper install lilypond timidity python3-pip python-imaging alsa-devel

Installing dependencies on Debian- and Ubuntu-based Linux distributions

There is currently a known issue on these distributions, since Debian and Ubuntu switched from ffmpeg to the libav fork. See issue #32 for a suggested workaround.

Additionally, Debian and Ubuntu both currently ship very old versions of LilyPond, so you might need to install a newer one via the "Generic Packages" section near the top of: http://lilypond.org/unix.html

You can ensure the remaining dependencies are installed via something like:

sudo apt-get install timidity python3-pip python3-pil

Installing dependencies on Arch-based Linux distributions

Download and install the AUR package ly2video-git. See the the Arch wiki for further instructions.

Installing dependencies on other platforms

If you have figured out how to install the dependencies and get ly2video working on another platform, please file a new issue containing the information, so that this README can be updated. Thanks!

Installing required Python module dependencies

ly2video requires some specific Python modules - do NOT install these manually! (unless you are a Python expert.) They can be installed system-wide via:

sudo pip install -r requirements.txt

or for the current user via:

pip install --user -r requirements.txt

You can optionally protect against the risk of installation of these Python modules destabilising any other Python applications you may use, by isolating them in a virtual environment using virtualenv. The most convenient way to do this is via virtualenvwrapper. Once you have virtualenvwrapper installed, it's as simple as:

mkvirtualenv ly2video
pip install -r requirements.txt

Installing ly2video itself

This is done via Python's standard package installation mechanism.

For example, to install system-wide, just run

sudo pip install .

or for the current user via:

pip install --user .

If something fails, please double-check you correctly met the requirements and dependencies detailed above.

Usage

Run ly2video --help to display usage information.

You must ensure that your .ly input file contains both \layout { } and \midi commands, which ensure that valid .midi and .png files are generated when it is run through lilypond --png.

Usage with docker container

Set up your path to argument LILY_FILES in makefile.

Build docker container with workable ly2video inside

make build

Run docker container with access to direcory you point at LILY_FILES

make run

Use ly2video usually. All actions applied in container to your files (LILY_FILES) will change your files (LILY_FILES) outside container.

Support, bugs, development etc.

Firstly, please check the issue tracker for known issues, and if yours is not there, please submit it.

Secondly, if you are able to perform some [[trouble-shooting|TROUBLE-SHOOTING]] yourself, even if you can't identify the exact problem or suggest a fix, any extra light you can shed will greatly increase the chances of it being fixed. Please see the [[trouble-shooting|TROUBLE-SHOOTING]] guide for information on how to do this.

If you know how to fix a problem or contribute an enhancement, you are extremely welcome to fork this repository, commit your fix, and then send a pull request!

Acknowledgements

Huge credits for the initial implementation go to Jiří "FireTight" Szabó, who wrote it as part of his Bachelor's degree. If you are lucky enough to understand Czech, you can read his thesis on ly2video in the doc/thesis/ subdirectory, or online :-) Work on an English translation has begun and is being tracked in issue 15 but is unlikely to be finished any time soon unless someone else volunteers to help out.

Very big thanks also to Jan Nieuwenhuizen not only for co-inventing LilyPond in the first place, but also for helping me implement the complete revamp of the synchronization algorithm, which should be much more robust than the previous one.

And finally of course, much gratitude to the many great people who have contributed to LilyPond over the years. This would not have been possible without you.

License

ly2video is released under the GNU GPL v3.

ly2video's People

Contributors

aspiers avatar beacon515l avatar bitdeli-chef avatar dependabot[bot] avatar eclairevoyant avatar jeandeaual avatar leguye avatar magiraud avatar mikeblackstock avatar pierstitus avatar stemby avatar thawk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ly2video's Issues

cursor scrolling should be sensitive to bar lines

When the scrolling cursor reaches the right-hand scrolling margin, it will jump back to the left hand side. Typically this results in the left side of the video frame showing a partial bar. It would be nicer if the cursor could jump back earlier, at the end of a bar, so that the left side of the video frame almost always starts on a bar line. "Almost" because this is not possible with very wide bars.

ChordNames cause suboptimal margins

The top margin is too much when ChordNames are present. I think the best approach is to count how many rows of pixels are totally white at the top and bottom, and then centre the effectively cropped music accordingly in cropVideo().

transparent notes break synchronization

If the .ly source has \hide in, with \hide defined as follows:

hide = {
  \once \override Dots #'transparent = ##t
  \once \override NoteHead #'transparent = ##t
  \once \override NoteHead #'no-ledgers = ##t
  \once \override Stem #'transparent = ##t
  \once \override Flag #'transparent = ##t
  \once \override Beam #'transparent = ##t
  \once \override Accidental #'transparent = ##t
  \once \override Glissando #'(bound-details left padding) = #0.3
}

then Lilypond still generates a NoteOn event for the hidden note, even though it is not present in the PDF. This causes a loss of synchronization between MIDI frames and video frames.

The same happens with \hideNotes.

Title Frame can be generated much more efficiently

Multiple frames are currently generated for title screen; only 1 is needed.

The following website seems to suggest that -r 1/(number of seconds) would do the trick:

http://ffmpeg.org/trac/ffmpeg/wiki/Create%20a%20video%20slideshow%20from%20images

I don't know python, but I think on ffmpeg side, replace

# generate silent title video
        silentAudio    = generateSilence(options.titleDuration)
        titleFramePath = tmpPath('title', 'frame%d.png')
        titlePath      = tmpPath('title.mpg')
        cmd = [
            ffmpeg,
            "-f", "image2",
            "-r", fps,
            "-i", titleFramePath,
            "-i", silentAudio,
            "-q:v", str(options.quality),
            titlePath
        ]
        safeRun(cmd, exitcode=14)

with

# generate silent title video
        silentAudio    = generateSilence(options.titleDuration)
        titleFramePath = tmpPath('title', 'title.png')
        titlePath      = tmpPath('title.mpg')
        cmd = [
            ffmpeg,
            "-f", "title",
            "-r", 1/(variable from --title-duration),
            "-i", titleFramePath,
            "-i", silentAudio,
            "-q:v", str(options.quality),
            titlePath
        ]
        safeRun(cmd, exitcode=14)

parser language currently hardcoded to English

Currently the parsing of pitches from the source .ly file is hardcoded to assuming \include "english.ly" is present. The parser needs to iterate the whole file and extract the correct language automatically.

--title-at-start broken (2)

After my fix (--title-at-start broken(1) bug report) I am still getting the following error:

TITLE: ly2video will generate approx. 90 frames.
Traceback (most recent call last):
File "./ly2video.py", line 2015, in
status = main()
File "./ly2video.py", line 1983, in main
generateTitle(titleText, options.width, options.height, fps, titleLength)
File "./ly2video.py", line 176, in generateTitle
nameFont = ImageFont.truetype("arial.ttf", height / 15)
File "/usr/lib64/python2.7/site-packages/PIL/ImageFont.py", line 218, in truetype
return FreeTypeFont(filename, size, index, encoding)
File "/usr/lib64/python2.7/site-packages/PIL/ImageFont.py", line 134, in init
self.font = core.getfont(file, size, index, encoding)
IOError: cannot open resource

I am using lilypond-2.16.2 on Linux Fedora 18 (64bits)

same_quant error

Most recent (as of 2/11/13) ffmpeg has depreciated same_quant and ly2video fails.

I forget the specifics of what happened here. If I remember correctly, I had 1 file I created that worked; it was a single staff. When I added a staff, I got the same_quant error.

Removing same_quant degraded video worked but degraded audio and video quality; fix was to insert -b:a 320 and -q 5

sync breaks when MIDI starts with only a chord

If the piece begins with a chord and no note, then the chord will typically get skipped:

absolutePitches: {(21, 23): u"f'", (21, 21): u"e'", (21, 19): u"d'"}
c   @  26: 25 | grob(time=0.0000, x=  273, tick=    0) | MIDI(tick=    0)
    grob's pitch 48 not found in midiPitches; probably a tie - skipping grob and tick.
    midiPitches: 60 (C) 64 (E) 67 (G)
d'  @  22: 19 | grob(time=0.2500, x=  291, tick=  384) | MIDI(tick=  384)
e'  @  22: 21 | grob(time=0.5000, x=  314, tick=  768) | MIDI(tick=  768)
f'  @  22: 23 | grob(time=0.7500, x=  337, tick= 1152) | MIDI(tick= 1152)
sync points found:     3
             from:     4 original indices
              and:     5 original ticks
   last tick used:     3
    ticks skipped:     1

This results in the first video frame starting from the first note (after the first chord), whereas the MIDI file starts from the first chord, so they are immediately out of sync.

\include "file-in-cwd" doesn't work

ly2video cannot handle \include statements that refer to files in the current working directory. It has been suggested that this is because it copies the main .ly file into a temporary directory for its build work, and it does not copy anything \include'd.

ly2video uses old version of `ly` module; conflicts with python-ly package

When ly2video is installed, the toplevel ly Python package conflicts with the ly module of the python-ly package. That package in turn, is needed to run Frescobaldi. I decided to make ly a standalone package so other tools (such as ly2video) can use it as well.

ly2video is using an old version of the same ly module, and probably could be changed so it depends on the python-ly package. The ly parser has improved since then and is maintained very well. I am willing to investigate the effort needed to use the parser from the newer ly module, from the python-ly package. And I can help making the changes. When that is done, python-ly becomes a dependency of ly2video.

An easier solution could be to move the ly module in ly2video to a private space or another name, such as ly2v.ly or ly2vly.

--title-at-start broken (1)

The --title-at-start option is currently broken.
I found one of the causes:

--- ly2video.py.orig    2013-02-08 08:29:55.953863236 +0100
+++ ly2video.py 2013-02-08 08:32:02.424701547 +0100
@@ -1980,7 +1980,7 @@

     # generate title screen
     if options.titleAtStart:
-        generateTitle(titleText, width, height, fps, titleLength)
+        generateTitle(titleText, options.width, options.height, fps, titleLength)
         output_divider_line()

     # generate notes

but this only partially fixes the problem. See my next submiited issue.

ly2video uses old Frescobaldi 1.x code

ly2video currently uses a copy of some old Frescobaldi 1.x code. Meanwhile, Frescobaldi 2.0 (a complete rewrite IIUC) is being actively worked on, and 1.x is no longer maintained. Having said that, sticking with 1.x could arguably be an advantage, since it's not a moving target, and may well be simpler to understand.

--version is missing

There needs to be a --version option supported for displaying the version number and license summary, as per GNU recommendations.

Add mode for vertical bar to scroll rather than music

Rather than having the staff horizontally scrolling left past a fixed vertical bar, there should also be the option of having the staff stay still and the vertical line scrolling right. When it reaches the far right of the screen, the staff would refresh to show the next few measures of music.

Some thought would be needed to ensure this happens in a visually intuitive manner e.g. the refresh should perhaps happen just before the line reaches the right hand edge, since humans always read slightly ahead. Also it might make sense to align measure breaks with the left and right-hand edges of the video, although that could pose other problems.

Chord repetition does not work

If my score contains chord repetitions like

<a c e>1 q <f a c>2 q

the script dies with

ERROR: Expected pitch token during conversion from relative to absolute
pitch, but found <class 'ly.tokenize.Unparsed'> instance @ /home/dir/ly2video-0.4.1/ly2video.tmp/sanitised.ly:25:38:

q

Format and filename extension of temporary videos should be same as output

If a title page is requested, ly2video creates 2 temporary videos and then joins them. To avoid lossy changes, the format of these videos should be the same as that of the requested output file. This should be as simple as replacing the filename extension of the interim video with that of the specified output file.

Porting to Python 3

It would be great if you could port ly2video to Python 3.

Thank you!

Carlo

Improve handling of dependencies

Currently the zip file includes some dependencies. These should be handled out of band, and corresponding installation instructions provided ('pip install PIL' etc.)

ChordNames break synchronization

The ChordNames context does not have an impact on MIDI rendering in LilyPond, but it does result in multiple note events being rendered as a single text grob (e.g. "Eb-7") whose PDF annotation links back to a location in the .ly source which looks like a normal note e.g. ef1:m9, which the tokenizer currently cannot distinguish from a normal note.

This makes it almost impossible for the synchronization algorithm to work. It's cleaner just to remove chords from the equation. This can easily be done with the MIDI by creating a separate \score which excludes the chords, but they still appear in the PDF.

"page turn" when cursor scrolls past right margin should be a smooth scroll

Currently, in cursor scrolling mode (i.e. when --scroll-notes is not used), when the cursor goes past the right margin (as defined by the second value to the --cursor-margins option) the notation instantly changes to the next chunk. It would be visually easier for the eyes/brain to track if the notation smoothly but quickly scrolled from right to left to the new position. This should happen very quickly to minimise distractions (e.g. in < 0.5 seconds).

articulate.ly should not have to be disabled

ly2video currently removes articulate.ly from the sources in order to stop MIDI events which sound ornaments from breaking the synchronisation. However this obviously has a negative impact on the quality of the performance. A smarter synchronisation algorithm might be able to tolerate these additional ornaments in the MIDI stream. Most likely this would require synchronisation based not only on pitch, but also on note length.

\parenthesize breaks synchronization

It seems that a note preceded with \parenthesize ends up having the grob cause pointing at the \parenthesize token not the note pitch. This breaks calculation of absolute pitches. Maybe work-around by just parsing the next token, or use a while loop with a bail-out threshold?

Calling Variable in << \staff \\ \tabstaff >> fails with error Not enough synchronization points found

Calling the variable melody gives error Not enough synchronization points found. Also fails when \new TabStaff is replaced with \new Staff.

This file compiles correctly when the music is explicitly stated inside the individual \staff contexts.

% Created on Sat Feb 09 15:10:04 EST 2013
\version "2.16.2"

\header {
    title = "Ode To Joy" 
    composer = "Beethoven" 
    tagline = "" 

}

\include "english.ly"

melody = {
    e e f g g f e d c c d e e4. d8 d2
    e4 e f g g f e d c c d e d4. c8 c2
    d4 d e c d e8 f e4 c d e8 f e4 d c d g,2
    e'4 e f g g f e d c c d e d4. c8 c2         
        \bar "|."

}

staffClassicalGuitar =  { 
    \time 4/4
    \tempo 4 = 100 
    \set Staff.midiInstrument = "acoustic guitar (nylon)"
    \key c \major
    \clef "G_8"
    \relative c' {  
        \melody
    }
}

staffTabGuitar = { 
    \new TabStaff {         
        \clef "moderntab"
        \relative c' {  
            \melody 
        }   
    } 
}
\score {
    <<
        \staffClassicalGuitar \\ \staffTabGuitar
    >>

    \midi {
    }

  \layout { indent=0\cm
  }
}

\paper {
}

configuration file

Feature request:
Would it be possible to let me put commandline options in a configuration file that I can load for easy re-usage ?
It can be quite a puzzle to find the best commandline settings. Having the best settings in a file would make things easier.

microtones are not supported

Currently the pitch matching algorithm in alignIndicesWithTicks() only works with semitone (half-step) pitches.

implement bug()

Need a bug() function for reporting fatal errors which indicate bugs in the software. It should output some text asking the user to file a new issue on this tracker.

dubious use of convert-ly

If the input .ly file does not contain \version "2.14.2" then ly2video will run convert-ly to convert it to that version and then operate on the result. An explanation for this is detailed in Jiri's thesis; a translation of the relevant section is:

Each new version of LilyPond can potentially break compatibility with the last. Since ly2video was written primarily for LilyPond's latest published version at its time of creation (i.e. 2.14.2), translation issues may occur when using older projects.One solution is to call the auxiliary script convert-ly, which is delivered directly in the installation package of GNU LilyPond and older projects that can convert to its current form. However, transformation may fail in some cases.

However, since LilyPond has changed hugely since 2.14.2, the current code does not make sense, especially given that in the majority of cases it will now result in a downgrade of the syntax used, even though the original intention was for an upgrade. So we need to decide how to handle this, and then update the code and README accordingly.

Repeated Chords: articulations and others not working

Hi,

thanks for the fast repeated chords fix. Here are some more cases. The one commented out are valid lilypond input but don't work in ly2video.

\version "2.16.0"

\header {
  title = "Regressiontests Chord Repetitions"
}

music = \new Voice {
  \relative c' {
    <a c e>2 q | % chord repetition
    <f a c>1 |
    q | % chord repetition on own line
    <g' c e>4 q q q | % multiple chord repetitions with octave change
    %<a c e>4 q q2 | % different rhythm => q2 script dies
    <g c e>4-. q q q | % repetition after articulation
    <g c e>4 q-. q^. q_. | % repetition articulation normal / up / down
    <g c e>8-. q-. q-- q-> q-^ q-_ q-+ q | % repetition with different articulations
    %<g c e>8_. q^. q-- q-1-3-5 q_1-3^5 q_1-3^4-_ q^5_1-3_+ q | % fingerings/articulations => q-1-3-5 script dies
    <g c e>4\f q\p q\sfz q\mf | % repetition with dynamics
    <g c e>4\f q\> q\! q | % repetition with dynamics / spanners
    %<g c e>4~ q q( q) | % repetition with ties / slurs => <g c e>4\f script dies
    %<g c e>8 q q[ q] q[ q q] q | % repetition =>   q[ script dies
    %<g c e>4 q\( q q\) | % phrasing slur => q\( script dies
    %<g c e>8 q q q-\markup{normal} q_\markup{down} q^\markup{up} q-\markup{ more \italic { complex } \super {markup} } q | % markups => q_ script dies

  }
}

\score {
  \music
  \layout { }
  \midi { }
}

regards
René

Count-in beats

Create frames displaying beat before music to count in with via something that creates number of frames ((60/tempo) * fps) for each beat desired.

multi-line videos

It would be cool to allow multiple systems of music in the same video frame, where the cursor line would only cover one system at any given moment in the video.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.