[Astro] #178 ブラウザだけで動く動画エディタ — 1.4GB・27分の動画を、アップロードなしで切って書き出す
はじめに
前回は、監視室のモニタ壁で、MSX・動画・SID を動かしました。
[Astro] #177 監視室のモニタ壁で MSX・動画・SID を動かす — Quest 3 の VR で、壁がそのままメニューになる
監視室の GLB の、モニタの壁を使って、MSX のゲーム、MP4 の動画、SID の曲を再生する「モニターモード」を作りました。
lain-lab.com今回は、ブラウザの中だけで動く、動画エディタです。
ブログに貼る動画を、サッと切って、つないで、書き出したい。それだけのために、毎回、重いソフトを開くのが面倒でした。そこで、ブラウザだけで完結する物を作りました。動画のファイルは、サーバーに送られません。
画面は、できるだけシンプルにしています。ふだんは「素材を入れる → 切る → 書き出す」だけで足ります。細かい機能は、右の欄の折りたたみに入れました。困ったときは、F1 キーで、「やりたいこと → やり方」を検索できます。
画面
全体
左に素材と追加ボタン、中央にプレビューとタイムライン、右にクリップの設定、という並び。
1.4 GB の動画を読み込み。
Steamの「Subsistence」の録画動画。
Steamで40% OFF:Subsistence
「Subsistence」は、一人称視点のサンドボックスで、ソロプレイも協力プレイも楽しめる、オープンワールドのPvEサバイバルゲーム。移り変わる季節の中で過酷な環境をサバイバルし、基地を建設してテクノロジーや装備を開発しよう。野生動物や自然の脅威、そしてAIハンター(彼らもこの世界で基地を建設する)から身を守れ。
store.steampowered.com書き出し
用途のプリセットを選んで、「書き出す」を押すだけです。いちばん上の「ブログ用」は、MP4・720p・30fps で、軽くて、どこでも再生できます。
F1 ヘルプ
「ぼかしたい」「縦動画にしたい」のように、やりたいことで探せます。
作ったもの
編集
- 分割、削除、詰めて削除、前後を削除、トリム(端をドラッグ)、複製、コピー、貼り付け
- クリップの種類は、動画、音声、画像、文字、字幕、色の背景、図形、ぼかし/モザイクです
- トラックは、文字、字幕、V2、V1、A1、A2 です。ロック、非表示、ミュートができます
- 映像と音声は、リンクで連動します。Alt を押しながら操作すると、片方だけ動かせます
- 位置、大きさ、回転、不透明度、反転、切り抜き、フィルタ、クロマキー、ズームや移動の動き
- 切り替えは、フェード、ワイプ、スライド、ズーム、ぼかし、回転です
- 速度は 0.25 倍から 8 倍まで。音の高さも変わります
- 音声は、音量、フェード、ノーマライズ、無音カットなどです
- 字幕は、一覧で編集できて、SRT と VTT の読み込みと書き出しに対応しています
- 画面録画、カメラ、マイクの録音もできます
書き出し
| 種類 | 内容 |
|---|---|
| 再エンコード | MP4 / WebM / MKV / MOV。使えるコーデックに自動で切り替えます |
| 無劣化カット | 再エンコードせずに、切るだけ。速くて、画質が落ちません |
| 音声のみ | M4A / WAV / OGG |
| GIF | 自前のエンコーダで作ります |
| 静止画・字幕 | その瞬間を PNG / JPG、字幕を SRT / VTT |
Chrome と Edge では、保存先を選ぶと、ファイルへ直接書き込みます。それ以外のブラウザでは、メモリの上で作ってから、ダウンロードします。
自動保存
編集内容は、ブラウザの IndexedDB に自動で保存されます。ページを読み込み直すと、「続きから再開」と出ます。動画のファイルそのものは保存しません。素材が見つからないときは、同じファイルを入れ直すと、自動でつながります。
作り方
ライブラリは Mediabunny
最初に、ffmpeg.wasm か、WebCodecs を使うか、で迷いました。
ffmpeg.wasm は、できることが多いのですが、1GB を超える動画では、メモリが厳しくなります。動きも重いです。
そこで、WebCodecs を使う、Mediabunny を選びました。ブラウザのデコーダとエンコーダを、そのまま使えます。動画の Blob から、必要な部分だけを読めるので、大きなファイルでも、全部をメモリに載せずに済みます。
代わりに、できることは、ブラウザの WebCodecs が対応しているコーデックまでです。H.264 や AAC が使えるかは、環境によって違います。使えないときは、VP9 や Opus などに、自動で切り替えて、結果の画面に注意を出します。
Mediabunny は、CDN を使わず、自分のサイトに置いて読み込んでいます。
1 つの描画関数
プレビューも、書き出しも、GIF も、同じ 1 つの関数で、1 フレームを描いています。2D キャンバスに、下のトラックから順番に重ねていきます。変形、切り抜き、フィルタ、切り替え、文字などが、全部この中です。
こうしておくと、プレビューで見た絵と、書き出した絵が、同じになります。
音
プレビューの再生は、AudioContext の時計を、マスターにしています。映像の側が、その時計に合わせます。
書き出しの音は、OfflineAudioContext で、5 秒ずつ作ります。音量、フェード、エフェクトの部分は、プレビューと書き出しで、同じ処理を使っています。
重なったときの扱い
クリップを同じトラックに落として、重なったときは、間に挿入して、後ろを右へ押し出します。Alt を押しながら落とすと、そのまま重ねられます。文字、字幕、図形、ぼかしは、最初から、自由に重ねられます。
無劣化カット
素材が 1 本で、拡大縮小もフィルタも文字も使っていないときだけ、再エンコードをせずに、パケットをそのままコピーします。切れ目は、直前のキーフレームに合います。
実機で確認できたこと
- 1.4GB・約 25 分の動画の読み込みは、問題ありませんでした
- 27 分 18 秒の動画を、「ブログ用」で、そのまま書き出して、94.8 秒で終わりました。約 17 倍の速さです。結果は、AVC + AAC の 430.9MB で、書き出し前の目安(424.9MB)とほぼ同じでした
- タスクマネージャーでは、GPU の Video Decode と Video Encode が動いていました。エンコーダは、ブラウザが自動で選んだ物です
- 日本語のファイル名で、保存できました
- ページを読み込み直したあとの、自動保存からの復元が、動きました
- 切って、つないだ動画の書き出しも、動きました
環境は、Windows 11、Chrome、Core i7-12700K、RTX 4070 Ti です。
詰まったこと
書き出しで、fastStart のエラー
最初の実機チェックで、書き出しが失敗しました。
options.fastStart, when provided, must be false, "in-memory", or "fragmented".
MP4 は、ふつう、再生に必要な情報が、ファイルの最後に入ります。ブログに貼る用途だと、先頭に置いたほうが、再生が早く始まります。そこで、ファイルへ直接書き込むときは、fastStart: 'reserve'(先頭に場所を確保しておく方式)を使っていました。
ところが、実機で読み込まれた mediabunny.min.mjs が、'reserve' に対応していない、古い版でした。私の環境では、新しい版を使っていたので、気づけませんでした。
直し方は、次のとおりです。
- 起動時に、
new Mp4OutputFormat({ fastStart: 'reserve' })が通るか、試す - 通らなければ、
'in-memory'に切り替える
古い版でも、書き出しは、できるようになりました。ただ、大きなファイルでは、メモリを多く使います。
日本語のファイル名で、テスト環境が落ちた
自分の環境の検証では、「無題.mp4」のような、日本語のファイル名を保存先に渡すと、ブラウザごと落ちることがありました。ただ、これは、古い Chromium を使った、テスト環境の問題でした。実機の Chrome では、日本語のファイル名でも、問題なく保存できました。
見た目のバグ
右の欄の「時間」に、[object HTMLDivElement] と出ていました。配列の中に、さらに配列を入れていたことが原因でした。F1 の検索欄が、右にはみ出していたのも、直しました。
未確認のこと・制限
- 字幕と文字の、実機での確認は、これからです。 ヘッドレスブラウザ(画面なしのテスト環境)では、書き出した画像に、文字と字幕が焼き込まれることを、確認しています
- M4A の書き出しと、無劣化カットは、実機で試していません。
- Safari と Firefox では、確かめていません。Safari は、フィルタが、プレビューに出ません
- 画面録画は、本物の画面では、試していません
- 速度を変えると、音の高さも変わります。音の高さを保ったまま、速度を変えることはできません
- 速度を変えたあとの隙間は、自動では詰まりません。右クリックの「隙間を詰める」で詰めます
- MP3 の書き出しは、ありません
- 無劣化カットは、切れ目が、キーフレームの単位になります
おわりに
「シンプルだけど、多機能」という、矛盾したお願いから始めました。ふだんの画面は、素材を入れて、切って、書き出すだけにして、そのほかの機能は、折りたたみと、F1 のヘルプに入れました。あとから機能を足したくなったときに、困らないようにするためです。
1.4GB の動画を、そのまま、アップロードなしで、1 分半ほどで書き出せたのは、うれしい誤算でした。
今は、v1 です。動かしながら、バグを見つけて、直していきます。