はじめに
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データを生成することができます。