WebCodecs: ブラウザの動画エンコーダで、動画を小さく書き出す

動画の変換を、ブラウザが持っているエンコーダに任せる。どのエンコーダがあるかはブラウザ次第で、指定したビットレートが守られるとも限らない。

公開: 2026年9月17日 / 更新: 2026年9月17日 / 文: おたすけ

スマホで撮った動画をメールに添付しようとして、上限を超えて送れない。必要な部分だけを切り出し、解像度や画質を落として作り直せば送れる。動画の切り出し・圧縮 は、この作業をするツールである。動画はサーバーに送らず、ブラウザの中で変換する。

動画を小さくするには、圧縮された映像をいったん 1 枚ずつの画像にほどき(復号)、少ないデータ量で圧縮し直す(符号化)必要がある。ブラウザでこれをやるなら、動画変換の定番である FFmpeg を WebAssembly にしたもの(ffmpeg.wasm など)を持ち込む方法がある。このツールはそうせず、ブラウザに組み込まれたエンコーダを WebCodecs という API で呼び出している。自前で持ち込まないぶん、使えるものはブラウザに左右される。

WebCodecs は、何をしてくれる API か

WebCodecs は、映像と音声の符号化と復号を、フレーム単位の細かさで Web ページから扱うための API である(MDN の解説)。映像のエンコーダとデコーダ(VideoEncoderVideoDecoder)、音声のエンコーダとデコーダ(AudioEncoderAudioDecoder)の 4 つが中心になる。

ただし WebCodecs が扱うのは、符号化と復号だけである。MP4 や WebM のファイルから映像のデータを取り出すことも、符号化したデータを再生できるファイルにまとめることもしない。動画ファイルは、映像と音声のデータを時刻の情報と一緒に詰めた入れ物(コンテナ)で、その読み書きは別に用意しなければならない。MDN もその用途のライブラリとして挙げている Mediabunny(MPL-2.0)を、このツールは MP4、MOV、WebM の読み込みと、MP4 と WebM への書き出しに使っている。切り出し、解像度の変更、エンコーダの設定も Mediabunny を通して行う。

どのブラウザで使えるのか

4 つの API がそろった時期は、ブラウザによって違う。MDN の browser-compat-data(2026年9月17日時点の 8.1.2)では、次のとおりである。

出典は MDN の VideoEncoderAudioEncoder の互換性表である。Can I use も Safari 16.4〜18 を部分対応、26 からを対応としている。Safari 26 で音声のエンコーダが加わったことは、WebKit のリリースノート(WebKit Features in Safari 26.0)にも書かれている。

したがって Safari 16.4〜18 では、映像は変換できても音声は作れない。この環境では音声ありの形式を選べなくし、その理由と、音声を「なし」にすれば映像だけで書き出せることを画面に出す。

API があっても、エンコーダがあるとは限らない

VideoEncoder があることは、H.264 のエンコーダがあることを意味しない。どのコーデック(圧縮の方式)を符号化できるかは、ブラウザ、OS、端末ごとに違う。そこでツールは、ページを開くたびに VideoEncoder.isConfigSupported()AudioEncoder.isConfigSupported() で、H.264、VP9、VP8 の映像と、AAC、Opus の音声を符号化できるかをブラウザに問い合わせる。対応表を自分では持たない。

いちばん差が出るのが、MP4 の音声に使う AAC である。MDN のコーデックの選び方の解説は、WebCodecs の AAC の符号化は、どのプラットフォームの Firefox でも、パソコンの Linux ではどのブラウザでも使えない、と書いている。

書き出す形式は二つ用意し、問い合わせの結果から選べるかを決める。

選べない形式には、足りないエンコーダの名前を添える。両方選べるときは、MP4 を選んだ状態から始める。MP4 の中に Opus の音声を入れる組み合わせも、仕組みの上では作れる。それを選ばなかったのは、再生できない端末が多いと判断したからである。WebM にも、iPhone の写真アプリなど再生できない環境があるので、WebM を選ぶと画面にそう添える。

Linux のブラウザで AAC が使えないことは、開発者の側では実機で確かめていない。MDN の記述を根拠にしているが、ツール自体は上の問い合わせで判断するので、仮に AAC が使える環境があれば、音声ありの MP4 を選べる。

読み込む側にも、環境の差がある。iPhone の動画は HEVC(H.265)で記録されていることが多く、HEVC を復号できるかはブラウザと端末によって違う。ツールは読み込んだ時点で復号できるかを確かめ、できなければ理由を示し、iPhone のカメラの設定を「互換性優先」にすると H.264 で記録されることを案内して止まる。

