はじめに
2023年10月現在、WebKitのMediaRecorderはwebmフォーマットの録画、録音に対応していません。
また逆にChromeやFirefoxなどは、WebKitがサポートしているmp4フォーマットに対応していません。
つまり全てのデバイスで同じフォーマットのデータで保存を行いたい場合、何かしらの変換処理を加える必要があります。
この記事では、ffmpeg.wasmを使って、MediaRecorderの録音結果などを想定したBlobデータの変換方法を紹介します。
ffmpeg.wasmについて
ffmpegとは、ファイルのフォーマットを変換させるためのツールです。
コマンドベースで簡単に特定のフォーマットに変換をさせることができます。
ffmpeg.wasmはこれをWebassembly化し、ブラウザ上でデータの変換を可能にしたライブラリです。
MediaRecorderについて
MediaRecorderとは、ブラウザ上で録画や録音を行うためのAPIです。
MediaRecorderを用いることで、ブラウザ上で録画、録音を行うことが可能です。
ffmpeg.wasmを用いてファイルフォーマットをaudio/webmに統一する
ffmpeg.wasmを用いて、ファイルフォーマットをaudio/webmに統一してみます。
qiita
ffmpeg.wasmのセットアップ方法については以下をご覧ください。
import { FFmpeg } from "@ffmpeg/ffmpeg";
import { fetchFile, toBlobURL } from "@ffmpeg/util";
const transcodeToWebm = async (blob: Blob) => {
const ffmpeg = new FFmpeg();
const baseURL = "https://unpkg.com/@ffmpeg/core@0.12.4/dist/umd";
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
wasmURL: await toBlobURL(
`${baseURL}/ffmpeg-core.wasm`,
"application/wasm",
),
});
const inputFileName = `input.${blob.type.split('/')[1]}`;
const outputFileName = "output.webm";
const file = new File([blob], inputFileName, {
type: blob.type,
lastModified: Date.now(),
});
await ffmpeg.writeFile(inputFileName, await fetchFile(file));
await ffmpeg.exec(["-i", inputFileName, outputFileName]);
const output = await ffmpeg.readFile(outputFileName);
if (typeof output === "string") throw new Error("Output is not a blob");
return new Blob([output.buffer], { type: "audio/webm" });
};
transcodeToWebm内でFFmpegのセットアップも行っていますが、処理が重ためなので分けてしまっても問題ありません。
Reactなどの場合はuseRefを使う方法が公式でも紹介されています。
MediaRecorderを用いて録画、録音などをしている場合は、onstopイベント内で今回紹介したような処理を挟んであげることで、どのデバイスでも同じmimeTypeのBlobデータを生成することができます。