推しエール
概要
アンケートに答えるだけで自分だけの推しキャラを生成し、PC作業中の疲労をキーボードの打鍵リズムだけから
検知するアプリ。ブラウザを閉じていてもバックグラウンドでPC全体を見守り続け、疲れを検知すると生成した
推しからデスクトップ通知でエールが届く。
役割分担
2チームに分かれて並行開発。
- 推し生成チーム:アンケートUI・キャラクター説明文/シルエット生成・画像生成API連携(FastAPI)
- 疲労推定チーム:打鍵リズムからの疲労検知エンジン・OSレベルのキーボードフック(Node.js)
2つの機能は共有JSONファイル経由で疎結合に連携している。
プロダクトのフロー
アンケート回答
↓
推しキャラ生成(説明文・シルエット/任意で実画像生成)
↓
「この推しに見守ってもらう」ボタン
↓
バックグラウンド疲労監視プロセスを起動(PC全体のキー入力の時刻のみを監視)
↓
見守り中 ⇄(打鍵ペースの乱れを検知)
↓
疲労検知 → 推しからデスクトップ通知でエール → 15分クールダウン → 見守り再開
使用技術
- フロントエンド:素のHTML / CSS / JavaScript(フレームワークなし)
- バックエンド:FastAPI(Python)+ Uvicorn + Jinja2
- 疲労推定エンジン:Node.js + uiohook-napi(OSレベルのグローバルキーボードフック)
- デスクトップ通知:node-notifier
- 画像生成(任意):Stable Diffusion XL(Stability AI API、APIキー未設定でも動作)
- データ永続化:JSONファイル(DB不使用)
- 動作確認環境:Windows
現在できている機能
- 存在の種類・雰囲気・色(最大3色)・役割を選択すると、リアルタイムに変化するシルエットプレビュー
- 選択内容から説明文と画像生成プロンプトを自動生成。画像生成APIキー未設定でも最後まで完結する設計
- STABILITY_API_KEYを設定すれば実画像も生成可能
- 生成した推しプロフィール(名前・アバター・トーン)をサーバーに保存し、疲労監視プロセスと共有
- Web UIのボタン一つでバックグラウンド疲労監視プロセスを起動/停止
- PC全体のキー入力(時刻のみ、内容は記録しない)から、個人ごとに自動キャリブレーションした統計モデルで
疲労を検知
- 疲労検知時にOSのデスクトップ通知でエール。メッセージは推しのトーン(元気系/落ち着き系/甘えさせ系/熱血系)
と疲労度に応じてテンプレートから選択(オフライン・APIキー不要)
- 実画像を生成していれば、その画像を通知アイコンとしても使用
- 検知後15分のクールダウンで連続通知を防止
- Web UI上に現在の疲労度・監視状態(見守り中/ひと休み中)をリアルタイムのゲージバーで表示
- サーバー終了時に疲労監視プロセスが孤児化しないようクリーンアップ
こだわりポイント
- 教師データなしで疲労を検知する設計:疲労ラベル付きの人間データは存在しないため、使い始めの打鍵ペースを
そのユーザー本人の「元気な状態」として自動キャリブレーションし、そこからの統計的な逸脱(マハラノビス
距離)を疲労スコアにした
- 統計モデルの正則化を弱くしすぎると、平常時のわずかなペースのゆらぎにも常に誤検知してしまうバグが
実際に発生。シミュレーションで誤検知0件になる値まで調整した
- プライバシー設計を後付けの注意書きではなく、データ構造そのものに組み込んだ:扱うのはKeyDown/KeyUpの
種別とミリ秒タイムスタンプのみで、どのキーが押されたかを持てる余地がない
- 画像生成APIの呼び出し回数を最小限にする設計:画像生成前にまず説明文とシルエットで確認でき、APIキーが
無い/失敗してもアプリ全体のフローが止まらない
- Python(FastAPI)とNode.jsという別々の言語・プロセスをまたいで動くシステムを、共有JSONファイル経由の
軽量な連携でつないだ。Web UIのボタンからNode.jsの疲労監視プロセスをサブプロセスとして起動・停止できる
詰まった点
- サーバー(FastAPI)からNode.jsの疲労監視を子プロセスとして起動できるようにしたが、サーバーを再起動する
と子プロセスが孤児化し、キーボードフックを持ったまま動き続けてしまうバグが実際に発生した。動作確認中に
実機で複数の孤児プロセスが残っているのを発見し、サーバー終了時に確実に子プロセスを停止する処理を
追加して解消した
- Pythonの仮想環境(venv)をフォルダごと移動した際、pipが生成した起動用exe(uvicorn.exe等)が古い場所の
Pythonパスを埋め込んだまま残り、「Fatal error in launcher」で起動できなくなった。venvを作り直して解消
- ブラウザの自動テストで日本語テキストを入力すると、実際のキー押下/離上イベントではなくテキスト挿入として
扱われてしまい、キー入力のタイミングを見る疲労検知エンジンが全く反応しない事象があった。ASCII文字で
入力し直し、実際の打鍵イベント経由で正しく動作していることを確認した
- 疲労検知エンジンはPC全体のOSレベルのキーボードフックを使うため、ブラウザの自動操作では実際の疲労度を
動かすテストができない。状態ファイルを直接書き換えることで、疲労度ゲージの表示部分だけを切り分けて検証した
今後の展望
- 生成履歴の保存・一覧表示
- 生成画像の保存・管理
- UIのデザインの作り込み
- macOS/Linux環境での動作確認(現状Windows想定)
- 疲労度に応じた癒し提案(ストレッチ・音楽など)の実装