PixiJSのパフォーマンス問題とRustへの書き換えによる解決
Mac用の画面レコーダー「TinyRec」の開発において、PixiJSを使用したエディタプレビューの処理が原因でエクスポート処理が非常に遅い(720pの5分間の動画で15分かかった)という問題が発生しました。
この問題を解決するため、エクスポートパイプラインをRustで書き直し、Electronアプリから別途Rustプロセスを起動して処理を行うように変更しました。
これにより、Metalコンポジター、ハードウェアエンコーダー、MuxerをRustプロセス内で実行し、CPUへのデータ転送を削減することで、処理時間を大幅に短縮(5分間の720p動画で1分に短縮)しました。
また、UIの応答性向上も実現し、進捗バーの表示や編集作業の継続を可能にしました。
Macの画面録画アプリ「TinyRec」の開発者が、動画のエクスポート処理が極端に遅いという課題に直面しました。従来のJavaScript(JS)ベースのパイプラインでは、5分間の720p動画の書き出しに15分もかかってしまう状況でした。この問題を解決するため、開発者は処理全体をRust言語で再構築したパイプラインを導入したと発表しました。
JSパイプラインのボトルネック構造
従来のTinyRecは、ElectronフレームワークとPixiJS(UIのプレビュー表示に使用)を標準スタックとして採用していました。この構成では、動画のデコード、PixiJSによる合成(クロップ、ズーム、アノテーションなど)、そしてエンコードという一連の処理がすべてメインスレッドで実行されていました。結果として、各フレームの合成処理がJSの実行を60〜120ミリ秒停止させてしまい、UIがフリーズし、処理速度が極端に低下するという問題が発生していました。ボトルネックはエンコーダーではなく、メインスレッドに縛られていたコンポジター(合成処理)にあったと分析されています。
Rustによる処理の分離と高速化
開発者は、エクスポート処理全体をElectronアプリから独立したRustバイナリとして分離しました。このRustプロセス内で、ffmpeg-sys-nextによるソースのデコード、Metalコンポジターによる合成、そしてh264_videotoolboxによるハードウェアエンコードが実行されます。特に重要なのは、GPUのピクセルバッファ(IOSurface)をCPUを経由させずに直接VideoToolboxに流し込むことで、フレームごとのデータコピーを完全に排除した点です。これにより、エンコーダー自体の速度向上ではなく、処理のオーバーヘッドが劇的に削減されました。
開発における技術選定の背景
処理をRustで実装した背景には、単なるパフォーマンス追求だけでなく、開発効率と将来的な拡張性も挙げられています。C++やSwiftでも実現可能でしたが、RustはCargoによるビルドの容易さ、単一バイナリでのリリース、そして将来的にLinuxやWindowsといったクロスプラットフォーム展開を容易にできるという利点がありました。また、処理をメインスレッドから分離したことで、たとえ処理時間が変わらなくても、リアルタイムの進捗バー表示やサムネイル表示といったユーザー体験(UX)が大幅に改善されたことも大きな成果だと説明しています。
まとめ
この事例は、単に「速い言語」に置き換えるのではなく、「処理をどこで実行するか」というアーキテクチャ設計がパフォーマンスに決定的な影響を与えることを示しています。TinyRecは、Rustによるパイプライン分離により、5分間の動画書き出し時間を15分から1分へと劇的に短縮することに成功しました。
原文の冒頭を表示(英語・3段落のみ)
← All posts
Nam Tran · May 3, 2026 I’m building a Mac screen recorder called TinyRec. Standard Electron stack — PixiJS for the editor preview, WebCodecs for the export. And it was slow.
A five-minute 720p clip took fifteen minutes to export. Not 4K. Not some pathological case. Plain 720p — the resolution everyone records at. Three times the source duration, just to render it out.
※ 著作権に配慮し、引用は冒頭3段落までです。続きは元記事をご覧ください。