Sジブンノート

Tauri でつくる自分用 VLog アプリ開発記

最近、Mac 向けに画面と自分の姿を同時に記録する VLog アプリを Tauri で作りました。 開発の背景やつまずき、乗り越えた工夫を振り返ります。 ソースコードと署名なしの .dmg は GitHub に置いています。

https://github.com/silverbirder/vlog

アプリの雰囲気が伝わるように、スクリーンショットを 2 枚載せておきます。

VLog アプリのホーム画面
タップして拡大
VLog アプリのホーム画面

起動直後のホーム画面です。保存先や自動停止時間などをここで設定できます。

録画中の VLog アプリと PiP 表示
タップして拡大
録画中の VLog アプリと PiP 表示

録画中はこのように ピクチャ・イン・ピクチャ (PiP) でカメラ映像を前面に固定しながら、画面全体をキャプチャします。

背景

YouTube や TikTok を見て、日常を短い動画で残す VLog 文化があることを知りました。 私は自分で書いたブログ記事を読み返したり、自分が歩いた記録が残る Google マップのタイムラインや撮りためた Google フォトのアルバムを眺めたりして、過去を振り返る時間が好きです。 「動画でも記録しておけたら面白そうだな」と思ったのが、今回の起点でした。

日々の大半は自宅で過ごし、パソコン作業の時間が長いです。 それなら Mac の画面と自分の姿を同時に録画できるデスクトップアプリを自作しよう と決めました。

技術選定の迷いと Tauri 採用

当初は経験のある Electron を使うつもりでした。 しかし、公式の React テンプレートが無かったり、Electron Fiddle がうまく動かなかったり、npm install electron が通らなかったりと、序盤からストレスが溜まり始めました。 過去にも同じような壁に当たった記憶があったので、Electron で進む気持ちは一気にしぼみました。

そこで思い出したのが、以前にメジャーアップデートのニュースで見かけた Tauri です。 モバイル対応は検討していませんでしたが、デスクトップアプリを作れるし、React テンプレートも整備されています。 クイックスタートをなぞるだけで数分後には開発環境が整い、.dmg ビルドまで一気に到達できました。 「これなら作り切れそうだ」と実感し、Tauri 採用を決めました。

動画保存まわりの試行錯誤

録画には Web API の MediaDevices.getDisplayMedia()MediaDevices.getUserMedia() を使いました。 getDisplayMedia が画面キャプチャ、getUserMedia がカメラ映像の取得を担当します。

最初は、取得した映像チャンクをフロントエンドで蓄積し、録画停止時にまとめて Rust 側へ送る構成を採用しました。 保存するのはスクリーン録画 (mp4)、カメラ映像 (mp4)、マイク音声 (m4a) の 3 ファイルです。 AI Agent に下書きしてもらったコードがそのまま動いたので、早速録画してみました。 ところが、完成した動画は冒頭の数分だけが動き、その後は静止画になっていました。 チャンク処理をフロントエンドで抱えきれず、途中で詰まってしまったようです。

次に、Rust 側で直接キャプチャする方法を調査しました。 ただしネイティブ API に踏み込む必要があり、理解コストが高そうだったので見送りました。

そこで フロントエンドでチャンクを保持せず、取得したデータを即座に Rust 側へ送り、ファイルに追記する 方式へ切り替えました。 結果として、録画が途中で止まる問題は解消され、停止ボタンを押すだけで保存が完了するようになりました。

欲しかった機能を揃える

使い続けるうちに、次のような要望が浮かびました。

  • 一定時間で自動停止したい
    • ずっと録画し続けるのではなく、15 分や 30 分で区切りたい
  • 停止に気づける通知が欲しい
    • 集中していると録画状態を忘れるので、自動停止時に気づきたい
  • カメラやマイクを切り替えたい
    • 外付けデバイスを接続したときに選択したい
  • 停止後にすぐ再開したい
    • 録画停止と開始を繰り返す操作を簡単にしたい

これらを一つずつ実装し、特に使っていなかったマイク録音は機能ごと削除しました。 余計な設定が消えて、アプリ全体の使い心地が軽くなった感覚があります。

PiP をどう実現したか

スクリーンとカメラを別々に保存していると、見返すときに視線が忙しく感じました。 そこで PiP のような、スクリーン上にカメラの映像を重ねて録画する方法を探りました。

まずはフロントエンドでスクリーンとカメラの映像を合成し、単一の動画として保存する方式を試しました。 ところが処理が重く、FPS が落ちてカクつきが目立ったため断念しました。 次に、録画後に ffmpeg で合成する案も検討しましたが、15 分の動画でも処理時間が長く、運用したい気持ちになれませんでした。

最終的にたどり着いたのは、録画中にカメラ映像を常に前面表示し、そのままスクリーン録画に写し込む というシンプルな方法です。 リアルタイム合成も後処理も不要で、狙い通りの PiP 動画が撮れるようになりました。 唯一の課題は、VS Code などをフルスクリーン表示すると PiP ウィンドウを最前面に固定できないことです。 今はフルスクリーンを控えることで運用しています。

おわりに

React の “Learn Once, Write Anywhere” というスローガンがありますが、Tauri でも同じ感覚でデスクトップアプリを作れたのが嬉しいポイントでした。 今回は Rust 側の実装を最小限に抑え、フロントエンドの改善に注力したことで、迷子にならずにリリースまでたどり着けました。

Tauri はデスクトップやモバイル、Web までを React の知識でカバーできる仕組みがすでに整っています。 ひと昔前なら Electron と React Native、さらに React Native for Web を組み合わせていた場面が、一つの選択肢にまとまるイメージです。 今後も Tauri を使って、日常を記録するためのツールを少しずつ育てていきたいと思います。