2017年01月29日

楽譜付きの動画を作る方法

 先日公開した「楽譜付きの動画」の作り方メモ。iMovie か何かを使って、音声ファイルに静止画をくっつけていくのが簡単なんだろうけど、何となくコマンドラインでやりたくて、いろいろ模索しました。

 結論から言えば、ffmpeg を使えばできる。Mac 用の ffmpeg は、osxexperts からバイナリをもらってきた。

 まず、楽譜を画像化しないといけない。全部同じ大きさにしないといけないのが地味に面倒。ImageMagick を使うのが簡単かな。楽譜を A5 横サイズの pdf に整形し、次のコマンドで 960×680 ピクセルの png に変換。img-1.png, img-2.png,... という連番のファイルができる。

$ convert -density 116 score.pdf -extent 960x680 img.png

 この静止画を指定時間ずつ表示する動画を作るには、次のようにすればよい。

$ ffmpeg \
-loop 1 -t 14.9 -i img-1.png \
-loop 1 -t 28.2 -i img-2.png \
-loop 1 -t 27.7 -i img-3.png \
-filter_complex "[0:v][1:v][2:v] concat=n=3:v=1:a=0 [v]" \
-map "[v]" -pix_fmt yuv420p -y out.mp4

 -t オプションで指定しているのが、各静止画の表示時間。ポイントは filter_complex です。[0:v][1:v][2:v] で、「0番目・1番目・2番目のストリームのビデオソース」を指定し、concat=n=3:v=1:a=0 [v] で「3つの入力を結合してビデオストリームを1つ(名前が [v])、オーディオストリームを0個」作る。そして -map "[v]" で結合後のストリームを指定し、その後のオプションに従って out.mp4 に書き出す。

 このコマンドラインを手動で打ち込むのは骨が折れる。せっかくシーケンサを使っているんだから、ここはシーケンサに計算させたい。このため、シーケンサ (Alchemusica) を開き、タイミング計算用のトラックを作成して、楽譜を切り替える位置にダミーのイベントを置いて行く。

 Alchemusica は(誰も知らないと思うけど)実は Ruby インタプリタを内蔵している。Window メニューから Ruby Console を開いて、次のように打ち込むと、トラック5(今回使ったタイミング計算用トラック)中のイベントの時刻が秒単位で取得できる。

% self.track(5).each { |e| puts self.tick_to_time(e.tick) }
14.856236
43.048685
70.757131
82.84784
...(中略)...
250.062446

 これを利用して、コマンドラインを自動生成させる。

% i = 0; last = 0.0; self.track(5).each { |e| t = self.tick_to_time(e.tick); printf "-loop 1 -t %.1f -i img-%d.png \n", t-last, i; last = t; i += 1 }; print "-filter_complex \""; i.times { |j| print "[#{j}:v]" }; print " concat=n=#{i}:v=1:a=0 [v]\" \n"
-loop 1 -t 14.9 -i img-0.png \
-loop 1 -t 28.2 -i img-1.png \
-loop 1 -t 27.7 -i img-2.png \
-loop 1 -t 12.1 -i img-3.png \
...(中略)...
-loop 1 -t 8.8 -i img-19.png \
-filter_complex "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v][9:v][10:v][11:v][12:v][13:v][14:v][15:v][16:v][17:v][18:v][19:v] concat=n=20:v=1:a=0 [v]" \

 生成されたコマンドラインを、次のシェルスクリプトの指定位置に貼付けて保存する。これを実行すれば、指定したタイミングで画像が切り替わる動画ができあがる。

#!/bin/sh
ffmpeg \
...(先ほどの出力)...
-map "[v]" -pix_fmt yuv420p -y out.mp4

 ここまではまだ画像だけなので、次にオーディオデータと結合する。

$ ffmpeg -i out.mp4 -i audio.mp3 -vcodec copy -y movie.mp4

 できました。全部コマンドラインで制作したので、制作過程をシェルスクリプトの形で残しておけるのは便利。

タグ:音楽
Posted at 2017年01月29日 01:49:48
email.png