bash

ffmpeg を使って音源を合成する! 【LaravelFFMpegの書き方もあるよ】

みなさん、こんにちは。どんぶラッコです。

今日は、ffmpegで複数音源ファイルを1つのファイルにまとめる方法について解説していきます。

グランくん
グランくん
筆者はLaravelFFMpegを使って組み込んだので、そっちのコードも紹介するよ!
グランくん
グランくん
LaravelFFMpegはPHP-FFMpegのラッパーだけど、文法が違ったりするよ。
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 で指定することで、ミックスされた音源が出力ファイルとして生成されます

どんぶラッコ
どんぶラッコ
-map はなくてもデフォルト参照で動くこともあります。僕の環境ではつけなくても動きましたが念のためにつけています!

Laravel-FFMpegで書いてみよう!

Laravelでかくとこんな感じになります。

どんぶラッコ
どんぶラッコ
LaravelFFMpegの導入方法は↓↓の記事を読んでね!

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の情報出てこないんですよね〜。でも英語のドキュメントを読んだらしっかり解説されているので、頑張って英語を読みましょう笑

ABOUT ME
どんぶラッコ
ECコンサルタント、システムエンジニアを経て、quintet株式会社CTOに就任。普段はNuxt.jsやLaravelを使用しています。

\面白いと思ったら/

記事のシェア & Twitter のフォロー をお願いします!

@proglearn
RELATED POST

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です