みなさん、こんにちは。どんぶラッコです。
今日は、ffmpegで複数音源ファイルを1つのファイルにまとめる方法について解説していきます。
PHP-FFMpegの方は動作未確認だけどテストで作ったコードがあるのでついでに公開しますね
今回実現したいこと
- no2.webm, no3.webm, no4.webm を用意する
- 音源を結合する
- ついでにフィルターを使えるようにする(今回は指定ミリ秒だけ音源の前に無音部分を挿入する)
ffmpegで複数音源の合成
ffmpeg -i no2.webm -i no3.webm -i no4.webm -filter_complex "[0]adelay=1000[a0];
adelay=2000[a1];
adelay=3000[a2];[a0][a1][a2]amix=inputs=3[a]" -map "[a]" out.webm-i を使って読み込むファイルを指定します。
次に、 -filter_complex を 使って、各ファイルに対して実施したいフィルタ処理を選択していきます。
-filter_complex の中身は、 ; でフィルターチェーンが区切られていきます。
文法としては
[in_link_N]filter_name@id=arguments[out_link_1]...[out_link_M]のようになっています。[] と [] の間にフィルター処理を記述することでフィルターを適用できるんですね。
今回はそれぞれの音源に対して adelay=XXXX をかけています。例えばXXXXが1000だったら 1000ミリ秒 = 1秒 音源の開始時間を遅らせるという処理です。
そしてフィルター処理が終わったそれぞれの音源を [a0], [a1], [a2], として出力させています。
その上で、 [a0][a1][a2]amix=inputs=3[a] 処理をかけることで、mixさせているわけですね。そしてミックスが完了した音源を [a] にアウトプットさせ、出力ファイルを生成する元を -map で指定することで、ミックスされた音源が出力ファイルとして生成されます
Laravel-FFMpegで書いてみよう!
Laravelでかくとこんな感じになります。
use ProtoneMedia\LaravelFFMpeg\Filesystem\Media;
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;
// ... 中略
$ffMpeg = FFMpeg::open(['no2.webm', 'no3.webm', 'no4.webm'])->export();
$ffMpeg->addFilter('[0]', 'adelay=1000', '[a0]');
$ffMpeg->addFilter('
', 'adelay=2000', '[a1]');
$ffMpeg->addFilter('
', 'adelay=3000', '[a2]');
$ffMpeg->addFilter('[a0][a1][a2]', 'amix=inputs=3', '[a]');
$ffMpeg->addFormatOutputMapping(new \FFMpeg\Format\Video\WebM, Media::make('local', 'out.webm'), ['[a]']);
$ffMpeg->save();処理ごとに書けるので、こっっちの方が読みやすいかもしれませんね!
addFormatOutputMapping内にある Media::make('local', 'out.webm') 部分がアウトプットファイル作成の指示です。
local の部分は、保存したいストレージの名前を指定してください。もし s3 の設定をされている場合は s3 にすればちゃんと向き先も変わってくれます。
PHP-FFMpegの場合(※動作未確認)
PHP-FFMpegの場合はドキュメントを読む限り、こうやって書けばいいんじゃないかな?と思っています。
ただ、私は動作未確認です。あくまでもイメージとしてお考えください。
$ffmpeg = FFMpeg::create();
$advancedMedia = $ffmpeg->openAdvanced($urls);
$advancedMedia->filters()->custom('[0]', 'adelay=1000', '[a0]');
$advancedMedia->filters()->custom('[0]', 'adelay=2000', '[a1]');
$advancedMedia->filters()->custom('[0]', 'adelay=3000', '[a2]');
$advancedMedia->filters()->custom('[a0][a1][a2]', 'amix=inputs=3', '[a]');
$advancedMedia->map(array('[a]'), new \FFMpeg\Format\Video\WebM, 'test_output');
$advancedMedia->save();意外とffmpegの情報出てこないんですよね〜。でも英語のドキュメントを読んだらしっかり解説されているので、頑張って英語を読みましょう笑






