出力サイズの目安は、どう計算するのか

ファイルの大きさは、おおよそ「1 秒あたりのデータ量(ビットレート)× 長さ」で決まる。以前のツールは、この式を逆向きに使っていた。送り先の上限と切り出した長さからビットレートを逆算し、解像度やフレームレートまで自動で決める。送り先に収めるだけなら、利用者の手間は少ない。

ところが、解像度やフレームレートは自分で決めたいという要望があった。自動で決めた音声のビットレートが、音声を消す原因にもなっていた。いまは式を順向きに使い、利用者が選んだ設定からビットレートを決めて、大きさの目安を出す。

  1. 解像度は、元のまま、長辺 1920・1280・854・640 ピクセル、幅の指定から選ぶ。高さは縦横比から決め、幅と高さを偶数に丸める。H.264 などで一般的な色の間引き方(4:2:0)が、縦横とも偶数の大きさを前提にしているからである。元の動画より大きくはしない。
  2. フレームレートは、元のまま、60・30・24・15 fps、数値の指定から選ぶ。元より上げはしない。
  3. 映像のビットレートは、kbps で直接指定するか、画質を「高・中・低」から選ぶ。画質で選んだときは、幅 × 高さ × フレームレートに、1 画素・1 フレームあたりのビット数を掛ける。H.264 では高 0.15、中 0.10、低 0.06 とし、同じ見た目を少ないデータで作れる VP9 では 0.11、0.07、0.045 にしている。
  4. 音声は、192・128・96・64 kbps か、なしから選ぶ。
  5. 目安は、映像と音声のビットレートの合計に長さを掛けて 8 で割り、ファイルの管理情報のぶん(64 KB と、1 秒あたり 2.5 KB)を足した値である。

たとえば 1920 × 1080 ピクセル、30 fps の動画を 1280 × 720 に縮め、画質「中」、音声 128 kbps で 30 秒を切り出すと、映像は約 2.76 Mbps、目安は約 11.0 MB になる。854 × 480、画質「低」、音声 96 kbps にすると、60 秒を切り出しても目安は約 6.5 MB である。どちらもツールの計算部分に同じ条件を与えて出した値である。

送り先の上限とは、比べるだけにした。設定を選ぶたびに、目安がメール(上限 10 MB)、Gmail(25 MB)、Microsoft Teams(100 MB)に収まるかを表示し、設定そのものは変えない。メールでは、上限そのものとは比べない。添付ファイルは送信時に Base64 という文字の並びに変換され、3 バイトが 4 文字になり、76 文字ごとに改行が入る(RFC 2045 の 6.8 節)ので、約 1.37 倍に膨らむ。メールサーバーの上限はこの膨らんだあとの大きさに掛かることが多いので、上限 10 MB のメールでは 7.2 MB までを「収まる」とみなす。先の例の 6.5 MB はメールに収まり、11.0 MB は Gmail(18.2 MB まで)にだけ収まる。

H.264 はレベルという区分ごとに扱える画面の大きさに上限があるので、変換の直前に、選んだ解像度とビットレートでもう一度エンコーダに問い合わせる。

Windows の Chrome で、音声だけが消えていた

目標サイズから逆算していたころ、利用者から報告があった。長さ 35 分、2150 MB、1920 × 1080 の H.264 と AAC の動画を Windows の Chrome で変換すると、書き出した動画から音が消える。同じ環境で短く切り出したときは、音声が残った。

長い動画でだけ起きるので、長時間の処理のどこかで音声のデータが途切れたように見える。ところが、手がかりは処理の長さではなく、ビットレートの計算の分岐にあった。

以前の逆算は、全体のビットレートが 600 kbps を下回ると、音声を 64 kbps にしていた。35 分の動画でこの分岐を避けるには、目標を約 180 MB 以上にしなければならない。たとえば Teams の 100 MB を選ぶと、全体は約 320 kbps で、音声は 64 kbps になる。報告にあった短い切り出し(1 分 35 秒、854 × 480)は、25 MB 前後の目標を選んだときの計算と合い、このとき音声は 96 kbps 以上になる。

一方、Windows の Chrome と Edge は、AAC の符号化を 96・128・160・192 kbps でしか受け付けない。Chromium のソース(audio_encoder.cc)では、Windows でこの四つ以外のビットレートを指定すると、AudioEncoder.isConfigSupported() が非対応と答える。Mac では、エンコーダが扱える近いビットレートに下げて符号化する。

