ラズパイで動画を作りたいことってありますよね?
ないと思うけど、そんなこと思うことありますよね?
・・・ふと、思いついたことがあったので
どれぐらいのことができるのか検証してみようと思いました。
どうやって作る?
GUIで作るのはかなりきついとおもいますので、シェルコマンドによって動画作成してみたいと思います。
作る動画は、紙芝居的なものにナレーションをつけてみたいと思います。
ナレーションは読み上げで作成を試します。
スライドの画像素材は普通のPCで作って用意します。
- 素材を結合しgifアニメーションの作成
- 読み上げ音声データの作成
- 音声とgifアニメを結合し動画データに
こんなのを想定していますが、できるかなー?
まずはMacで試す
ラズパイでいきなり試すと辛いので、まず普通に試します。
Gifアニメを作る
movieというフォルダに次の画像を入れます。
こんな感じの猫の素材を、frame_01.jpg・・・と連番でフォルダに入れます。
imagemagickをインストールします。
$ brew install imagemagick
これで convert コマンドが使えるようになりました。
$ convert -delay 500 0 frame_*.jpg movie.gif
5秒切り替えのスライドショーができるはず。
読み上げ音声を作ってみる
どうやら、openjtalkという良いものがあるらしいので使わせてもらう。
nodeで使いやすくしてある、node-openjtalkというものがあるのでこれを使う
インストール
$ npm install openjtalk
読み上げ用のものらしく、音声ファイルがつど削除される仕様になっていた。
それは困る。処理を途中で止めると音声ファイルは残るみたいなので使わせてもらう。
適当な読み上げ用の テキストをファイルも作っておいてください。(text.txt)
voice.js
var OpenJTalk = require('openjtalk');
var fs = require('fs');
var mei = new OpenJTalk();
var text = fs.readFileSync("./text.txt","utf-8");
mei.talk(text,200);
process.exit(1);
file.js
wavを探して、名前をvoice.wavに変えます。
必要な複数の音声ファイルがあるところで実行すると危険です。消えます。
法則性がないファイル名だったのでこんなことをしてます。
いろいろ自動化したいという思いでこのプログラム作りましたが、普通は手動でリネームしてください。
var fs = require('fs');
readdir("./");
function readdir(dir) {
fs.readdir(dir, function (err, files) {
if (err) {
throw err;
}
console.log(files);
for(let i = 0; i < files.length; i++) {
var result = files[i].match( /.wav$/ );
if(result != null ){
console.log(result.input);
fs.rename(result.input, 'voice.wav', function (err) {
});
}
}
});
}
音声と、gifアニメができました。
結合して動画を作成する
まずffmpegをインストールします。
$ brew install ffmpeg
結合するコマンド
ffmpeg -i movie.gif -i voice.wav -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
-i がソースとなるファイル名で、最後が出力されるファイル名。
とりあえずできたっぽいです。
quicktimeでは再生できませんでしたが、ブラウザでは再生されます。
youtubeにアップしました。
音声とgifアニメの長さが異なるのでシークバーがバグっとる
※サイコなので閲覧注意
といった感じでとりあえず動画ができました(?)
実際に使うには音声の秒数調節とかが難しそうだなぁ。
ラズパイで試す
ラズパイにubuntuが乗ってるのでapt-getとかでいろいろ入れてく。
imagemagick
$ sudo apt-get -y install imagemagick
ffmpeg
$ sudo add-apt-repository ppa:jonathonf/ffmpeg-4
$ sudo apt update
$ sudo apt-get install ffmpeg
//入ったかチェック
$ ffmpeg -version
node-openjtalk
$ npm install openjtalk
pngのフレーム画像を入れて、gif作成
$ convert -delay 500 frame_*.png movie.gif
音声ファイル作成
$ node voice.js
$ node file.js
合成
ffmpeg -i movie.gif -i voice.wav -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
こんな感じです。超稚拙ですが、処理は全然重くないし、工夫を加えていけば紙芝居的な画像は作れちゃいそうです。
改善版!を考えてみる
どうやらffmpegで動画が結合できるみたいので、紙芝居の結合はそっちに任せたいと思います。
いめーじまじっく不要。画像をいきなり動画に変えます。
そうなると
- 画像を動画に変換(表示秒数の調整)
- 音声をその画像に載せる(mp4化)
- それを紙芝居分作成する。
- 最後に結合する
こんな流れですね。まずはとりあえずやってみよ。
画像を動画にする
$ ffmpeg -f image2 -r 1 -loop 1 -t 00:00:10 -i frame_01.jpg video01.mp4
動画にした画像に音声を合成
$ ffmpeg -i video01.mp4 -i voice.wav -c:a aac -map 0:v:0 -map 1:a:0 v_01.mp4
これをフレーム分、作ります。
動画の後に動画をつなげる・・・な感じで結合する
まず、結合する動画のファイル一覧をテキストファイルにします。
maylist.txt
file v_01.mp4
file v_02.mp4
file v_03.mp4
結合コマンド
ffmpeg -f concat -i mylist.txt -c:v copy output.mp4
できた動画はブラウザだと音声が繋がっておかしかったのですが、youtubeにアップしたら想定した感じになりました。
じつは1080pです。
macで作りましたが、全然処理が重たいとかないのでラズパイでも問題ないでしょう。
ちょっと声が低い方が好みだなぁと思うのであとで調整します。
あ、個人的な話でした。
ちょっと記事が長くなってだるくなってきたのでわけます。
この記事の結論
全然できる!!!!!!11111