rakushoo blog

ジャズとプログラミングがやりたい人

herokuサーバー上で、music21のpngファイル出力に失敗する

前回の記事でherokuサーバー上でmusic21を動かす際に、LilypondとmuseScoreのパス設定が必要、まだpng画像が生成されないことを書きました。
music21をherokuサーバーで動かす時に困ったこと - rakushoo blog

結論としては、Lilypond(2.20.0-1)内のgsバージョン不整合が原因でした。Buildpackでgsもインストールするようにし、Lilypondから参照するバイナリと差し替えることで対応したところ、png画像が出力されるようになりました。

解決までの経過

ローカルでは動くしパスも通ってるのに何故か画像が出力しない。 png変換でwarningが出ていました。

Converting to PNG...  
warning: `(gs -q -dSAFER -dEPSCrop -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dNOPAUSE -dBATCH -sDEVICE=png16m -dAutoRotatePages=/None -dPrinted=false -sOutputFile=Oleo.png -r101 -fOleo.eps)' failed (256)  
fatal error: failed files: "/app/media/output/Oleo"

とりあえず、gsなんちゃらのコマンドで失敗していると。ここで3日ほどハマったので、検討した手順だけ残しておきます。

  • そもそも入力ファイルがどういう手順でpngに変換されるかを確認。
  • ローカルでは、lyファイル、epsファイル(複数)、pngファイルが作成されている。この時点で拡張子なしのファイル(.lyファイル)のみ作成されていた。→ epsファイルの変換で失敗している、ぽい
  • music21のソースをfolkして確認。コード見ても異常なし。
  • herokuサーバーにログインして、lilypondを直接実行したところ、.epsファイルが一つ作成されるがやはりgsで失敗。

lilypondの不具合だということまではわかった

不具合は、music21ではなく、Lilypondが受け持つ処理で、gsコマンドが失敗している、とまでわかった。外部アプリの不具合は辛い。。まあ仕事じゃないし、諦めてローカルで画像を作るようにPCアプリにしようかとぼんやり考えながら休憩。

ふと、デバッグログとか無いかな?、とlilypondのヘルプを見たら大当たりでした。
ログレベルを設定して実行したところ、gsコマンドのバージョン不一致が原因とのこと。

/app/lilypond/usr/bin/lilypond -f png -dbackend=eps --loglevel=DEBUG -o /app/media/output/test /app/media/output/sample.ly
〜省略〜
[test.eps] Invokinggs -dSAFER -dEPSCrop -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dNOPAUSE -dBATCH -sDEVICE=png16m -dAutoRotatePages=/None -dPrinted=false -sOutputFile=test.png -r101 -ftest.eps'...
gs: Interpreter revision (926) does not match gs_init.ps revision (921).

lilypond内のgsバージョン不整合が原因

インストールしたLilypond(2.20.0-1)から通るパスのgsバージョンは9.26だが、途中で必要となるgs_init.psバージョンが9.21と不整合となっていた。

Buildpackでgs(Ghostscript)9.21をインストールし、lilypondから使用するgsと差し替えることにし、無事に画像出力ができるようになった。

GitHub - rakushoo/heroku-buildpack-ghostscript: Ghostscript for Heroku Cedar

自分のアプリから呼び出したアプリ内の不具合調査は疲れるけど、良い経験になりました。