2021年01月02日

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

 あけましておめでとうございます。今年もよろしくお願いします。

 今年の正月休みは、メンタルには健全だったが(去年は最悪だった)、積み残した仕事が半端じゃない量だった。ようやく一段落したのが 12/30 だった。それから大掃除をして、年賀状を書いて……全般的に2日ぐらい後ろにずれている感じだった。

 さて、今年も正月休みは DTM をやっています。YouTube に上げる時には「楽譜付きの動画を作る」に書いたやり方で楽譜をつけているのですが、いろいろ改良しています。

 まず、画像のサイズは 1280x720 にする。前に調べた時には、「画像は 1920x1080 (1080p)、音声は非圧縮」にすれば高音質 (opus251) で再生される、ということだった。その後に投稿した動画では、画像が 1280x720 (720p) でも opus251 で再生されることがわかったので、今はこちらでやっています。

 1ページ分の動画を作成するのは、下のようなコマンドです。-t 20.52 は1ページ分の時間、-i p01.jpg が1ページ分の画像、fade=in... というオプションは、最初と最後に 0.2 秒ずつのフェードイン・フェードアウトをつけるものです。

$ ffmpeg -loop 1 -t 20.52 -i p01.jpg -vf \ "setsar=1,fade=in:st=0:d=0.2,fade=out:st=20.3:d=0.2" \
-pix_fmt yuv420p -y p01.mp4

 今回少し長めの曲を処理していて、最後の方でページめくりのタイミングがずれることに気がつきました。いろいろ調べてみると、ページめくりの時刻が1フレームの時間の整数倍になってなかったため、四捨五入の誤差が累積して、ずれてしまったようです。上のコマンドで作成した動画は、フレームレートが 25 fps になっていたので、すべての時刻を 40 ミリ秒(1/25 秒)の整数倍で扱うようにした。

 処理は、Alchemusica 内蔵の Ruby インタプリタを使います。まず、トラックを1つ作って、テキストメタイベントでページめくりのタイミングを埋め込んでおきます。時刻0には "title", 演奏終了のタイミングに "end" と入れておく。

20210102-1.png

 次に、Alchemusica の Ruby Console を開いて、次のスクリプトを実行します。

tt = 6        #  タイミングトラックの番号
offset = -0.2 #  ページめくりのタイミング調整
name = nil    #  直前のファイル名(@Text の中身の文字列)
last = 0      #  直前の @Text のタイミング
a = []        #  ファイル名を覚えておく配列
self.track(tt).each { |e|   #  タイミングトラックの各イベントについて繰り返し
  next if e.data[0]=="#"    #  '#' で始まるデータ名はコメントとして無視する
  t = ((self.tick_to_time(e.tick)+offset) * 25).to_i  #  イベントの時刻 (40 ミリ秒単位)
  if name     #  「直前」があれば
    dt=t-last #  そこからの経過時間がそのファイルの動画の長さ
    printf "ffmpeg -loop 1 -t %.2f -i %s.jpg -vf \"setsar=1,fade=in:st=0:d=0.2,fade=out:st=%.2f:d=0.2\" -pix_fmt yuv420p -y %s.mp4\n", dt*0.04, name, (dt-5)*0.04, name  #  動画作成コマンドを出力
    a.push(name)  #  出力した名前を覚えておく
    last=t        #  nameのタイミング(オフセット込み)
  end
  name=e.data   #  次に使うファイル名
}
print "(for f in #{a.join(' ')}; do echo \"file $f.mp4\"; done) >files.txt\n" # 作成した動画を集めるためのシェルスクリプト

 見やすいように改行してコメントを入れていますが、実際には1行に詰め込まないといけません。「コメント+改行」をすべてセミコロン1個に置き換えて、Ruby Console にペーストします。次のようになります。

tt=6;offset=-0.2;name=nil;last=0;a=[];self.track(tt).each{|e| next if e.data[0]=="#";t=((self.tick_to_time(e.tick)+offset)*25).to_i; if name;dt=t-last;printf "ffmpeg -loop 1 -t %.2f -i %s.jpg -vf \"setsar=1,fade=in:st=0:d=0.2,fade=out:st=%.2f:d=0.2\" -pix_fmt yuv420p -y %s.mp4\n",dt*0.04,name,(dt-5)*0.04,name; a.push(name);last=t;end;name=e.data;}; print "(for f in #{a.join(' ')}; do echo \"file $f.mp4\"; done) >files.txt\n"

 Ruby Console に出力されたコードをコピーして:

20210102-2.png

 下のスクリプトの # ---- Replace the following lines from Alchemusica output ----# ---- end Alchemusica output ---- の間に貼り付けます。

#!/bin/sh

# ---- Replace the following lines from Alchemusica output ----
# ---- end Alchemusica output ----

ffmpeg -f concat -i files.txt -codec copy -y scores.mp4
rm files.txt
ffmpeg -i scores.mp4 -i ../PARTITA_revised.flac -vcodec copy -acodec copy -strict -2 -y movie.mp4

 画像は、title.jpg, p01.jpg, ... と1ページずつ順に、1280x720 サイズで作成します。

20210102-3.png

 音声は、Alchemusica で AIFF, 48000 Hz で録音して:

20210102-4.png

 Audacity に読み込み、全選択して「増幅」を選び、New Peak Amplitude を -1 dB にしてレベル調整。(-1 dB に特に根拠はありません。みなさんレベル調整はどうしてるのかな?)

20210102-5.png

 FLAC 形式で書き出します。

20210102-6.png

 先ほどのスクリプトを実行すると、動画が作成されます。20分の楽曲で、170 MB。ずっとハードディスクに置いていると容量を圧迫するけど、一時的に作業するには特に問題ないサイズ。

20210102-7.png

タグ:音楽 DTM Mac
Posted at 2021年01月02日 12:06:16
email.png