はじめに
FFmpegを利用して1枚の画像と音声ファイルから動画を作成します。
FFmpegのダウンロード
公式サイトからプログラムを入手します
https://ffmpeg.org/
FFmpegのコマンド
FFmpegで1枚の画像と音声ファイルから動画を作成するコマンドです
ffmpeg -loop 1 -i sample.jpg -i sample.mp3 -vcodec libx264 -acodec aac -ab 160k -ac 2 -ar 48000 -pix_fmt yuv420p -shortest output.mp4
コマンドオプションの説明
コマンド | 説明 |
---|---|
-loop | 1で静止画を繰り返す |
-i | 入力ファイル。画像を先に |
-vcodec | 動画コーデック |
-acodec | 音声コーデック |
-ab | 音声ビットレート |
-ac | 音声チャンネル数 |
-ar | 音声サンプリングレート |
-pix_fmt | yuv420p |
-shortest | 入力の短い方(音声)に動画時間を合わす |
output.mp4 | 出力ファイル名 |
最小オプションのコマンド
ffmpeg -loop 1 -i sample.jpg -i sample.mp3 -pix_fmt yuv420p -shortest output.mp4
-rは25、-abと-acと-arは入力通りになる
Webで動かす
ffmpeg.wasmを使用してWebで動かす。
夢のような話ですが、ブラウザ上でエンコードします。
<form id="form">
音声<input id="audio" type="file" required><br>
画像<input id="image" type="file" required><br>
<button id="button">音声と画像から動画を作成する</button>
</form>
<video id="video" controls></video>
<script>
form.onsubmit = function(event){
event.preventDefault()
button.disabled = true
ffmpeg('-y', '-loop', 1, '-i', image.files[0], '-i', audio.files[0], '-pix_fmt', 'yuv420p', '-shortest', 'out.mp4')
.then( mp4 => video.src = URL.createObjectURL(mp4) )
.finally( () => button.disabled = false )
}
async function ffmpeg(...command){ // https://github.com/ffmpegwasm/ffmpeg.wasm
await import('https://unpkg.com/@ffmpeg/ffmpeg@0.9.6/dist/ffmpeg.min.js')
const ffmpeg = FFmpeg.createFFmpeg({logger: e => console.log(e.message)})
if (!ffmpeg.isLoaded()){
await ffmpeg.load()
}
for(var [i,v] of command.entries()){
if(v instanceof Blob){
ffmpeg.FS('writeFile', String(i), new Uint8Array(await v.arrayBuffer()))
v = i
}
command[i] = String(v)
}
await ffmpeg.run(...command)
return new File([ffmpeg.FS('readFile', v).buffer], v)
}
</script>
きちんと動作するが、エンコードが遅くて実用性に欠ける。
コマンドを工夫するのだろうが分からない。試しに「-r 1」とすると動画時間が狂う
上記のコードですが、少し作り込んでFFmpegのラッピング関数ffmpeg
を作っている。
- コマンドを1つ1つ引数に渡す。入力ファイルは直接渡し、出力ファイル名を最後に渡す
- この関数は非同期であり、成功時はFileオブジェクトが返る
バッチファイルで動かす
音声+画像ファイルをBATファイルにD&Dし、起動させることもできる。
音声と画像から動画作成.bat
@echo off
rem https://qiita.com/economist/items/bb325e8d23e0b3521c65
ffmpeg -loop 1 -i %1 -i %2 -pix_fmt yuv420p -shortest "%~dpn2.mp4"
pause
注意する点として、先に音声ファイルを選択する必要がある
音声ファイルを選択→画像ファイルを選択→両方一緒にBATファイルにD&D
出力ファイル名は音声ファイルで決まる。画像ファイルに合わせたい場合は%~dpn1.mp4