64 kbps の AAC を作れないと分かると、Mediabunny は音声のトラックを出力から外し、外した理由を記録する。ただし映像のトラックが残っていれば、変換そのものは有効とみなして進む。ツールはその記録を見ていなかったので、音のない動画が何の知らせもなく書き出された。

報告者が選んだ目標サイズは分かっていないので、報告者の環境でこの経路を再現したわけではない。確かめられたのは、報告された条件がこの分岐と矛盾しないところまでである。開発環境では、Windows の Chrome と同じ答えを返す偽の AudioEncoder を置き、64 kbps を指定すると Mediabunny が音声を外したまま変換を有効とみなすことを、テストで確かめた。

いまのツールは、音声のビットレートごとにエンコーダへ問い合わせ、受け付けない値を選べなくしている。それでも音声が外されたら、変換を始める前に止めて理由を示す。書き出したあとは、ファイルを開き直して音声のトラックがあるかを表示する。

固定ビットレートを指定しても、目安を超えることがある

ビットレートの指定は、エンコーダへの目安である。目安と実際の大きさが離れないよう、場面ごとに配分を変えるより平均を守ってほしいので、ツールは固定ビットレートを指定している。それでも、指定どおりの大きさになるとは限らなかった。

開発中、Linux のヘッドレス Chromium(画面を出さずに動かす Chromium。H.264 の符号化には OpenH264 が使われる)で、時間方向のノイズを強く載せた 1080 × 1920 の映像に 3.9 Mbps を指定したところ、出力は 6.7 Mbps になった。ノイズの多い映像は圧縮しにくく、エンコーダが指定を下回れなかったと考えられる。同じ素材でも 720 × 1280 に落とすと、当時の目標サイズに収まった。

画素数に対して低いビットレートを選ぶほど、このずれは起きやすいと考えられる。そのため、書き出したファイルは開き直して大きさと長さ、トラックを確かめ、実際の大きさが目安から何 % ずれたかを表示する。作り直すかどうかは、その差を見て利用者が決める。

書き出す動画に残るもの、確かめていないこと

書き出す動画には、元の動画の撮影日時や撮影場所などのメタデータを引き継がない。ffmpeg でタイトル、位置情報、作成日時を入れた MP4 を変換し、出力に残るのが作成日時(変換した時刻)だけであることを ffprobe で確かめた。

読み込んだ動画は、必要な部分だけをファイルから読む。困るのは書き出す側である。報告のあった 35 分の動画を 1280 × 720、画質「低」、音声 96 kbps で書き出すと、目安は約 467 MB になる。書き出す動画をすべてメモリに溜めてからダウンロードさせる方式では、少なくとも出力と同じ大きさのメモリが要り、メモリの少ない端末では途中で止まるおそれがある。

そこでパソコンの Chrome と Edge では、File System Access API の showSaveFilePicker() で保存先を先に選んでもらい、Mediabunny の StreamTarget で変換しながらファイルに書き込む。メモリに溜まるのは、書き込み待ちの数十 MB ほどで済む。目安が 200 MB 以上なら、この方式を選んだ状態から始める。Safari や Firefox のように showSaveFilePicker() が無いブラウザではメモリに作るしかなく、目安が 500 MB 以上なら、途中で止まるおそれがあると画面に出す。

確かめていないこともある。iPhone の実機での変換は、まだ確認していない。Safari 26 の対応は、ここまでに挙げた資料に基づく。Linux で AAC が使えないことと、Windows の Chrome が受け付ける AAC のビットレートも、資料と Chromium のソースに基づくもので、開発者の側では実機で試していない。ファイルへの直接の書き込みは、ヘッドレス Chromium で、保存先を選ぶ画面の代わりにブラウザ内の保存領域(OPFS)のファイルを渡して確かめた。

FFmpeg を持ち込まなかったぶん、ブラウザに無いエンコーダは使えず、ブラウザのエンコーダが受け付けない設定も使えない。受け付けるかどうかは、音声のビットレート一つまで、問い合わせてみるまで分からない。その代わり、ツールが配るのはページと Mediabunny を含む JavaScript で、符号化と復号そのものはブラウザが持つエンコーダとデコーダが行う。どの形式とビットレートを選べるかは、ページを開いた環境で問い合わせた結果として、画面に出る。