wasm版FFmpegが登場!

と言ってもちょっと前の話ですが…

FFmpeg君とは腐れ縁なので、wasmの姿になっても仲良くしていきたいと思います。

 

今回は何を作るのか?

今回はみんな大好き動画ファイルからGIFアニメーションへの変換を行います。

最近GitHubのREADMEに動画を載せることができることになりましたが、その前まではPhotoshopを使って機能ごとのデモGIFアニメーションを載せていました。動画が載せるようになった今もGIFアニメーションの方が見やすいので今後もGIFアニメーションは必要ですが…

今回はwasm版FFmpegを用いて、わざわざPhotoshopみたいな重いソフトを使うのも面倒なのでWeb画面でサクッと変換できるようにしました!

尚、今回のブログではFFmpegの部分を中心的に解説していますが、JavaScriptの基本的な部分やサンプルコード内のFFmpegに関係のない部分以外は特に解説をしませんのでコード内のコメントを元に理解していただければと思います(そんな複雑な処理はしていないです。)

 

サンプルコードとデモページ

今回のコードはGitHubへ、デモ用にGitHubPagesにてデモページを公開しています。

→リポジトリ – GitHub

→デモページ – GitHubPages

 

ブラウザでの読み込み

npm でのインストールも勿論できるのですが、今回は簡単にscriptタグを使って読み込んでみます。

これで読み込みは完了です。

因みに今回は使わないですが、npmの場合はこんな感じ。

 

インスタンスの作成

FFmpegのインスタンスを作成します。

今回は  log と progress のみを有効にしていますが、他のオプションもオブジェクトでまとめて渡すことが出来ます。

  •   corePath :ffmpeg-core.jsスクリプトのパス
  •   log :ログメッセージのコンソール出力の有効 / 無効(デフォルト:  false )
  •   logger :ログメッセージの取得関数
  •   <span>progress :進行状況の取得

と言った感じです。

ちなみにここでのログメッセージとはコマンドライン等でFFmpegを実行した際の標準出力に出力される内容と同じかと思います。横に並べて見比べたわけでは無いので、正確には分かりませんが…

コマンドのFFmpegではオプションでログメッセージのレベルを指定できるのですが、この場合のログレベルがいくつに定まっているか謎です。

 

スクリプトのロード

ffmpeg.wasm-core というwasm版FFmpegのスクリプトを読み込みます。

ffmpeg.isLoaded() でFFmpegのスクリプトが既に読み込まれているかを確認できます。

重複して読み込む場合はエラーになるので気を付けましょう。

尚、読み込み自体に数秒から数分の時間がかかるとされているため、極力早めに読み込むことが推奨されています。

 

FS操作

wasm版のFFmpegで扱うためには、MEMFS(メモリ内ファイルシステム)に保存する必要があります。

そのための関数が  ffmpeg.FS() です。

ffmpeg.FS() は第一引数にメソッド名(文字列)が入ります。

  • 保存:  'writeFile'
  • 取得:  'readFile'
  • リンク解除:  'writeFile'

実際は以下のように書きます。

尚、入力できるファイルサイズに関しては2GBまでという制限があります。

 

保存

  • 第二引数:保存時の名称(文字列)
  • 第三引数:保存するファイル

 

取得

  • 第一引数:呼び出すファイルの名称(文字列)

 

リンク解除

  • 第一引数:リンク解除するファイルの名称(文字列)

 

FFmpegの実行

ffmpeg.run() でFFmpegコマンドを実行します。

コマンドライン上での実行とあまり大差ないのですが、コマンドライン引数はスペース区切りで渡す部分を、JavaScriptの引数の渡し方であるカンマ区切りでオプションやパラメータを文字列として渡しています。

オプションに関しては、通常のFFmpegのドキュメントや記事を参考にしても問題ないです。

因みに上の例は

このコマンドをFFmpegのコマンドとしてコマンドラインで実行するのと同じ処理になります。

尚、個々での出力結果もMEMFSとしてメモリファイルシステムに保存されるため、先程の  ffmpeg.FS() を用いて結果を取得します。

 

実際にGIFへ変換

それでは、実際にGIFへ変換する過程を見ていきます。

基本的にFFmpeg周りに関しては先程解説した内容になります。

流れとしては、

  1. FFmpegの読み込み( ffmpeg.load() の実行)
  2. MEMFSへの対象動画ファイルの保存( ffmpeg.FS('writeFile', ...) の実行)
  3. GIFファイルへの変換コマンドの実行(  ffmpeg.run() の実行)
  4. 実行結果のファイルをMEMFSから取得( ffmpeg.FS('readFile', ...) の実行)
  5. 画像として出力
  6. リンク解除( ffmpeg.FS('unlink', ...) の実行)

の順に処理を行います。

実際のコードはこちら。

 

因みに読み込み部分はこちら

 

 

progress オプションの p には進行状況が少数で入ります。

指定している displayProgress(p) の内容はこちらです。

 

 

進行中に変換ボタン内に進行状況を出力するようにしています。

実際の画面はこんな感じです。

デモ

ちなみにこのGIFアニメーションもサンプルで作りました!

変換時の問題なのか、表示サイズによっては画像上に四角い模様が見えますね。

mp4でしかまだ試していませんが、FFmpegで対応している動画形式なら大半ができるのかな?と思います。

 

最後に

簡単な内容ですが、今回の記事はここで終わりたいと思います。

FFmpeg自体のコード部分はとても短いながらに色々な機能が実装できると思いました。

処理の速度に関しても10秒程度の動画であれば特にストレスない速度で結果が返ってきました。

これからも色々と作ってみたいと思います!

尚、今回紹介していない機能なども公式ドキュメントに記載されているのでこちらも確認してみてください。

 

参考にした記事

 

今回のブログ曲

今回投稿中に聴いていた曲はこちら

 

カテゴリー: JavaScript

コメントを残す

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