本メモの結論
ffmpegを使って連番pngを結合して動画を作成するとよさそう。
もっといいやり方あるのかもだけど、この方法である程度改善はしたのでメモを残しておく。
Canvasのpngを連番で保存
このsavePicture()
をdraw()
の一番最後に入れます。適切なmaxCount
を設定してください。
※大量に画像が保存されることになるので、ご注意!
また、私のPCの様に非力だとなぜか出力されないフレームが出てくるので、その場合はsetup()
内でframeRate(5)
とかでフレームレート落として実行してください。
let count = 0;
const savePicture = ( maxCount = 10 ) => {
save( ( '' + count ).padStart( 3, '0' ) + '.png' );
count++;
if( count > maxCount ){
noLoop()
}
}
連番pngをffmpegで結合しmp4化
ffmpeg.exe -r 30 -i ~/Downloads/%03d.png -vcodec libx264 -pix_fmt yuv420p -r 30 out.mp4
結論に至るまで
背景
最近、p5.jsでジェネラティブアートを作って遊んでいるのですが、特に動きのある作品を動画としてtwitterに投稿したときに、自動的に圧縮され非常に残念な結果となります。↓はびっくりするぐらい汚い絵になった例。
setup=_=>g=createCapture({audio:0,video:{}}).hide()
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) August 29, 2020
draw=_=>{a=g.get()
f=fill
resizeCanvas(w=a.width,h=a.height)
u=10
textSize(d=2*u)
for(i=h/u;i--;)for(j=w/u;j--;)f(a.get(u*j,u*i)),r=random(d),circle(u*j,u*i,r)
f(255)
textStyle(BOLD)
text('#つぶやきProcessing #pchj03 ',d,2*d)} pic.twitter.com/N4qLTjCZRc
これは、Windows PCの画面キャプチャでも、iPhone/iPadの画面キャプチャでもどちらでも発生しており、最初はこんなものかなと思っていましたが、他の皆様の投稿を見ていると、キレイに動画を投稿できている方が多いので解はあるはずだと思い、調査を始めました。
解決していそうな方のコメント
なんかtwitterの動画がひどく圧縮されないための条件が複数あるらしいのですが、画サイズを720以下にする以外は動画の設定を細かく調整する必要がありそうです。面倒なので、その辺をケアできているffmepg
の神コマンド落ちていないかなと検索した結果見つけました。↓
こんにちは!
— かねた (@kanetaaaaa) June 21, 2019
特にこれといってしていませんが、30fpsで連番pngで出力したものをffmpegで繋げています。
コマンドはこんな感じです
./ffmpeg.exe -r 30 -i ~/Downloads/img%03d.png -vcodec libx264 -pix_fmt yuv420p -r 30 out.mp4
ただ、デフォルトではp5.jsには連番の画像出力機能はないと思うので、上述の関数を作って連番PNGを出力できるようにしてからトライしました。
やってみた
対応前後の動画を比較します。
Before
こちらはiPadの画面キャプチャをトリミングしたそのままの動画。若干ノイジーに感じます。
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) September 6, 2020
After
コチラが今回の方法で出力した動画。すこしだけキレイになめらかに表示されています!
ffmpegでpngから生成した動画がなめらかに見えるかのテスト pic.twitter.com/7DZguJsv6C
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) September 7, 2020
別の動画も投稿してみましたが、まずまずのなめらかさな気がする。とりあえず、継続して試してみよう。
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) September 7, 2020