🐰

MediaBunnyというmuxerライブラリが素晴らしい

に公開

https://mediabunny.dev/
https://github.com/Vanilagy/mediabunny

前置き

動画や音声ファイルをブラウザで扱うなら、従来は<video><audio>要素を使うか、FFmpeg.wasmのような大型のWASMライブラリに頼るしかなかったが、WebCodecs APIの普及とともに、より軽量で高性能なソリューションが求められるようになってきた。

そんな中mp4-muxerやwebm-muxerといったライブラリで知られる開発者が、それらを統合・発展させた新しいライブラリ MediaBunny を発表した。

MediaBunnyとは何か

MediaBunnyは包括的なWebCodecsのラッパーであり、公式サイトによれば:

A JavaScript library for reading, writing, and converting media files. Directly in the browser, and faster than anybunny else.

と紹介されている。

開発者自身は「FFmpeg but built for the web」と表現することを好まないとしているが、実際のところその機能範囲は非常に広い。demuxing、muxing、decoding、encoding、resizing、rotation、resampling、transcoding、compressionといった、メディア処理に必要な一連の機能を包括的に提供している。

興味深いのは、このライブラリが「2つのクライアントの支援により開発できた」と開発者が述べている点だ。どちらもWebベースの動画エディタを手がけている企業で、実際にMediaBunnyはそこで「メディアパイプライン全体を支えている」という。
再生は100%MediaBunnyによって行われ(<video>要素は使用しない)、これにより「非常に高速なパフォーマンスと完璧な精度でのシーク」を実現している。
エクスポートもMediaBunnyを通じて行い、通常10倍速でのエクスポートを達成しているそうだ。

技術的な特徴

軽量性
pure TypeScript, has zero dependencies, is very performant, and is extremely tree-shakableであり、全機能を有効にしても最終的なバンドルサイズは約60kBという。公式サイトのデータによれば、.wav ファイルの読み取りなら5.10kB、.webm ファイルの書き込みなら11.4kBと、必要な機能だけを含めることで非常にコンパクトになる。

高性能
開発者は「自分がテストしたすべてのWASMベースのソリューションに速度で勝っている」と主張している。公式サイトのベンチマークを見ると、確かにメタデータの抽出では862 ops/sと、@remotion/media-parserの233 ops/sやffmpeg.wasmの1.83 ops/sを大幅に上回る結果を示している。

対応フォーマット
25種類以上の動画・音声・字幕コーデックをサポートし、MP4、WebM、MP3、Ogg、WAVEファイルの読み書きに対応している。重要なのは、これらすべてが双方向対応(読み取りと書き込み両方)であることだ。

実装例:メディアファイルの読み取り

const input = new Input({
  source: new UrlSource('./bigbuckbunny.mp4'),
  formats: ALL_FORMATS, // .mp4, .webm, .wav, ...
});

const duration = await input.computeDuration();
const videoTrack = await input.getPrimaryVideoTrack();
const { displayWidth, displayHeight, rotation } = videoTrack;
const audioTrack = await input.getPrimaryAudioTrack();
const { sampleRate, numberOfChannels } = audioTrack;

// 動画の中間地点のフレームを取得
const sink = new VideoSampleSink(videoTrack);
const frame = await sink.getSample(duration / 2);

// 動画の全フレームをループ処理
for await (const frame of sink.samples()) {
  // ...
}

このコードを見ると、MediaBunnyが「必要な部分だけを読み込む」という思想で設計されていることが分かる。大きなファイルでも効率的に処理できる設計になっている。

実装例:メディアファイルの作成

const output = new Output({
  format: new Mp4OutputFormat(), // .mp4
  target: new BufferTarget(), // メモリ内
});

// キャンバスからの映像を追加
const videoSource = new CanvasSource(canvas, {
  codec: 'av1',
  bitrate: QUALITY_HIGH,
});
output.addVideoTrack(videoSource);

// オーディオバッファからの音声を追加
const audioSource = new AudioBufferSource({
  codec: 'opus',
  bitrate: QUALITY_HIGH,
});
output.addAudioTrack(audioSource);

await output.start();
// メディアデータを追加...
await output.finalize();

const { buffer } = output.target; // 最終的なファイルを含む

このAPIからは、MediaBunnyが「コンポーザビリティ」を重視した設計になっていることが読み取れる。異なるソースからのデータを組み合わせて、一つのメディアファイルを作ることができる。

変換API

const input = new Input({
  source: new BlobSource(file), // ディスクから読み取り
  formats: ALL_FORMATS,
});

const output = new Output({
  format: new WebMOutputFormat(), // .webmに変換
  target: new StreamTarget(writableStream), // ディスクに書き込み
});

const conversion = await Conversion.init({ input, output });
await conversion.execute();

transmuxing、transcoding、resizing、rotation、audio resampling、trimmingなど、様々な変換処理を行うことができる。

設計思想

開発者は、MediaBunnyを「メディアファイルと相互作用するための基礎的なビルディングブロック」と位置づけている。MediaBunny自体はメディアコンポジター(クリップベースの編集)ではないが、その上により強力なツールを構築できるとしている。

実際、WebCodecs APIの「多くのラッパーと抽象化」を提供し、ブラウザサポートを問い合わせるユーティリティも含んでいる。開発者にとって使いやすいAPIを提供することで、メディア関連のWebアプリケーション開発を促進しようという意図が感じられる。

ライセンスと今後

MediaBunnyはMPL-2.0ライセンスでオープンソース化されており、商用利用も可能だ。開発者は「基礎的なライブラリが真に繁栄するためには、寛容なライセンスが不可欠」と述べている。

パフォーマンスベンチマークを公開し、競合ライブラリとの比較を明示的に行っているのも興味深い。特に、従来の選択肢だったffmpeg.wasmと比較して、大幅な性能向上とサイズ削減を実現している点が良い。

所感

MediaBunnyは、ブラウザでのメディア処理という分野において、一つの転換点になる可能性を秘めている。WebCodecs APIの普及とともに、こうした軽量で高性能なライブラリの需要は高まっているだろう。
WebCodecs APIのブラウザサポートが不完全とはいえ、MediaBunnyのような先進的なライブラリが登場することで、Web標準の普及も加速するかもしれない。

Discussion