MnemoVR は、PC に保存された VRChat の写真(VRChat_*.png)を自動で読み込み、カレンダー・ワールド・お気に入りなどの切り口で振り返れるデスクトップアプリです。写真に記録された情報からワールド名や撮影日時を読み取り、訪れた場所ごとに思い出を整理します。
さらに Discord ログインすると、「いまコミュニティで多く写真に撮られているワールド」のランキングを閲覧でき、自分の記録もその集計に加わります。次に行く撮影スポット探しに使えます(ログインせずゲストとして写真管理だけ使うことも可能です)。
- 自動取り込み: 起動するだけで、新しく撮った写真をまとめて取り込み
- 撮影情報の表示: 写真に記録されたワールド名・撮影日時を自動で読み取り、どこで・いつ撮ったかを一覧で確認
- VRChat 用 URL を即発行: 写真をアップロードして VRChat 内でそのまま使える画像 URL をその場で生成
- お気に入り登録: 気に入った写真にワンクリックでフラグを立て、専用ビューでまとめて確認
![]() |
![]() |
| ビュー | 内容 |
|---|---|
| 📅 カレンダー | 月別・年別に写真を一覧 |
| 🌐 ワールド | 訪れたワールドごとに写真をまとめて表示 |
![]() |
![]() |
「どのワールドが、いま多くの人に写真に撮られているか」を利用者全体で集計して表示します。VRChat の人気・話題の撮影スポットを見つけるのに使えます。
- 3 つの期間: デイリー / ウィークリー / 歴代(All-time)
- スコア: そのワールドで写真を撮った人数(多いほど上位)
- 一覧の行をクリックすると VRChat のワールドページを開けます
- 利用には Discord ログインが必要。ランキングの集計のためにサーバーへ送られるのはワールド単位の数値(ワールドID・日付・枚数)だけで、写真そのものは送信されません
- ゲストモードでも、ランキング以外の機能はすべて利用できます
最新版は Releases からダウンロードできます。
- インストーラを実行して MnemoVR を起動
- 初回起動時に 利用規約に同意
- Discord ログイン(ランキング機能を使う)か ゲスト(写真管理のみ)を選択
- 既定の写真フォルダ(
ピクチャ\VRChat)が自動で読み込まれ、カレンダー / ワールド / お気に入りから写真を振り返れます。別の場所に保存している場合は設定画面でフォルダを指定できます
VRChat 写真整理デスクトップアプリ(Tauri + React + Rust)と、ランキング同期用の Cloudflare Workers API を同一リポジトリで管理しています。
- クライアント: ローカル写真スキャン・整理、カレンダー/ワールド/お気に入り/ランキング表示、Discord OAuth ログイン
- サーバー: 同期 API、ランキング API、Discord トークン検証と JWT 発行
- 同期: HMAC 署名 + JWT で保護し、ワールド単位の集計ログを送信
| レイヤー | 使用技術 |
|---|---|
| Desktop | Tauri v2 |
| Frontend | React 19, TypeScript, Vite, Tailwind CSS, Zustand, React Router |
| Local backend | Rust, rusqlite (SQLite), tokio, notify, image, quick-xml |
| Server | Cloudflare Workers, Hono, D1 |
MnemoVR/
├── client/ # Tauri デスクトップアプリ
│ ├── src/ # React フロントエンド
│ │ ├── components/ # 共通コンポーネント
│ │ ├── views/ # 各ページ
│ │ ├── store/ # Zustand ストア
│ │ ├── lib/ # ユーティリティ・文字列定義
│ │ └── api/ # Tauri invoke ラッパー
│ ├── src-tauri/ # Rust バックエンド
│ └── package.json
├── server/ # Cloudflare Workers API
│ ├── src/
│ │ └── routes/ # auth / sync / rankings / version
│ ├── schema.sql
│ ├── wrangler.toml
│ └── package.json
└── README.md
- Node.js 20+
- Rust stable
- Tauri 実行に必要な OS 依存パッケージ
cd client
cp .env.example .env
npm install
npm run tauri devclient/.env の主な変数:
| 変数 | 説明 |
|---|---|
HMAC_SECRET |
サーバーとの共有署名シークレット |
SYNC_API_URL |
同期 API のエンドポイント |
VITE_SYNC_API_URL |
フロントエンド用同期 API URL |
DISCORD_CLIENT_ID |
Discord OAuth アプリの Client ID |
cd server
cp .dev.vars.example .dev.vars
npm install
npm run devserver/.dev.vars の主な変数:
| 変数 | 説明 |
|---|---|
HMAC_SECRET |
クライアントとの共有署名シークレット |
JWT_SECRET |
JWT 署名シークレット |
DISCORD_CLIENT_ID |
Discord OAuth アプリの Client ID |
ローカル:
cd server
wrangler d1 execute mnemovr-db --local --file=schema.sql本番:
cd server
wrangler d1 execute mnemovr-db --file=schema.sqlusers.is_banned を既存 DB に追加済みでない場合は一度だけ実行:
wrangler d1 execute mnemovr-db --command "ALTER TABLE users ADD COLUMN is_banned INTEGER DEFAULT 0"- 受け取り:
{ access_token } - 処理: Discord
/users/@meで検証し、usersに UPSERT、JWT を返却
- ヘッダ:
X-Signature(HMAC-SHA256),Authorization: Bearer <jwt> - ボディ:
{
"logs": [
{
"world_id": "wrld_xxx",
"last_visited_date": "2026-03-25",
"photo_count": 12
}
]
}- BAN ユーザーは 403、
world_id + user_idで UPSERT
- 返却:
daily,weekly,all_time - スコア:
COUNT(DISTINCT user_id) - ワールド名:
worldsテーブルを 3 日 TTL でキャッシュ
- 最新リリースバージョンを返却(クライアントのアップデート確認用)
| テーブル | 内容 |
|---|---|
photos |
写真メタデータ (パス, ワールド名, 撮影日時, お気に入りフラグ等) |
settings |
設定キー値ストア |
image_url_cache |
アップロード済み画像 URL キャッシュ (3 日 TTL) |
| テーブル | 内容 |
|---|---|
users |
OAuth ユーザー (is_banned あり) |
world_visits |
ユーザー x ワールドの訪問集計 |
worlds |
ワールド名キャッシュ |
| 種別 | 場所 | 内容 |
|---|---|---|
| フロントメモリ | React state | サムネイル URL (thumbCache) |
| ローカルファイル | thumbnails/ ディレクトリ |
サムネイル JPEG |
| ローカル DB | image_url_cache |
アップロード済み画像 URL (3 日 TTL) |
| サーバー DB | worlds.updated_at |
ワールド名 (3 日 TTL) |
設定画面の「サムネイル・アップロードURLキャッシュの削除」でサムネイルファイルと image_url_cache を同時に削除できます。
cd client
npm run dev # Vite 開発サーバー単体起動
npm run tauri dev # Tauri + Vite 同時起動
npm run build # フロントエンドビルド
npm run tauri build # デスクトップアプリビルド
npm run lint # ESLintcd server
npm run dev # ローカル Workers 起動
npm run deploy # 本番デプロイ
npm run db:migrate # D1 マイグレーション実行MIT License © 2026 SmiSANN




