📼

Chrome 拡張機能でタブを録画する際の Tips

2024/06/24に公開

先日、Instant Tab Recorder という Chrome の拡張機能をリリースしました。
その名の通り、Chrome のタブを瞬時に録画することにフォーカスした拡張機能です。

https://chromewebstore.google.com/detail/instant-tab-recorder/giebbnikpnedbdojlghnnegpfbgdecmi

こちらの拡張機能の開発にあたって、Chrome 拡張機能でタブを録画する際の知見が得られたのでまとめます。

モチベーション

Google Chrome では Developer Tools にて標準でスクリーンショットの機能が提供されています。
しかし動画を撮影する機能は無いため、OS のスクリーンキャプチャ機能を使うか、拡張機能を導入する必要があります。

OS のスクリーンキャプチャ機能は基本的に画面を録画するので、ブラウザのウィンドウの移動、最小化、写したいタブが他のタブによって隠れてしまうとうまく録画できないという課題があります。
特定のタブのみを録画したく、他のウィンドウやタブの裏に隠れても、最小化されたとしても録画を継続するためにはブラウザ側で実行する必要があります。

Chrome の拡張機能[1]はというと、豊富な機能が提供されているものの1クリックで録画開始できないもの、10分以上録画を続けると終了時に処理が終わらず動画データが得られないもの、といった具合で使い勝手に難がありました。

それなら自分で作ろうと手を動かし始めたのが先月初頭、なんやかんやあって気付いたらリリースまでに1ヶ月以上を要してしまいました。

Tips

Offscreen Documents

Chrome 116 以降では stream id を Offscreen Documents に渡して、バックグラウンドで録画することができます。
この機能を用いると、アクションボタンのクリックをトリガーとして、ユーザーに選択や許可を求めることなく即座にタブの録画を行うことができます。

録画を行っているのは offscreen document なので、誤って閉じてしまい録画が停止するリスクがありません。録画対象のタブについては、閉じることさえしなければページ遷移しても録画は継続されます。

https://developer.chrome.com/docs/extensions/how-to/web-platform/screen-capture?hl=ja#user-gesture

親切にサンプルコードも提供されており、かなり参考になりました。

Origin Private File System

巷の拡張機能は MediaRecorder で記録された動画データを一時的にメモリに保持しているようで、長尺の録画には向きません。
また、録画中にプログラムがクラッシュするなど予期せぬ問題が起きたときに録画データが揮発する問題があります。

そこで思いつく対策としては、メモリではなく永続化されたストレージに逐次書き出すことです。
しかしながら、ブラウザから自由に OS のファイルシステムにアクセスできては危険なので、都度ユーザーに許可を求めるように設計されています。

これでは、録画したいと思った瞬間にディレクトリピッカーが表示されて、保存先のディレクトリを指定する必要があり手軽ではありません。他の拡張機能が行っているハックとして、事前にユーザーにディレクトリを選ばせておきハンドルを開いたままのタブでメモリ上に保持し、録画時に参照することで都度選ばせる手間を回避するというものがありますが、中々苦しい対応だと思います。

そこで利用できるのが Origin Private File System (OPFS) です。特別な権限を必要とせず、基本的に自由に読み書きできる Origin 事に独立したファイルシステムが提供されます。

OPFS を利用することで、ユーザーに許可を求めることなく動画データを書き込んで永続化できます。拡張機能上で書き込み、参照する上では OPFS 上で完結します。ただし OPFS はブラウザ外から容易に参照できないので、FFmpeg 等他のツールで動画データを扱いたい場合に不便です。そこで、外部にエクスポートする時だけ都度ユーザーに許可を求めてファイルシステムの任意のディレクトリに書き出せるように実装しました。

MediaRecorder

MediaRecorder が突然停止することがあります。
1時間以上録画し続けた場合に停止することが多いように感じます。

このケースでは MediaRecorder は停止していても MediaStream は停止していない事に気付きました。
MediaRecorder の stop イベントのハンドリングの中で、MediaStream が active であれば MediaRecorder を再開するよう対応しました。

https://github.com/ww24/chrome-tab-recorder/blob/v1.0.0/src/offscreen.ts#L98-L102

WebM duration 問題

MediaRecorder が生成する動画データ (WebM) のメタデータには duration が含まれていません。
そのため、シークが効かず録画データが長尺になった際には大変不便です。

詳細はこちらの記事が参考になります。
https://qiita.com/legokichi/items/83871e1f034331222fd2

WebM のデータを読み込んで duration を算出し、メタデータを更新する必要があります。
EBML を解析して修正する処理には ts-ebml を使わせていただきました。
https://github.com/legokichi/ts-ebml

他にも類似のツールはありますが、最後に一括して duration の修正処理を行うと重たいので逐次読み込ませた方が効率が良いです。ts-ebml はそのようなインターフェースが提供されているので MediaRecorder との相性が良い点が採用の決め手となりました。

※ ts-ebml は MediaRecorderWebMDurationWorkaround class の中で利用しています。
https://github.com/ww24/chrome-tab-recorder/blob/v1.0.0/src/offscreen.ts#L82-L91
https://github.com/ww24/chrome-tab-recorder/blob/v1.0.0/src/offscreen.ts#L119-L137

こちらの問題に関しては github.com/w3c/mediacapture-record に2017年に Issue が作成されていますが、未だに解決されていないようです… 😢

https://github.com/w3c/mediacapture-record/issues/119

まとめ

  • Offscreen Documents を利用するとバックグラウンドで録画できる
  • 永続的なストレージを利用したい時は Origin Private File System を検討する
  • MediaRecorder の突然の停止に備える
  • MediaRecorder で記録された WebM 動画データには duration が含まれないので、メタデータを修正する

似たような拡張機能は既に存在するので車輪の再発明感はありますが、Web フロントは専門外なので久々に Chrome 拡張機能を作成して多くの学びと刺激がありました。
(余裕ができたら OSS として開発されている既存の拡張機能にコントリビュートしてみます)

脚注
  1. セキュリティとプライバシーの観点から、ソースコードが公開されている拡張機能のみを対象としています ↩︎

Discussion