VoiceBookLM
このドキュメントは、AIを活用したボイスメモアプリケーションの設計と仕様についてまとめたものです。
概要
このボイスメモアプリは、音声を録音し、その内容を自動で文字起こし・要約することで、情報の記録と整理を効率化することを目的としています。会議の議事録、アイデアのメモ、日々のタスク管理など、様々なシーンでご活用いただけます。
Web版
公開URL: https://voicenotelm.app
リリース期間: 2026年1月28日 〜 2月中旬
※ iOS / Android版のリリース予定はありません。
主な機能
本アプリケーションが提供する主な機能は以下の通りです。
- 音声録音: 簡単な操作でボイスメモを録音します。
- 自動文字起こし: 録音された音声を高精度なAIがテキストに変換します。
- 自動要約: 文字起こしされたテキストをAIが解析し、簡潔な要約を生成します。
- タグ付け・自動振り分け: メモの内容に応じて自動でタグを付け、ジャンルごとに整理します。
- 検索・閲覧: 過去のメモをキーワードで簡単に検索し、内容をすぐに確認できます。
リポジトリ
- フロントエンド: voicebooklm-frontend
- バックエンド: voicebooklm-backend
製品要件定義書(PRD)
| 項目 | 内容 |
|---|---|
| プロジェクト名 | 思考崩壊防止型AI音声メモアプリ |
| バージョン | 1.1 (Draft) |
| 作成日 | 2025-12-15 |
| ステータス | 企画・要件定義 |
1. 製品概要(Product Overview)
本アプリは、ユーザーが思いついた考えやアイデアを音声で話すだけで、 AIが内容を整理し、「読み返しても分かるメモ」に整形する思考整理特化型音声メモアプリである。
解決する主な課題
- 書いている途中で思考が迷子になる
- 文章化が難しい
- 後で読み返した際に意味がわからない
2. 背景・課題(Background / Problem Statement)
ユーザーがメモを残す際に直面している問題は以下の通り。
2.1 書いている途中で迷走する
- 頭の中では整理できているが、文章にすると論点がズレる
- 文脈が散乱して一貫性が失われる
2.2 アイデアの文章化が難しい
- 語彙が出てこない
- どこから書き始めればよいか分からない
- 文章構成が難しく、勢いが途切れる
2.3 読み返した時に意味が分からない
- 説明不足
- 断片的で文脈が繋がらない
- 当初の意図を思い出せない
結論: 「メモしたのに役に立たない」「思考整理に活かせない」という問題が根本に存在する。
3. このアプリが提供する価値(Value Proposition)
- 思考維持:書く途中で思考が崩壊する問題を防ぐ
- 文章化代行:AIが文章化の苦手を代替し、整ったメモに変換
- 自動整理:要点・背景・意図・次アクションまで自動で構造化
- 高再利用性:思考の“本来の形”を保ち、読み返しやすく再利用しやすい
4. 製品目標(Goals)
- G1: 思考崩壊を防ぐ音声入力を提供する
- G2: AIが内容を再構成し、読み返し時の理解を保証する
- G3: 誰でも「分かりやすいメモ」を作れる状態にする
- G4: 思考の勢いを止めない最小ステップUIを実現する
- G5: Markdownで構造化し、二次利用を容易にする
5. ペルソナ(Persona)
Persona 1:アイデアマン・学生
- アイデアは浮かぶが文章整理が苦手
- 思いついた瞬間に声で残したい
- 読み返した際に意味不明になるメモが多い
Persona 2:文章を書くのが苦手な人
- タイピングより話すほうが考えやすい
- 書く途中で文脈が崩壊しがち
- 読み返しやすい整理されたメモが必要
6. ユースケース(Use Cases)
- 通学中:アイデアを録音 → AIが整理しタイトル付きで保存
- 授業・作業中:その場の気づきを音声で記録 → 後で見返して理解できる状態に
- 就寝前:モヤモヤを吐き出す → AIが論点を整理してメモ化
- 代替入力:文章化が苦手な人が声でメモを残す
対象ユースケース(具体的な利用シーン)
| シーン | 説明 |
|---|---|
| 面接の振り返り | 面接直後に歩きながら感想を話し、後で検索 |
| 自己分析ログ | 散歩中に気持ちを話し、タグで思考を整理 |
| アイデア記録 | 浮かんだ瞬間に話すだけで保存 |
7. スコープ(Scope)
In Scope(MVP)
- 音声録音(モバイルアプリ)
- Google Speech-to-Text APIによる高精度文字起こし
- AIによる文字起こし内容整形、構造化
- タイトル自動生成
- 自動ディレクトリ作成、分類(AI)
- 自動タグ付け(AI)
- Markdown形式で保存
- メモ一覧(タイトル+ディレクトリ構造)
- 再要約機能
Out of Scope(MVP外)
- リアルタイム文字起こし
- obsidianのような編集と閲覧が同じような機能
- 意味ベース検索(Semantic Search)
- ニュアンス・文脈で検索可能
- Embeddingによる類似度検索
8. コア機能(Core Features)
8.1 音声 → テキスト変換
- Google Speech-to-Text API
- 言い直し・雑談も保持し高精度で文字化
8.2 AI構造化メモ生成(Markdown)
出力構造:
- タイトル(AI生成)
- タグ(AI生成)
- 本文(LLM整形)
- 作成日時(属性)
Markdownテンプレ例
---
title: "自動生成タイトル"
tags: ["アイデア", "プロジェクトA"]
created: 2025-12-01
---
# タイトル
LLMが整形した本文がここに入る。
ユーザーの音声入力を元に、読みやすく構造化された文章が生成される。
8.3 自動分類
ジャンル例:アイデア / 日記 / 勉強 / 仕事 / 感情 / TODO
8.4 メモ一覧画面
- 日付順 / カテゴリ別ソート
- サマリ表示
8.5 意味ベース検索(Semantic Search)
- 正確なキーワード不要
- ニュアンス検索・文脈検索
- Embedding による類似度検索
9. 非機能要件(NFR)
- 安定性: アプリクラッシュ時でも音声データ保持・復旧
- プライバシー: 音声データは端末内保存を基本とする
(※取り消し線項目は削除し、必要項目のみ残しました)
10. 技術要件(Technical Requirements)
- フロント: React Native
- 文字起こし: Google Speech-to-Text API
- 要約・整形AI: Gemini 2.0 Flash
- データ保存: PostgreSQ ( 必要に応じてAWS S3)
- Markdown生成: フロントエンド側でフォーマット(詳細は未確定)
11. 競合分析(Competitive Analysis)
| 競合サービス | 特徴 | 本アプリの優位性 |
|---|---|---|
| TalkNotes | 会議・制作寄り | 思考整理に特化したテンプレ |
| BrainDump | 音声→Markdown化 | より強力な構造化・分類機能 |
| Echo Notes | ライター向け・高品質文字起こし | 「要約・再構成」を重視 |
| Cleft Notes | 構造化に強いが汎用的 | 思考崩壊防止に特化したUX |
| v2md | Obsidian特化 | 初心者でも使いやすい構造化テンプレ |
差別化ポイント:
- 会議・議論録音ツールは多いが、個人の思考整理に特化したアプリは少ない
- タグやディレクトリ構成をAIが自動で提案・整理
- 「思考の崩壊を防ぐ」「読み返して分かる」出力品質とUX
12. 成果指標(KPI)
- 理解できたメモ率
- 1ユーザーあたりの再閲覧数
- “意味不明メモ”の減少
- 書くストレスの低減
- 月間継続利用率
- 意味検索からのメモ閲覧数
- 探したいメモが見つかった成功率
13. エレベーターピッチ
「書くと途中で迷子になる思考を、AIが整えて“読み返して分かるメモ”に変換する音声メモアプリ。」
プロダクト概要
VoiceBookLM は、音声ファースト × 自動整理 をコンセプトとした AI 搭載ボイスメモアプリケーションです。
コンセプト
「話すだけで、整理されたメモが自動で作られる」
ユーザーは話すことに集中するだけ。AI がタイトル・本文・タグを自動生成し、クラウドに保存します。
解決する課題
graph TD
subgraph 従来のメモアプリ
A[テキスト入力] --> B[タイトル設定]
B --> C[タグ付け]
C --> D[整理・分類]
end
subgraph VoiceBookLM
E[話す] --> F[AI が自動整理]
F --> G[保存完了]
end
style D fill:#f99,stroke:#333
style G fill:#9f9,stroke:#333
| 課題 | VoiceBookLM の解決策 |
|---|---|
| キーボード入力は思考を阻害 | 音声入力で思考の流れを保つ |
| 整理作業がユーザー負担 | AI が自動でタイトル・タグ生成 |
| 会議向けが多い | 個人の思考ログに特化 |
主要機能
MVPに含む機能
- ワンタップ録音 - シンプルな操作で録音開始
- AI 自動整理 - タイトル・本文・タグを自動生成
- マークダウン対応 - 本文はマークダウン形式で記述・編集・表示
- クラウド保存 - どこからでもアクセス可能
- 全文検索 - 過去のメモを素早く発見
- Google 認証 - 安全なログイン
対象ユースケース
| シーン | 説明 |
|---|---|
| 面接の振り返り | 面接直後に歩きながら感想を話し、後で検索 |
| 自己分析ログ | 散歩中に気持ちを話し、タグで思考を整理 |
| アイデア記録 | 浮かんだ瞬間に話すだけで保存 |
目標数値
| 指標 | 目標 |
|---|---|
| 録音→AI整形完了 | 30秒以内 |
| 検索レスポンス | 0.5秒以内 |
| クラウド稼働率 | 99%以上 |
アーキテクチャ
システム全体像
graph TB
subgraph Client["📱 モバイルアプリ"]
RN["React Native + Expo"]
end
subgraph Backend["🖥️ バックエンド"]
API["REST API<br/>Spring Boot"]
DB[(PostgreSQL)]
end
subgraph External["🌐 外部サービス"]
ASR["Google Cloud<br/>Speech-to-Text"]
AI["AI サービス<br/>Claude/GPT"]
OAuth["Google OAuth"]
end
RN -->|HTTPS| API
API --> DB
API --> ASR
API --> AI
RN --> OAuth
API --> OAuth
backend オニオンアーキテクチャ × DDD
バックエンドはオニオンアーキテクチャと**ドメイン駆動設計(DDD)**を採用しています。
graph TB
subgraph Presentation["🎨 Presentation Layer"]
Controller["Controller<br/>REST API"]
end
subgraph UseCase["⚙️ UseCase Layer"]
UC["UseCase<br/>ビジネスロジック"]
end
subgraph Domain["💎 Domain Layer"]
Entity["Entity"]
Repo["Repository<br/>Interface"]
end
subgraph Infrastructure["🔧 Infrastructure Layer"]
JPA["JPA Repository<br/>実装"]
Client["外部API<br/>クライアント"]
end
Controller --> UC
UC --> Entity
UC --> Repo
JPA -.->|implements| Repo
Client --> ASR["Speech-to-Text"]
style Domain fill:#ffd,stroke:#333
レイヤー責務
| レイヤー | 責務 | 依存 |
|---|---|---|
| Domain | エンティティ・ビジネスルール | なし(純粋Kotlin) |
| UseCase | アプリケーション固有ロジック | Domain のみ |
| Presentation | REST API・DTO変換 | UseCase のみ |
| Infrastructure | DB実装・外部API | Domain IF を実装 |
技術スタック
Backend
| カテゴリ | 技術 |
|---|---|
| 言語 | Kotlin 2.0.21 |
| フレームワーク | Spring Boot 3.4.12 |
| ランタイム | JDK 21 LTS |
| データベース | PostgreSQL 16 |
技術的意思決定
アーキテクチャ選定
オニオンアーキテクチャ × DDD 採用理由
graph LR
subgraph オニオンアーキテクチャ
D[Controller] --> E[UseCase]
E --> F[Domain]
G[Infrastructure] -.->|implements| F
end
| 観点 | 採用理由 |
|---|---|
| ドメイン独立性 | ビジネスロジックをフレームワークから隔離 |
| テスタビリティ | Domain/UseCase は純粋Kotlinでテスト可能 |
| 拡張性 | DB変更やCQRS導入に強い構造 |
ボイスメモ ユースケース図
flowchart LR
User((ユーザー))
subgraph VoiceBookLM
Login([Google でログイン])
Record([ボイスメモを録音])
ViewList([メモ一覧を閲覧])
Search([メモを検索])
Edit([タイトル・タグを編集])
end
User --> Login
User --> Record
User --> ViewList
User --> Search
User --> Edit
ユースケース一覧
MVP 機能(実装対象)
| ユースケース | 説明 | アクター |
|---|---|---|
| Google でログインする | Google OAuth で認証し、JWT トークンを取得 | ユーザー |
| ボイスメモを録音する | ワンタップで録音開始・停止 | ユーザー |
| 音声をサーバーに送信する | 録音完了後に REST API 経由で音声ファイルを送信 | システム |
| 文字起こしする | 録音完了後に ASR で一括テキスト化 | システム |
| AI でメモを整理する | タイトル・本文・タグを自動生成 | システム |
| クラウドに保存する | AI 整形済みメモのみを永続化 | システム |
| メモ一覧を閲覧する | 日付ソートでメモを表示 | ユーザー |
| メモを検索する | 全文検索でメモを検索 | ユーザー |
| タグでフィルタする | タグ指定でメモを絞り込み | ユーザー |
| タイトル・タグを編集する | AI 生成結果を手動で修正 | ユーザー |
MVP 対象外
| ユースケース | 理由 |
|---|---|
| 音声を永続保存する | プライバシー重視設計により永久に含まない |
| 要約を生成する | MVP スコープ外 |
| 複数発話者を判定する | 個人メモ特化のため対象外 |
| Apple/メールでログインする | MVP では Google 認証のみ |
| オフラインで録音する | MVP では対象外 |
データポリシー
| データ種別 | 永続保存 | 説明 |
|---|---|---|
| AI 整形済みメモ本文 | ✓ | メモの主内容として保存 |
| タイトル | ✓ | AI 生成または編集結果 |
| タグ | ✓ | AI 生成または編集結果 |
| タイムスタンプ | ✓ | 録音開始/終了の情報 |
| 音声データ | ✗ | 処理完了後に削除 |
| 生文字起こし | ✗ | AI 整形前の生データは破棄 |
ボイスメモ アクティビティ図
メインフロー(録音〜保存)
flowchart TD
Start((開始))
Start --> Login[Google ログイン]
Login --> Home[ホーム画面]
Home --> Record[録音ボタンをタップ]
Record --> Speaking[話す]
Speaking --> Stop[録音停止]
Stop --> Upload[音声ファイル送信]
Upload --> Transcribe[文字起こし]
AI --> Save[クラウドに保存]
Save --> Done((完了))
Transcribe --> AI[AI でタイトル・本文・タグ生成]
メモ閲覧フロー
flowchart TD
Home((ホーム画面))
Home --> Directory[ディレクトリ構造]
Home --> Search[キーワード検索]
Directory --> Detail[メモを選択して閲覧]
Search --> List[メモ一覧を表示]
List --> Detail
フローの説明
録音フロー
- Google ログイン → JWT トークン取得
- 録音ボタンをタップ → 録音開始
- 話す → 音声を端末に一時保存
- 録音停止 → 音声ファイル確定
- 音声ファイル送信 → REST API 経由でサーバーに送信
- 文字起こし → ASR で一括テキスト化
- AI 処理 → タイトル・本文・タグを自動生成
- クラウドに保存 → AI 整形済みメモのみ永続化
メモ閲覧フロー
- 一覧表示: 日付ソートでメモを表示
- 検索: キーワードやタグで絞り込み
- 閲覧: メモを選択して内容を確認
シーケンス図
システムの主要なフローを時系列で図示したシーケンス図です。
1. 音声メモ生成フロー(メインフロー)
アプリのコア機能「音声 → 文字起こし → AI整形 → 保存」の全体フローです。
sequenceDiagram
autonumber
participant App as 📱 Mobile App
participant API as 🖥️ Backend API
participant STT as 🎤 Google Speech-to-Text
participant AI as 🤖 Gemini AI
participant DB as 🗄️ PostgreSQL
Note over App: ユーザーが録音完了
App->>API: POST /api/voice/memos<br/>multipart/form-data<br/>(file, language)
activate API
Note over API: JWT検証
API->>STT: 音声ファイル送信
activate STT
STT-->>API: 文字起こしテキスト
deactivate STT
alt 文字起こし成功
API->>AI: 文字起こしテキスト送信
activate AI
Note over AI: タイトル生成<br/>本文整形<br/>タグ抽出
AI-->>API: 整形結果<br/>(title, content, tags)
deactivate AI
alt AI整形成功
API->>DB: メモ保存
activate DB
DB-->>API: 保存完了
deactivate DB
API-->>App: 201 Created<br/>{memoId, title, content, tags, ...}
else AI整形失敗
Note over API: フォールバック処理<br/>文字起こしテキストをそのまま使用
API->>DB: メモ保存(フォールバック)
DB-->>API: 保存完了
API-->>App: 201 Created<br/>{..., fallback: {formatting: true}}
end
else 文字起こし失敗
API-->>App: 500 Internal Server Error
end
deactivate API
フローの詳細
| ステップ | 処理内容 | 処理時間目安 |
|---|---|---|
| 1 | 音声ファイルアップロード | ファイルサイズ依存 |
| 2-3 | JWT認証 + 文字起こし | 2-10秒 |
| 4-5 | AI整形処理 | 1-3秒 |
| 6-7 | DB保存 | 100ms以下 |
エラーハンドリング
- 文字起こし失敗: 500エラーを返却
- AI整形失敗: フォールバックモードで文字起こしテキストをそのまま保存
- DB保存失敗: 500エラーを返却
2. Google OAuth ログインフロー
Google Sign-In を使用した認証フローです。
sequenceDiagram
autonumber
participant App as 📱 Mobile App
participant Google as 🌐 Google OAuth
participant API as 🖥️ Backend API
participant DB as 🗄️ PostgreSQL
App->>Google: Google Sign-In 開始
activate Google
Note over Google: ユーザー認証<br/>同意画面
Google-->>App: ID Token
deactivate Google
App->>API: POST /api/auth/google<br/>{idToken}
activate API
API->>Google: ID Token 検証<br/>/tokeninfo
activate Google
Google-->>API: Token Info<br/>(sub, email, name, ...)
deactivate Google
alt トークン検証成功
API->>DB: ユーザー検索<br/>(googleSub)
activate DB
alt 既存ユーザー
DB-->>API: User
else 新規ユーザー
API->>DB: ユーザー作成
DB-->>API: User
end
Note over API: JWT生成<br/>・accessToken (1日)<br/>・refreshToken (180日)
API->>DB: RefreshToken 保存
DB-->>API: 保存完了
deactivate DB
API-->>App: 200 OK<br/>{accessToken, refreshToken}
else トークン検証失敗
API-->>App: 401 Unauthorized
end
deactivate API
セキュリティポイント
| 項目 | 内容 |
|---|---|
| ID Token 検証 | Google の /tokeninfo エンドポイントで検証 |
| aud クレーム確認 | クライアントIDとの一致を確認 |
| メール検証確認 | email_verified: true を確認 |
| UUIDv7 使用 | 時系列順でソート可能なID |
3. トークンリフレッシュフロー
アクセストークン更新時のトークンローテーションフローです。
sequenceDiagram
autonumber
participant App as 📱 Mobile App
participant API as 🖥️ Backend API
participant DB as 🗄️ PostgreSQL
Note over App: accessToken 期限切れ検知
App->>API: POST /api/auth/refresh<br/>{refreshToken}
activate API
API->>DB: RefreshToken 検証<br/>(token, revoked=false, expires > now)
activate DB
DB-->>API: RefreshToken (valid/invalid)
deactivate DB
alt トークン有効
API->>DB: ユーザー取得
activate DB
DB-->>API: User
deactivate DB
API->>DB: 旧 RefreshToken 無効化<br/>(revoked = true)
activate DB
DB-->>API: 更新完了
deactivate DB
Note over API: 新規JWT生成<br/>・accessToken<br/>・refreshToken
API->>DB: 新 RefreshToken 保存
activate DB
DB-->>API: 保存完了
deactivate DB
API-->>App: 200 OK<br/>{accessToken, refreshToken}
else トークン無効/期限切れ
API-->>App: 401 Unauthorized
Note over App: 再ログイン必要
end
deactivate API
トークンローテーションの意義
旧トークン使用 → 無効化 → 新トークン発行
- リプレイ攻撃防止: 古いトークンは使えなくなる
- トークン漏洩検知: 無効化済みトークンの使用で検知可能
- セッション管理: アクティブなセッションのみ有効
4. 認証付きAPI呼び出しフロー
JWT認証が必要なAPIの共通フローです。
sequenceDiagram
autonumber
participant App as 📱 Mobile App
participant Filter as 🔐 JwtAuthFilter
participant Controller as 📋 Controller
participant UseCase as ⚙️ UseCase
App->>Filter: API Request<br/>Authorization: Bearer {token}
activate Filter
Filter->>Filter: JWT検証
alt 有効なアクセストークン
Filter->>Filter: SecurityContext設定<br/>(userId, email)
Filter->>Controller: Request継続
activate Controller
Controller->>UseCase: ビジネスロジック実行
activate UseCase
UseCase-->>Controller: 結果
deactivate UseCase
Controller-->>App: 200 OK / 201 Created
deactivate Controller
else 無効/期限切れトークン
Filter-->>App: 401 Unauthorized
else リフレッシュトークン使用
Filter-->>App: 401 Unauthorized<br/>(アクセストークンが必要)
end
deactivate Filter
5. ログアウトフロー
sequenceDiagram
autonumber
participant App as 📱 Mobile App
participant API as 🖥️ Backend API
participant DB as 🗄️ PostgreSQL
App->>API: POST /api/auth/logout<br/>{refreshToken}
activate API
API->>DB: RefreshToken 無効化<br/>(revoked = true)
activate DB
DB-->>API: 更新完了
deactivate DB
API-->>App: 204 No Content
deactivate API
Note over App: ローカルトークン削除
6. アカウント削除フロー
sequenceDiagram
autonumber
participant App as 📱 Mobile App
participant API as 🖥️ Backend API
participant DB as 🗄️ PostgreSQL
App->>API: DELETE /api/auth/account<br/>Authorization: Bearer {token}
activate API
Note over API: JWT検証(userId取得)
API->>DB: メモ削除<br/>(user_id = ?)
activate DB
DB-->>API: 削除完了
deactivate DB
API->>DB: RefreshToken 削除<br/>(user_id = ?)
activate DB
DB-->>API: 削除完了
deactivate DB
API->>DB: User 削除<br/>(id = ?)
activate DB
DB-->>API: 削除完了
deactivate DB
API-->>App: 204 No Content
deactivate API
Note over App: ログイン画面へ遷移
削除順序の重要性
外部キー制約を考慮し、以下の順序で削除:
- VoiceMemo (user_id 参照)
- RefreshToken (user_id 参照)
- User (親テーブル)
7. エラーハンドリング全体像
sequenceDiagram
participant App as 📱 Mobile App
participant API as 🖥️ Backend API
Note over App,API: 想定されるエラーパターン
rect rgb(255, 230, 230)
Note right of App: 認証エラー
App->>API: 無効なJWT
API-->>App: 401 Unauthorized<br/>{error, code: "UNAUTHORIZED"}
end
rect rgb(255, 245, 230)
Note right of App: 入力エラー
App->>API: 不正なリクエスト
API-->>App: 400 Bad Request<br/>{error, code: "BAD_REQUEST"}
end
rect rgb(255, 230, 245)
Note right of App: リソースエラー
App->>API: 存在しないリソース
API-->>App: 404 Not Found<br/>{error, code: "NOT_FOUND"}
end
rect rgb(230, 230, 255)
Note right of App: サーバーエラー
App->>API: 外部API障害
API-->>App: 500 Internal Server Error<br/>{error, code: "INTERNAL_SERVER_ERROR"}
end
処理時間の目安
| フロー | 想定処理時間 | ボトルネック |
|---|---|---|
| ログイン | 500ms - 1s | Google Token検証 |
| トークンリフレッシュ | 100ms - 200ms | DB操作 |
| 音声メモ生成 | 3s - 15s | Speech-to-Text + AI整形 |
| ログアウト | 50ms - 100ms | DB操作 |
| アカウント削除 | 200ms - 500ms | 複数テーブル削除 |
関連ドキュメント
- アーキテクチャ - システム全体構成
- 認証 - 認証システム詳細
- API リファレンス - API仕様詳細
- アクティビティ図 - ユーザー操作フロー
画面遷移図
VoiceBookLM モバイルアプリの画面遷移を図示します。
全体概要
stateDiagram-v2
[*] --> スプラッシュ
スプラッシュ --> ログイン: 未認証
スプラッシュ --> ホーム: 認証済み
state ログイン {
[*] --> ログイン画面
ログイン画面 --> Google認証
Google認証 --> ログイン画面: 失敗
}
ログイン --> ホーム: 認証成功
state ホーム {
[*] --> メモ一覧
メモ一覧 --> 検索
検索 --> メモ一覧
}
ホーム --> 録音: 録音ボタン
録音 --> 処理中: 録音完了
処理中 --> メモ詳細: 生成完了
メモ詳細 --> ホーム: 戻る
ホーム --> メモ詳細: メモ選択
ホーム --> 設定: 設定アイコン
設定 --> ログイン: ログアウト
設定 --> [*]: アカウント削除
1. 認証フロー
flowchart TD
subgraph 起動["📱 アプリ起動"]
Splash[スプラッシュ画面]
end
subgraph 認証チェック["🔐 認証チェック"]
Check{JWT有効?}
Refresh{リフレッシュ<br/>可能?}
end
subgraph ログイン["🔑 ログイン"]
Login[ログイン画面]
GoogleAuth[Google Sign-In]
AuthError[認証エラー<br/>ダイアログ]
end
subgraph メイン["🏠 メイン"]
Home[ホーム画面]
end
Splash --> Check
Check -->|有効| Home
Check -->|期限切れ| Refresh
Refresh -->|成功| Home
Refresh -->|失敗| Login
Check -->|なし| Login
Login -->|Googleでログイン| GoogleAuth
GoogleAuth -->|成功| Home
GoogleAuth -->|失敗| AuthError
AuthError -->|再試行| Login
style Splash fill:#e1f5fe
style Home fill:#c8e6c9
style Login fill:#fff3e0
style AuthError fill:#ffcdd2
画面詳細
| 画面 | 説明 | 主要アクション |
|---|---|---|
| スプラッシュ | アプリロゴ表示、JWT検証 | 自動遷移 |
| ログイン | Google Sign-In ボタン | Googleでログイン |
| 認証エラー | エラーメッセージ表示 | 再試行、閉じる |
2. メイン画面フロー
flowchart TD
subgraph ホーム["🏠 ホーム画面"]
MemoList[メモ一覧<br/>日付順表示]
Directory[ディレクトリ<br/>ツリー表示]
SearchBar[検索バー]
RecordBtn((🎤<br/>録音))
SettingsBtn[⚙️]
end
subgraph 検索["🔍 検索"]
SearchInput[キーワード入力]
TagFilter[タグフィルター]
SearchResults[検索結果一覧]
end
subgraph メモ詳細["📄 メモ詳細"]
MemoView[メモ表示<br/>Markdown]
MemoTags[タグ表示]
MemoMeta[作成日時]
ResummarizeBtn[再要約ボタン]
end
subgraph 録音["🎤 録音画面"]
Recording[録音中<br/>波形表示]
StopBtn[停止ボタン]
end
subgraph 処理中["⏳ 処理中"]
Uploading[アップロード中]
Transcribing[文字起こし中]
Formatting[AI整形中]
end
subgraph 設定["⚙️ 設定"]
Profile[プロフィール]
Language[言語設定]
Logout[ログアウト]
DeleteAccount[アカウント削除]
end
MemoList --> SearchBar
SearchBar --> SearchInput
SearchInput --> SearchResults
TagFilter --> SearchResults
SearchResults --> MemoView
MemoList --> MemoView
Directory --> MemoView
RecordBtn --> Recording
Recording --> StopBtn
StopBtn --> Uploading
Uploading --> Transcribing
Transcribing --> Formatting
Formatting --> MemoView
MemoView --> ResummarizeBtn
ResummarizeBtn --> Formatting
SettingsBtn --> Profile
Profile --> Language
Profile --> Logout
Profile --> DeleteAccount
style RecordBtn fill:#f44336,color:#fff
style MemoList fill:#e3f2fd
style MemoView fill:#e8f5e9
style Recording fill:#ffebee
style Formatting fill:#fff3e0
3. 録音〜保存フロー(詳細)
flowchart TD
subgraph 録音準備["📱 録音準備"]
Home[ホーム画面]
RecordButton((🎤))
PermissionCheck{マイク<br/>許可?}
PermissionRequest[許可リクエスト]
end
subgraph 録音中["🔴 録音中"]
RecordingScreen[録音画面]
Waveform[波形表示]
Timer[経過時間]
StopButton[停止ボタン]
CancelButton[キャンセル]
end
subgraph 確認["✅ 確認"]
Preview[録音プレビュー]
PlayButton[再生]
RetryButton[録り直し]
SubmitButton[送信]
end
subgraph 処理["⚙️ 処理中"]
Progress[プログレス表示]
Step1[1. アップロード中...]
Step2[2. 文字起こし中...]
Step3[3. AI整形中...]
Step4[4. 保存中...]
end
subgraph 完了["🎉 完了"]
Result[生成結果画面]
Title[タイトル]
Content[整形済み本文]
Tags[自動タグ]
SaveButton[保存して閉じる]
end
subgraph エラー["❌ エラー"]
ErrorDialog[エラーダイアログ]
RetryOption[再試行]
DismissOption[閉じる]
end
Home --> RecordButton
RecordButton --> PermissionCheck
PermissionCheck -->|許可済み| RecordingScreen
PermissionCheck -->|未許可| PermissionRequest
PermissionRequest -->|許可| RecordingScreen
PermissionRequest -->|拒否| Home
RecordingScreen --> Waveform
RecordingScreen --> Timer
RecordingScreen --> StopButton
RecordingScreen --> CancelButton
CancelButton --> Home
StopButton --> Preview
Preview --> PlayButton
Preview --> RetryButton
Preview --> SubmitButton
RetryButton --> RecordingScreen
SubmitButton --> Progress
Progress --> Step1 --> Step2 --> Step3 --> Step4
Step4 -->|成功| Result
Step1 -->|失敗| ErrorDialog
Step2 -->|失敗| ErrorDialog
Step3 -->|失敗| ErrorDialog
ErrorDialog --> RetryOption
ErrorDialog --> DismissOption
RetryOption --> Progress
DismissOption --> Home
Result --> Title
Result --> Content
Result --> Tags
Result --> SaveButton
SaveButton --> Home
style RecordButton fill:#f44336,color:#fff
style RecordingScreen fill:#ffcdd2
style Progress fill:#fff3e0
style Result fill:#c8e6c9
style ErrorDialog fill:#ffcdd2
4. 画面一覧
認証系
| # | 画面名 | パス | 説明 |
|---|---|---|---|
| 1 | スプラッシュ | /splash | アプリ起動時のロード画面 |
| 2 | ログイン | /login | Google Sign-In ボタン |
メイン系
| # | 画面名 | パス | 説明 |
|---|---|---|---|
| 3 | ホーム | /home | メモ一覧、ディレクトリ表示 |
| 4 | 検索 | /search | キーワード・タグ検索 |
| 5 | メモ詳細 | /memo/:id | Markdown形式でメモ表示 |
録音系
| # | 画面名 | パス | 説明 |
|---|---|---|---|
| 6 | 録音 | /record | 音声録音画面 |
| 7 | 録音確認 | /record/preview | 録音プレビュー・送信確認 |
| 8 | 処理中 | /record/processing | アップロード〜AI整形のプログレス |
| 9 | 生成結果 | /record/result | 生成されたメモの確認 |
設定系
| # | 画面名 | パス | 説明 |
|---|---|---|---|
| 10 | 設定 | /settings | 設定メニュー |
| 11 | プロフィール | /settings/profile | ユーザー情報表示 |
| 12 | 言語設定 | /settings/language | 文字起こし言語選択 |
5. 画面コンポーネント構成
flowchart TB
subgraph App["📱 App"]
subgraph Navigation["🧭 Navigation"]
BottomTab[BottomTabNavigator]
Stack[StackNavigator]
end
subgraph Screens["📄 Screens"]
subgraph Auth["認証"]
SplashScreen
LoginScreen
end
subgraph Main["メイン"]
HomeScreen
SearchScreen
MemoDetailScreen
end
subgraph Record["録音"]
RecordScreen
PreviewScreen
ProcessingScreen
ResultScreen
end
subgraph Settings["設定"]
SettingsScreen
ProfileScreen
LanguageScreen
end
end
subgraph Components["🧩 共通コンポーネント"]
Header[Header]
MemoCard[MemoCard]
TagChip[TagChip]
LoadingIndicator[LoadingIndicator]
ErrorDialog[ErrorDialog]
FAB[FloatingActionButton]
end
end
BottomTab --> HomeScreen
BottomTab --> SearchScreen
BottomTab --> SettingsScreen
Stack --> MemoDetailScreen
Stack --> RecordScreen
Stack --> PreviewScreen
Stack --> ProcessingScreen
Stack --> ResultScreen
HomeScreen --> MemoCard
HomeScreen --> FAB
SearchScreen --> MemoCard
SearchScreen --> TagChip
MemoDetailScreen --> TagChip
RecordScreen --> Header
ProcessingScreen --> LoadingIndicator
ResultScreen --> TagChip
6. ナビゲーション構造
App
├── AuthStack (未認証時)
│ ├── Splash
│ └── Login
│
└── MainStack (認証済み)
├── BottomTabs
│ ├── HomeTab
│ │ └── Home
│ ├── SearchTab
│ │ └── Search
│ └── SettingsTab
│ └── Settings
│
└── Modals / Stacks
├── MemoDetail
├── RecordFlow
│ ├── Record
│ ├── Preview
│ ├── Processing
│ └── Result
├── Profile
└── Language
7. 状態遷移表
認証状態
| 現在の状態 | イベント | 次の状態 | アクション |
|---|---|---|---|
| 未認証 | アプリ起動 | スプラッシュ | JWT確認 |
| スプラッシュ | JWT有効 | ホーム | 自動遷移 |
| スプラッシュ | JWT無効 | ログイン | 自動遷移 |
| ログイン | Google認証成功 | ホーム | トークン保存 |
| ログイン | Google認証失敗 | ログイン | エラー表示 |
| 認証済み | ログアウト | ログイン | トークン削除 |
| 認証済み | アカウント削除 | ログイン | データ削除 |
録音状態
| 現在の状態 | イベント | 次の状態 | アクション |
|---|---|---|---|
| ホーム | 録音ボタン | 録音画面 | 権限確認 |
| 録音画面 | 停止 | プレビュー | 録音停止 |
| 録音画面 | キャンセル | ホーム | 録音破棄 |
| プレビュー | 送信 | 処理中 | API呼び出し |
| プレビュー | 録り直し | 録音画面 | 録音リセット |
| 処理中 | 完了 | 結果画面 | レスポンス表示 |
| 処理中 | エラー | エラーダイアログ | エラー表示 |
| 結果画面 | 保存 | ホーム | 一覧更新 |
8. ワイヤーフレーム概要
ホーム画面
┌─────────────────────────────────┐
│ 📱 VoiceBookLM ⚙️ │
├─────────────────────────────────┤
│ 🔍 メモを検索... │
├─────────────────────────────────┤
│ │
│ 📁 アイデア │
│ └─ 📄 新機能のアイデア │
│ └─ 📄 改善案メモ │
│ │
│ 📁 日記 │
│ └─ 📄 今日の振り返り │
│ │
│ 📁 仕事 │
│ └─ 📄 会議メモ │
│ │
│ │
│ ┌─────┐ │
│ │ 🎤 │ │
│ └─────┘ │
├─────────────────────────────────┤
│ 🏠 🔍 ⚙️ │
└─────────────────────────────────┘
録音画面
┌─────────────────────────────────┐
│ ← 録音 │
├─────────────────────────────────┤
│ │
│ │
│ ╭──────────────╮ │
│ │ │ │
│ │ 🔴 録音中 │ │
│ │ │ │
│ ╰──────────────╯ │
│ │
│ ∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿ │
│ 波形表示 │
│ │
│ 00:15 │
│ │
│ ┌─────────┐ │
│ │ 停止 │ │
│ └─────────┘ │
│ │
│ キャンセル │
│ │
└─────────────────────────────────┘
メモ詳細画面
┌─────────────────────────────────┐
│ ← メモ詳細 ⋮ │
├─────────────────────────────────┤
│ │
│ # 新機能のアイデア │
│ │
│ 📅 2025-12-17 │
│ 🏷️ アイデア 機能 MVP │
│ │
│ ───────────────────────────── │
│ │
│ ## 概要 │
│ 音声入力でメモを取れる │
│ アプリを作りたい。 │
│ │
│ ## ポイント │
│ - AIで自動整形 │
│ - タグ自動付与 │
│ - Markdown形式 │
│ │
│ ## 次のアクション │
│ - 技術選定を進める │
│ │
│ ┌─────────┐ │
│ │ 再要約 │ │
│ └─────────┘ │
└─────────────────────────────────┘
関連ドキュメント
- PRD - 製品要件定義
- アクティビティ図 - ユーザー操作フロー
- シーケンス図 - システム間の通信フロー
- API リファレンス - バックエンドAPI仕様
ER図
erDiagram
users {
UUID id PK "UUIDv7"
VARCHAR google_sub UK "Google User ID (sub claim)"
VARCHAR email UK "メールアドレス"
VARCHAR name "表示名"
TIMESTAMPTZ created_at "作成日時"
TIMESTAMPTZ updated_at "更新日時"
}
memos {
UUID id PK "UUIDv7"
UUID user_id FK "ユーザーID"
VARCHAR transcription_status "文字起こしステータス"
VARCHAR formatting_status "AI整形ステータス"
TEXT transcription "文字起こし結果"
VARCHAR title "AIタイトル"
TEXT content "AI整形本文(Markdown)"
TIMESTAMPTZ created_at "作成日時"
TIMESTAMPTZ updated_at "更新日時"
BOOLEAN deleted "論理削除フラグ"
}
memo_tags {
UUID memo_id PK,FK "メモID"
VARCHAR tag PK "タグ名"
}
refresh_tokens {
UUID id PK "UUIDv7"
VARCHAR token UK "リフレッシュトークン"
UUID user_id FK "ユーザーID"
TIMESTAMPTZ expires_at "有効期限"
TIMESTAMPTZ created_at "作成日時"
BOOLEAN revoked "無効化フラグ"
}
users ||--o{ memos : "has"
users ||--o{ refresh_tokens : "has"
memos ||--o{ memo_tags : "has"
テーブル概要
| テーブル名 | 説明 |
|---|---|
users | ユーザーアカウント情報(Google OAuth 認証) |
memos | AI 整形済みボイスメモ(文字起こし→AI整形の2段階処理) |
memo_tags | メモタグ(AI 生成またはユーザー編集) |
refresh_tokens | JWT リフレッシュトークン(トークンローテーション対応) |
リレーションシップ
- users → memos: 1対多(1ユーザーが複数のメモを持つ)
- users → refresh_tokens: 1対多(1ユーザーが複数のトークンを持つ)
- memos → memo_tags: 1対多(1メモが複数のタグを持つ)
ステータス値
transcription_status / formatting_status
| 値 | 説明 |
|---|---|
PENDING | 処理待ち |
PROCESSING | 処理中 |
COMPLETED | 完了 |
FAILED | 失敗 |
認証
VoiceBookLM Backend の認証システムは、Google OAuth 認証と JWT トークン管理を提供するクリーンアーキテクチャベースの実装です。
アーキテクチャ概要
flowchart TB
subgraph Presentation["Presentation Layer"]
AuthController["AuthController (/api/auth)<br/>POST /google : Google OAuth ログイン<br/>POST /refresh : トークンリフレッシュ<br/>POST /logout : ログアウト<br/>DELETE /account : アカウント削除<br/>GET /me : 現在のユーザー情報取得"]
end
subgraph UseCase["UseCase Layer"]
LoginUseCase
RefreshTokenUseCase
LogoutUseCase
GetCurrentUserUseCase
DeleteAccountUseCase
end
subgraph Domain["Domain Layer"]
subgraph Models
User
RefreshToken
OAuthUserInfo
end
subgraph Interfaces
UserRepository
RefreshTokenRepo
OAuthClient
end
end
subgraph Infrastructure["Infrastructure Layer"]
JwtTokenProvider
JwtAuthenticationFilter
GoogleOAuthClient
UserRepositoryImpl["UserRepositoryImpl (JPA)"]
RefreshTokenRepositoryImpl
end
Presentation --> UseCase
UseCase --> Domain
Domain --> Infrastructure
Domain Layer
User
ファイル: src/main/kotlin/com/assari/voicebooklm/domain/model/User.kt
Google OAuth 認証で取得したユーザー情報を表現するドメインモデル。
class User(
val id: UUID, // UUIDv7 (時系列順)
val googleSub: String, // Google の一意識別子
val email: String, // メールアドレス
var name: String, // 表示名
val createdAt: Instant,
var updatedAt: Instant
)
メソッド:
| メソッド | 説明 |
|---|---|
updateName(newName: String) | ユーザー名を更新し、updatedAt を現在時刻に設定 |
RefreshToken
ファイル: src/main/kotlin/com/assari/voicebooklm/domain/model/RefreshToken.kt
JWT リフレッシュトークンの情報を表現するドメインモデル。トークンローテーションをサポート。
class RefreshToken(
val id: UUID, // UUIDv7
val token: String, // JWT トークン文字列
val userId: UUID, // 所有ユーザーの ID
val expiresAt: Instant, // 有効期限
val createdAt: Instant,
var revoked: Boolean // 無効化フラグ
)
メソッド:
| メソッド | 戻り値 | 説明 |
|---|---|---|
isExpired() | Boolean | 有効期限切れかどうか |
isValid() | Boolean | 有効かどうか(未失効 かつ 期限内) |
revoke() | Unit | トークンを無効化 |
OAuthUserInfo
ファイル: src/main/kotlin/com/assari/voicebooklm/domain/model/OAuthUserInfo.kt
OAuth プロバイダーから取得したユーザー情報を表現する値オブジェクト。
data class OAuthUserInfo(
val providerId: String, // プロバイダー固有 ID (Google: sub)
val email: String,
val name: String,
val picture: String? // プロフィール画像 URL
)
OAuthClient (Interface)
ファイル: src/main/kotlin/com/assari/voicebooklm/domain/gateway/OAuthClient.kt
OAuth 認証プロバイダーとの通信を抽象化するゲートウェイインターフェース。
interface OAuthClient {
fun verifyIdTokenAndGetUserInfo(idToken: String): OAuthUserInfo?
}
実装:
GoogleOAuthClient- Google OAuth 認証
UserRepository (Interface)
ファイル: src/main/kotlin/com/assari/voicebooklm/domain/repository/UserRepository.kt
interface UserRepository {
fun save(user: User): User
fun findById(id: UUID): User?
fun findByEmail(email: String): User?
fun findByGoogleSub(googleSub: String): User?
fun deleteById(id: UUID)
}
RefreshTokenRepository (Interface)
ファイル: src/main/kotlin/com/assari/voicebooklm/domain/repository/RefreshTokenRepository.kt
interface RefreshTokenRepository {
fun save(token: RefreshToken): RefreshToken
fun findByTokenAndValid(token: String, now: Instant): RefreshToken?
fun revokeByToken(token: String)
fun revokeByUserId(userId: UUID) // ログアウト時
fun deleteByUserId(userId: UUID) // アカウント削除時
}
UseCase Layer
LoginUseCase
ファイル: src/main/kotlin/com/assari/voicebooklm/usecase/auth/LoginUseCase.kt
OAuth 認証フローを処理し、JWT トークンペアを発行する。
入力: LoginCommand(idToken: String)
出力: LoginResult(accessToken, refreshToken, userId)
フロー:
OAuthClientで ID トークンを検証- ユーザーを取得または新規作成
- アクセストークン・リフレッシュトークンを生成
- リフレッシュトークンを DB に保存
例外:
InvalidIdTokenException- ID トークンの検証失敗
RefreshTokenUseCase
ファイル: src/main/kotlin/com/assari/voicebooklm/usecase/auth/RefreshTokenUseCase.kt
リフレッシュトークンローテーションを実装。旧トークンを無効化し、新しいトークンペアを発行。
入力: RefreshTokenCommand(refreshToken: String)
出力: RefreshTokenResult(accessToken, refreshToken, userId)
フロー:
- 保存済みリフレッシュトークンを検証
- ユーザーを取得
- 旧トークンを無効化(ローテーション)
- 新しいトークンペアを生成・保存
例外:
InvalidRefreshTokenException- トークンが無効または期限切れ
LogoutUseCase
ファイル: src/main/kotlin/com/assari/voicebooklm/usecase/auth/LogoutUseCase.kt
リフレッシュトークンを無効化してログアウト。
入力: LogoutCommand(refreshToken: String)
出力: なし
GetCurrentUserUseCase
ファイル: src/main/kotlin/com/assari/voicebooklm/usecase/auth/GetCurrentUserUseCase.kt
JWT から取得したユーザー ID でユーザー情報を取得。
入力: GetCurrentUserCommand(userId: UUID)
出力: UserInfo(id, email, name)
DeleteAccountUseCase
ファイル: src/main/kotlin/com/assari/voicebooklm/usecase/auth/DeleteAccountUseCase.kt
ユーザーのすべてのデータを物理削除。
入力: DeleteAccountCommand(userId: UUID)
削除順序(参照整合性維持):
- メモ
- リフレッシュトークン
- ユーザー
Infrastructure Layer
JwtTokenProvider
ファイル: src/main/kotlin/com/assari/voicebooklm/infrastructure/security/JwtTokenProvider.kt
JWT アクセストークン・リフレッシュトークンの生成・検証を行う。HS256 アルゴリズムを使用。
設定:
| プロパティ | 説明 |
|---|---|
jwt.secret | 署名用シークレットキー |
jwt.access-token-expiration | アクセストークン有効期限(ms) |
jwt.refresh-token-expiration | リフレッシュトークン有効期限(ms) |
メソッド:
| メソッド | 説明 |
|---|---|
generateAccessToken(userId, email) | アクセストークン生成 |
generateRefreshToken(userId) | リフレッシュトークン生成 |
validateToken(token) | トークン検証 |
isAccessToken(token) | アクセストークン判定 |
isRefreshToken(token) | リフレッシュトークン判定 |
getUserIdFromToken(token) | トークンからユーザー ID 抽出 |
getEmailFromToken(token) | トークンからメール抽出 |
トークンクレーム:
userId- ユーザー IDemail- メールアドレス(アクセストークンのみ)tokenType-accessまたはrefresh
JwtAuthenticationFilter
ファイル: src/main/kotlin/com/assari/voicebooklm/infrastructure/security/JwtAuthenticationFilter.kt
Authorization ヘッダーから JWT トークンを抽出し、検証する Spring Security フィルタ。
動作:
Authorization: Bearer <token>ヘッダーからトークン抽出JwtTokenProviderでトークン検証- アクセストークンの場合のみ認証情報を
SecurityContextに設定
GoogleOAuthClient
ファイル: src/main/kotlin/com/assari/voicebooklm/infrastructure/api/GoogleOAuthClient.kt
OAuthClient インターフェースの Google 実装。Google ID トークンの検証とユーザー情報の取得を行う。
検証フロー:
https://oauth2.googleapis.com/tokeninfoエンドポイントで検証audクレームがクライアント ID と一致するか確認- メール検証済みか確認
OAuthUserInfoに変換して返却
Presentation Layer
AuthController
ファイル: src/main/kotlin/com/assari/voicebooklm/presentation/controller/auth/AuthController.kt
Base Path: /api/auth
| メソッド | パス | 説明 | 認証 |
|---|---|---|---|
| POST | /google | Google OAuth ログイン | 不要 |
| POST | /refresh | トークンリフレッシュ | 不要 |
| POST | /logout | ログアウト | 不要 |
| DELETE | /account | アカウント削除 | 必要 |
| GET | /me | 現在のユーザー情報取得 | 必要 |
リクエスト/レスポンス
GoogleAuthRequest
{
"idToken": "eyJhbGciOiJSUzI1NiIsInR..."
}
RefreshTokenRequest / LogoutRequest
{
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR..."
}
TokenResponse
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR..."
}
UserResponse
{
"id": "01916f54-1234-7abc-def0-123456789abc",
"email": "user@example.com",
"name": "田中太郎"
}
ErrorResponse
{
"error": "認証に失敗しました",
"code": "UNAUTHORIZED"
}
認証フロー
1. ログインフロー
sequenceDiagram
participant App as Mobile App
participant Backend
participant Google
App->>Google: Google Sign-In
Google-->>App: ID Token
App->>Backend: POST /api/auth/google<br/>{ idToken }
Backend->>Google: Verify Token
Google-->>Backend: Token Info
Note over Backend: Create/Find User<br/>Generate JWT Pair<br/>Save Refresh Token
Backend-->>App: TokenResponse<br/>{ accessToken, refreshToken }
2. トークンリフレッシュフロー
sequenceDiagram
participant App as Mobile App
participant Backend
App->>Backend: POST /api/auth/refresh<br/>{ refreshToken }
Note over Backend: Validate Stored Token<br/>Revoke Old Token (Rotation)<br/>Generate New JWT Pair<br/>Save New Refresh Token
Backend-->>App: TokenResponse<br/>{ accessToken, refreshToken }
セキュリティ考慮事項
- トークンローテーション: リフレッシュトークン使用時に旧トークンを無効化
- JWT 署名検証: HS256 アルゴリズムによる改ざん検知
- トークンタイプ分離: アクセストークンとリフレッシュトークンを区別
- メール検証: Google 認証時にメール検証済みを確認
- クライアント ID 検証: ID トークンの
audクレームを検証
API
API リファレンス
VoiceBookLM バックエンド API の詳細仕様です。
Note
バージョン: 0.0.1-SNAPSHOT
開発環境:http://localhost:8080
本番環境:https://api.voicebooklm.example.com
認証 API (/api/auth)
POST /api/auth/google - Google OAuth ログイン
Google ID トークンを検証し、JWT トークンペアを発行します。新規ユーザーの場合はアカウントを作成します。
認証: 不要
リクエスト:
{
"idToken": "string (必須) - Google ID トークン"
}
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | ログイン成功 |
401 Unauthorized | 認証失敗 |
{
"accessToken": "string - アクセストークン(1日有効)",
"refreshToken": "string - リフレッシュトークン(180日間有効)"
}
POST /api/auth/refresh - トークンリフレッシュ
リフレッシュトークンを使用して新しいトークンペアを発行します(トークンローテーション)。
認証: 不要
リクエスト:
{
"refreshToken": "string (必須) - リフレッシュトークン"
}
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | リフレッシュ成功 |
401 Unauthorized | リフレッシュトークンが無効または期限切れ |
{
"accessToken": "string - 新しいアクセストークン",
"refreshToken": "string - 新しいリフレッシュトークン"
}
POST /api/auth/logout - ログアウト
リフレッシュトークンを無効化してログアウトします。
認証: 不要
リクエスト:
{
"refreshToken": "string (必須) - リフレッシュトークン"
}
レスポンス:
| ステータス | 説明 |
|---|---|
204 No Content | ログアウト成功 |
400 Bad Request | リクエスト形式が不正 |
DELETE /api/auth/account - アカウント削除
ユーザーアカウントとすべての関連データを完全に削除します。
認証: 必須(JWT Bearer トークン)
レスポンス:
| ステータス | 説明 |
|---|---|
204 No Content | 削除成功 |
401 Unauthorized | 認証失敗 |
404 Not Found | ユーザーが見つからない |
GET /api/auth/me - 現在のユーザー情報取得
認証済みユーザーの情報を取得します。
認証: 必須(JWT Bearer トークン)
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 取得成功 |
401 Unauthorized | 認証失敗 |
404 Not Found | ユーザーが見つからない |
{
"id": "UUID - ユーザー ID",
"email": "string - メールアドレス",
"name": "string - ユーザー名"
}
音声メモ API (/api/voice)
POST /api/voice/memos - 音声ファイルからメモを生成
音声ファイルをアップロードし、文字起こし → AI整形 → 保存を行います。60秒以内のレスポンスを想定。
認証: 必須(JWT Bearer トークン)
Content-Type: multipart/form-data
リクエスト:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
file | File | ○ | 音声ファイル |
language | String | × | 言語コード(例: ja-JP, en-US) |
レスポンス:
| ステータス | 説明 |
|---|---|
201 Created | メモ生成成功 |
400 Bad Request | 入力不正(音声が空、Content-Type 不正など) |
401 Unauthorized | 認証エラー(JWT 不正) |
500 Internal Server Error | サーバエラー |
{
"memoId": "UUID - メモ ID",
"title": "string - タイトル",
"content": "string - 整形されたメモ内容",
"tags": ["string"],
"transcription": "string | null - 文字起こしテキスト",
"transcriptionStatus": "COMPLETED | FAILED | PENDING",
"formattingStatus": "COMPLETED | FAILED | PENDING",
"processingTimeMillis": {
"transcription": "number (ms)",
"formatting": "number (ms)",
"persistence": "number (ms)",
"total": "number (ms)"
},
"fallback": {
"transcription": "boolean",
"formatting": "boolean"
}
}
メモ API (/api/memos)
GET /api/memos - メモ一覧取得
認証ユーザーのメモを取得します。フォルダーによるフィルタリング、キーワード検索、ソート、件数制限が可能。
認証: 必須(JWT Bearer トークン)
クエリパラメータ:
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
folderId | UUID | × | - | フォルダーIDでフィルタリング |
includeDescendants | boolean | × | false | true の場合、子孫フォルダーのメモも含める |
uncategorizedOnly | boolean | × | false | true の場合、未分類メモのみ取得 |
keyword | string | × | - | キーワード検索(タイトルまたはコンテントに含まれるメモを検索) |
sort | string | × | updated_at | ソート項目(updated_at, created_at, title) |
order | string | × | desc | ソート順序(asc, desc) |
limit | integer | × | - | 取得件数制限 |
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 取得成功 |
401 Unauthorized | 認証エラー |
{
"memos": [
{
"memoId": "UUID",
"title": "string | null",
"tags": ["string"],
"transcriptionStatus": "COMPLETED | FAILED | PENDING",
"formattingStatus": "COMPLETED | FAILED | PENDING",
"folder": {
"id": "UUID",
"name": "string",
"path": "string"
},
"createdAt": "ISO 8601 datetime",
"updatedAt": "ISO 8601 datetime"
}
]
}
GET /api/memos/{id} - メモ詳細取得
指定されたIDのメモの詳細情報を取得します。セキュリティ上、権限のないメモも404として返します。
認証: 必須(JWT Bearer トークン)
パスパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id | UUID | ○ | メモ ID |
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 取得成功 |
401 Unauthorized | 認証失敗 |
404 Not Found | メモが見つからない(存在しない、削除済み、または権限なし) |
{
"memoId": "UUID",
"title": "string | null",
"content": "string | null",
"tags": ["string"],
"transcriptionText": "string | null",
"transcriptionStatus": "COMPLETED | FAILED | PENDING",
"formattingStatus": "COMPLETED | FAILED | PENDING",
"createdAt": "ISO 8601 datetime",
"updatedAt": "ISO 8601 datetime"
}
PATCH /api/memos/{id} - メモ更新
メモの部分更新を行います。指定されたフィールドのみ更新されます。
認証: 必須(JWT Bearer トークン)
パスパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id | UUID | ○ | メモ ID |
リクエスト:
{
"title": "string (任意, 最大100文字)",
"content": "string (任意)",
"tags": ["string (任意)"]
}
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 更新成功 |
400 Bad Request | バリデーションエラー |
401 Unauthorized | 認証失敗 |
404 Not Found | メモが見つからない(存在しない、削除済み、または権限なし) |
422 Unprocessable Entity | メモの整形が完了していない、またはフォルダーが存在しない |
{
"memoId": "UUID",
"title": "string | null",
"content": "string | null",
"tags": ["string"],
"transcriptionText": "string | null",
"transcriptionStatus": "COMPLETED | FAILED | PENDING",
"formattingStatus": "COMPLETED | FAILED | PENDING",
"createdAt": "ISO 8601 datetime",
"updatedAt": "ISO 8601 datetime"
}
DELETE /api/memos/{id} - メモ削除
指定されたメモを削除します。
認証: 必須(JWT Bearer トークン)
パスパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id | UUID | ○ | メモ ID |
レスポンス:
| ステータス | 説明 |
|---|---|
204 No Content | 削除成功 |
401 Unauthorized | 認証失敗 |
403 Forbidden | アクセス権限なし |
404 Not Found | メモが見つからない |
POST /api/memos/{id}/resummarize - 再要約
編集された文字起こしテキストから再度AI整形(要約)を行います。
認証: 必須(JWT Bearer トークン)
パスパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id | UUID | ○ | メモ ID |
リクエスト:
{
"editedTranscription": "string (必須) - 編集された文字起こしテキスト"
}
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 再要約成功 |
400 Bad Request | バリデーションエラー |
401 Unauthorized | 認証失敗 |
404 Not Found | メモが見つからない(存在しない、削除済み、または権限なし) |
422 Unprocessable Entity | 処理エラー(整形失敗など) |
{
"memoId": "UUID",
"title": "string | null",
"content": "string | null",
"tags": ["string"],
"transcriptionText": "string | null",
"transcriptionStatus": "COMPLETED | FAILED | PENDING",
"formattingStatus": "COMPLETED | FAILED | PENDING",
"createdAt": "ISO 8601 datetime",
"updatedAt": "ISO 8601 datetime"
}
フォルダー API (/api/folders)
GET /api/folders - フォルダー一覧取得
認証ユーザーのフォルダー一覧をパス情報付きで取得します。
認証: 必須(JWT Bearer トークン)
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 取得成功 |
401 Unauthorized | 認証エラー |
{
"folders": [
{
"id": "UUID",
"name": "string",
"parentId": "UUID | null",
"path": "string"
}
]
}
POST /api/folders - フォルダー作成
新しいフォルダーを作成します。親フォルダーを指定して階層構造を作成可能。
認証: 必須(JWT Bearer トークン)
リクエスト:
{
"name": "string (必須, 最大50文字)",
"parentId": "UUID (任意) - 親フォルダー ID"
}
レスポンス:
| ステータス | 説明 |
|---|---|
201 Created | 作成成功 |
401 Unauthorized | 認証エラー |
404 Not Found | 親フォルダーが見つからない |
409 Conflict | 同名フォルダーが既に存在する |
{
"id": "UUID",
"name": "string",
"parentId": "UUID | null",
"path": "string"
}
PATCH /api/folders/{id} - フォルダー更新
フォルダーのリネームまたは移動を行います。両方同時に指定可能。
認証: 必須(JWT Bearer トークン)
パスパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id | UUID | ○ | フォルダー ID |
リクエスト:
{
"name": "string (任意, 最大50文字)",
"parentId": "UUID (任意) - 新しい親フォルダー ID",
"moveToRoot": "boolean (必須) - ルートに移動する場合 true"
}
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 更新成功 |
401 Unauthorized | 認証エラー |
404 Not Found | フォルダーが見つからない |
409 Conflict | 同名フォルダーが既に存在する / 循環参照が発生する |
{
"id": "UUID",
"name": "string",
"parentId": "UUID | null",
"path": "string"
}
DELETE /api/folders/{id} - フォルダー削除
フォルダーを削除します。子フォルダーまたはメモが存在する場合は削除できません。
認証: 必須(JWT Bearer トークン)
パスパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
id | UUID | ○ | フォルダー ID |
レスポンス:
| ステータス | 説明 |
|---|---|
204 No Content | 削除成功 |
401 Unauthorized | 認証エラー |
404 Not Found | フォルダーが見つからない |
409 Conflict | 子フォルダーまたはメモが存在するため削除できない |
タグ API (/api/tags)
GET /api/tags - タグ一覧取得
認証ユーザーが使用している全タグを取得します。ソート順と件数制限が指定可能。
認証: 必須(JWT Bearer トークン)
クエリパラメータ:
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
sort | string | × | name | ソート項目(name: 名前順, usage_count: 使用回数順) |
order | string | × | asc | ソート順序(asc, desc) |
limit | integer | × | - | 取得件数制限 |
使用例:
- 人気タグを取得:
GET /api/tags?sort=usage_count&order=desc&limit=10
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 取得成功 |
401 Unauthorized | 認証エラー |
{
"tags": ["開発", "コード", "ミーティング"]
}
開発用 API (/api/dev)
Caution
これらの API は 開発環境(dev)でのみ有効です。本番環境では使用できません。
POST /api/dev/token - 開発用トークン取得
指定したメールアドレスのユーザーのアクセストークンを取得します。OAuth不要で、Swagger UIからすぐにAPIテストができます。
認証: 不要
クエリパラメータ:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
email | string | ○ | ユーザーのメールアドレス |
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | トークン取得成功 |
404 Not Found | ユーザーが見つからない |
{
"accessToken": "string - アクセストークン(JWT)",
"userId": "string - ユーザーID",
"email": "string - メールアドレス",
"message": "string - 使い方の説明"
}
POST /api/dev/seed - テストデータ作成
認証ユーザー用にテスト用のフォルダーとメモを作成します。データは seed-data.yml から読み込まれます。冪等性を持ち、既にフォルダーが存在する場合はスキップします。
認証: 必須(JWT Bearer トークン)
レスポンス:
| ステータス | 説明 |
|---|---|
200 OK | 作成成功(またはスキップ) |
401 Unauthorized | 認証エラー |
{
"foldersCreated": 3,
"memosCreated": 10,
"skipped": false,
"message": "string - 結果メッセージ"
}
共通仕様
認証方式
JWT (JSON Web Token) を使用。
| トークン種別 | 有効期限 |
|---|---|
| アクセストークン | 1日 |
| リフレッシュトークン | 180日 |
認証が必要な API には Authorization ヘッダーを設定:
Authorization: Bearer <access_token>
エラーレスポンス
{
"error": "string - エラーメッセージ",
"code": "string - エラーコード"
}
| コード | 説明 |
|---|---|
UNAUTHORIZED | 認証失敗 |
FORBIDDEN | アクセス権限なし |
NOT_FOUND | リソースが見つからない |
BAD_REQUEST | リクエスト形式が不正 |
CONFLICT | リソースの競合 |
UNPROCESSABLE_ENTITY | 処理不能なエンティティ |
INTERNAL_SERVER_ERROR | サーバー内部エラー |
OpenAPI ドキュメント
- Swagger UI:
http://localhost:8080/swagger-ui.html - API 仕様 (JSON):
http://localhost:8080/v3/api-docs
画面一覧
VoiceBookLM の画面仕様書一覧です。
画面ID採番ルール
| プレフィックス | 種別 | 例 |
|---|---|---|
| SCR | 画面(Screen) | SCR-001 |
| CMN | 共通(Common) | CMN-001 |
画面一覧
| 画面ID | 画面名 | パス | 概要 |
|---|---|---|---|
| SCR-001 | ウェルカム画面 | / | 未認証ユーザー向け初期画面・ファイルアップロード |
| SCR-002 | ホーム画面 | /home | ログイン済みユーザーのメイン画面 |
| SCR-003 | 録音画面 | /recording | 音声メモを録音する画面 |
共通コンポーネント一覧
| コンポーネントID | コンポーネント名 | 概要 |
|---|---|---|
| CMN-001 | AI処理通知トースト | AI整形処理の進行状況を通知するフローティングトースト |
ウェルカム画面
基本情報
| 項目 | 内容 |
|---|---|
| 画面ID | SCR-001 |
| 画面名 | ウェルカム画面 |
| URL/パス | / |
| 認証要否 | 不要(未認証でも閲覧可) |
画面概要
VoiceBookLMアプリ起動時に未認証ユーザーに表示されるウェルカム画面。アプリの概要と主な機能を紹介し、Googleアカウントでのログインを促す。
画面イメージ

画面要素一覧
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| app_icon | アプリアイコン | 画像 | - | 画面最上部に配置 |
| app_name | アプリ名 | ラベル | - | 「VoiceBookLM」 |
| catchphrase | キャッチフレーズ | ラベル | - | アプリの簡潔な説明 |
| feature_1_icon | 機能1アイコン | アイコン | - | 機能1のアイコン |
| feature_1_name | 機能1名 | ラベル | - | 機能1の名称 |
| feature_1_desc | 機能1説明 | ラベル | - | 機能1の説明文 |
| feature_2_icon | 機能2アイコン | アイコン | - | 機能2のアイコン |
| feature_2_name | 機能2名 | ラベル | - | 機能2の名称 |
| feature_2_desc | 機能2説明 | ラベル | - | 機能2の説明文 |
| feature_3_icon | 機能3アイコン | アイコン | - | 機能3のアイコン |
| feature_3_name | 機能3名 | ラベル | - | 機能3の名称 |
| feature_3_desc | 機能3説明 | ラベル | - | 機能3の説明文 |
| btn_google_login | Googleでログインボタン | ボタン | - | Googleアカウントで認証後、ホーム画面へ遷移 |
| terms_notice | 利用規約同意文 | ラベル | - | 「ログインすることで、利用規約とプライバシーポリシーに同意したものとみなされます。」 |
画面遷移
遷移元
なし
API連携
| メソッド | エンドポイント | 用途 |
|---|---|---|
| POST | /api/auth/google | Google認証処理 |
バリデーション
なし
状態
| 状態 | 説明 |
|---|---|
| 初期状態 | 静的表示、操作待ち状態 |
備考
- 未認証状態でのみ表示される画面
- ログイン済みユーザーはホーム画面へリダイレクト
- 利用規約・プライバシーポリシーへのリンクを含む
ホーム画面
基本情報
| 項目 | 内容 |
|---|---|
| 画面ID | SCR-002 |
| 画面名 | ホーム画面 |
| URL/パス | /home |
| 認証要否 | 要(ログイン済みユーザー) |
画面概要
ログイン済みユーザーのメイン画面。最近作成・編集したメモの一覧と、フォルダによるメモの整理機能を提供する。また、音声入力ボタンから新規メモの作成が可能。
画面イメージ
通常状態

AI整形実行中

AI整形完了

AI整形に失敗

画面要素一覧
ヘッダー部
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| btn_search | 検索ボタン | アイコン | - | メモ検索画面へ遷移 |
| btn_setting | 設定ボタン | アイコン | - | 設定画面へ遷移(歯車アイコン) |
最近のメモセクション
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| section_recent | 最近のメモ | セクション | - | セクションヘッダー |
| memo_card | メモカード | カード | - | メモのプレビューカード(複数) |
| memo_title | メモタイトル | ラベル | - | メモのタイトル表示 |
| memo_tags | タグ | バッジ | - | メモに付与されたタグ(デザイン、UIなど) |
| memo_date | 更新日時 | ラベル | - | 最終更新日時(YYYY-MM-DD HH:mm) |
| btn_memo_menu | メモメニューボタン | アイコン | - | メモの編集・削除メニュー(︙) |
フォルダセクション
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| section_folder | フォルダ | セクション | - | セクションヘッダー |
| folder_item | フォルダ項目 | リストアイテム | - | フォルダ名と件数を表示 |
| folder_name | フォルダ名 | ラベル | - | フォルダ名(受信トレイ、仕事など) |
| folder_count | メモ件数 | ラベル | - | フォルダ内のメモ件数 |
| folder_expand | 展開アイコン | アイコン | - | サブフォルダの展開/折りたたみ(>) |
音声入力ボタン
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| btn_voice | 音声入力ボタン | FAB | - | 音声入力で新規メモ作成開始 |
通知トースト(グローバルコンポーネント)
AI処理通知トーストの詳細仕様は CMN-001 AI処理通知トースト を参照してください。
メモメニュー(ポップアップ)
メモカードの︙ボタンをタップすると表示されるコンテキストメニュー。

| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| menu_delete | 削除 | ボタン | - | メモ削除確認ダイアログを表示(赤字) |
画面遷移
遷移元
| 遷移元 | 条件/アクション |
|---|---|
| ウェルカム画面 | ログイン成功後 |
| 各画面 | 戻るボタン押下 |
API連携
| メソッド | エンドポイント | 用途 |
|---|---|---|
| GET | /api/memos?sort=updated_at&order=desc&limit=3 | メモ一覧取得(更新日時降順、最新3件) |
| GET | /api/folders | フォルダ階層取得(memoCount含む) |
| GET | /api/memos?folder_id=:id | フォルダ内メモ取得(フォルダ展開時) |
| GET | /api/memos/:id/status | メモのAI処理状態確認(将来実装予定) |
バリデーション
なし
状態
| 状態 | 説明 | 画像 |
|---|---|---|
| 通常状態 | メモ一覧とフォルダ一覧を表示 | SCR-002_ホーム画面.png |
| AI整形実行中 | 通知トースト表示 | SCR-002_ホーム画面AI整形実行中.png |
| AI整形完了 | 通知トーストで確認を案内 | SCR-002_ホーム画面AI整形完了.png |
| AI整形に失敗 | 通知トーストでエラー表示 | SCR-002_ホーム画面AI整形に失敗.png |
備考
- ログイン済みユーザー専用画面
- 未認証ユーザーはウェルカム画面へリダイレクト
- 最近のメモは更新日時の降順で表示
- フォルダは階層構造をサポート(サブフォルダあり)
- AI整形処理はバックグラウンドで実行され、完了時にトースト通知
録音画面
基本情報
| 項目 | 内容 |
|---|---|
| 画面ID | SCR-003 |
| 画面名 | 録音画面 |
| URL/パス | /recording |
| 認証要否 | 要(ログイン済みユーザー) |
画面概要
音声メモを録音するための画面。リアルタイムで音声波形を表示し、録音の一時停止・再開が可能。録音完了後はAIによる整形処理へ遷移する。
画面イメージ
録音中

一時停止中

画面要素一覧
ヘッダー部
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| btn_back | 戻るボタン | アイコン | - | 前画面へ戻る(録音破棄確認あり) |
| recording_indicator | 録音インジケーター | バッジ | - | 赤い●と経過時間を表示(MM:SS形式) |
波形表示エリア
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| waveform_area | 波形表示エリア | コンテナ | - | 音声波形を表示するエリア |
| waveform | 音声波形 | グラフィック | - | リアルタイムで音声入力レベルを波形で可視化(青→ピンクのグラデーション) |
操作ボタン
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| btn_pause | 一時停止ボタン | アイコン | - | 録音を一時停止(⏸アイコン) |
| btn_resume | 再開ボタン | アイコン | - | 一時停止中に表示、録音を再開(▷アイコン) |
| btn_complete | 完了ボタン | ボタン | - | 「完了してAI整形する」録音を終了しAI処理開始 |
画面遷移
遷移元
| 遷移元 | 条件/アクション |
|---|---|
| ホーム画面 | 音声入力ボタン(FAB)押下 |
遷移先
| 遷移先 | 条件/アクション |
|---|---|
| ホーム画面 | 完了してAI整形するボタン押下(通知トーストを表示して遷移) |
API連携
| メソッド | エンドポイント | 用途 |
|---|---|---|
| POST | /api/voice/memos | 音声アップロード・文字起こし・AI整形を一括処理する |
バリデーション
| 項目 | ルール | エラーメッセージ例 |
|---|---|---|
| 録音時間 | 最低1秒以上の録音が必要 | 録音時間が短すぎます |
| 録音時間 | 最大60分まで | 録音時間の上限に達しました |
| マイク権限 | マイクへのアクセス許可が必要 | マイクへのアクセスを許可してください |
状態
| 状態 | 説明 | 画像 |
|---|---|---|
| 録音中 | 波形がアニメーションし、経過時間が更新される | SCR-003_録音画面.png |
| 一時停止中 | 波形が静止し、再開ボタンが表示される | SCR-003_録音画面一時停止.png |
備考
- ログイン済みユーザー専用画面
- 録音中は画面スリープを無効化
- バックグラウンド移行時は録音を自動的に一時停止
- 録音データはローカルに一時保存され、完了時にサーバーへアップロード
- 戻るボタン押下時は録音破棄確認ダイアログを表示
- 録音インジケーターの●は録音中に点滅アニメーション
メモ検索画面
基本情報
| 項目 | 内容 |
|---|---|
| 画面ID | SCR-004 |
| 画面名 | メモ検索画面 |
| URL/パス | /search |
| 認証要否 | 要(ログイン済みユーザー) |
画面概要
キーワードによるメモの全文検索機能を提供する画面。検索履歴とよく使うタグからの絞り込みにも対応し、目的のメモに素早くアクセスできる。
画面イメージ
初期状態(検索前)

検索結果あり

検索結果なし

画面要素一覧
ヘッダー部
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| btn_back | 戻るボタン | アイコン | - | 前画面(ホーム画面)へ戻る |
| page_title | 画面タイトル | ラベル | - | 「検索」を表示 |
検索入力部
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| input_search | 検索入力欄 | テキスト | - | プレースホルダー「メモを検索…」 |
| btn_clear | クリアボタン | アイコン | - | 検索文字列をクリア(×アイコン) |
検索履歴セクション(初期状態のみ表示)
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| section_history | 検索履歴 | セクション | - | セクションヘッダー「検索履歴」 |
| history_item | 履歴項目 | リストアイテム | - | 過去の検索キーワード(タップで再検索) |
| history_expand | 展開アイコン | アイコン | - | 履歴詳細へ遷移(>アイコン) |
よく使うタグセクション(初期状態のみ表示)
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| section_tags | よく使うタグ | セクション | - | セクションヘッダー「よく使うタグ」 |
| tag_chip | タグチップ | チップ | - | タグバッジ(開発、コード、ミーティング等) |
検索結果セクション(検索実行後に表示)
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| section_results | 検索結果 | セクション | - | 「検索結果 (N件)」を表示 |
| result_item | 検索結果項目 | リストアイテム | - | ヒットしたメモの一覧 |
| result_title | メモタイトル | ラベル | - | メモのタイトル表示 |
| result_tags | タグ | バッジ | - | メモに付与されたタグ |
| result_date | 更新日時 | ラベル | - | 最終更新日時(YYYY-MM-DD HH:mm形式) |
| btn_result_menu | メニューボタン | アイコン | - | メモの編集・削除メニュー(︙) |
検索結果なし表示
| 要素ID | 要素名 | 種別 | 必須 | 説明 |
|---|---|---|---|---|
| empty_state | 結果なしメッセージ | メッセージ | - | 「該当するメモが見つかりませんでした」 |
画面遷移
遷移元
| 遷移元 | 条件/アクション |
|---|---|
| ホーム画面 | 検索ボタン押下 |
遷移先
| 遷移先 | 条件/アクション |
|---|---|
| ホーム画面 | 戻るボタン押下 |
| メモ詳細画面 | 検索結果のメモ項目タップ |
API連携
| メソッド | エンドポイント | 用途 |
|---|---|---|
| GET | /api/memos/search?q=:keyword | キーワードによるメモ全文検索 |
| GET | /api/search/history | 検索履歴取得 |
| GET | /api/tags?sort=usage&limit=10 | よく使うタグ取得(使用頻度順) |
バリデーション
| 項目 | ルール | エラーメッセージ例 |
|---|---|---|
| 検索文字列 | 最低1文字以上入力が必要 | 検索キーワードを入力してください |
| 検索文字列 | 最大100文字まで | 検索キーワードが長すぎます |
状態
| 状態 | 説明 | 画像 |
|---|---|---|
| 初期状態 | 検索履歴とよく使うタグを表示 | SCR-004_メモ検索画面.png |
| 検索結果あり | 検索結果一覧を表示(件数付き) | SCR-004_メモ検索画面_検索ヒットあり.png |
| 検索結果なし | 「該当するメモが見つかりませんでした」を表示 | SCR-004_検索画面_検索ヒットなし.png |
備考
- ログイン済みユーザー専用画面
- 検索はメモのタイトル・本文・タグを対象とした全文検索
- 検索は入力完了後に自動実行(デバウンス処理あり)
- 検索履歴は最新10件まで保持
- タグチップタップ時は該当タグでフィルタリング検索を実行
- 検索結果はスクロールによる無限ロード対応
AI処理通知トースト
基本情報
| 項目 | 内容 |
|---|---|
| コンポーネントID | CMN-001 |
| コンポーネント名 | AI処理通知トースト |
| 種別 | グローバルコンポーネント(フローティング) |
概要
AI整形処理(要約生成)の進行状況をユーザーに通知するフローティングトースト。録音完了後にホーム画面へ遷移した際に表示され、どの画面に遷移しても画面上部に表示され続ける。処理完了後はタップして作成されたメモへ遷移可能。
画面イメージ
処理中

処理完了

処理失敗

要素一覧
処理中状態
| 要素ID | 要素名 | 種別 | 説明 |
|---|---|---|---|
| toast_processing | 処理中トースト | トースト | フローティングトーストコンテナ |
| processing_text | 処理中テキスト | ラベル | 「AI整形を実行中」 |
| processing_sub_text | サブテキスト | ラベル | 「バックグラウンドで処理中」 |
| processing_indicator | プログレス表示 | アイコン | ローディングインジケーター(青丸) |
完了状態
| 要素ID | 要素名 | 種別 | 説明 |
|---|---|---|---|
| toast_completed | 完了トースト | トースト | フローティングトーストコンテナ |
| completed_text | 完了テキスト | ラベル | 「AI整形が完了」 |
| completed_action | 確認リンク | リンク | 「タップして確認する」 |
| completed_icon | 完了アイコン | アイコン | チェックマークアイコン(緑丸) |
失敗状態
| 要素ID | 要素名 | 種別 | 説明 |
|---|---|---|---|
| toast_failed | 失敗トースト | トースト | フローティングトーストコンテナ |
| failed_text | 失敗テキスト | ラベル | 「AI整形に失敗」 |
| failed_action | リトライ案内 | ラベル | 「長押しで破棄 / タップで再試行」 |
| failed_icon | 失敗アイコン | アイコン | ×アイコン(赤丸) |
表示条件
| 条件 | 動作 |
|---|---|
| AI整形処理開始 | 処理中トーストを表示 |
| AI整形処理完了 | 完了トーストに切り替え |
| AI整形処理失敗 | 失敗トーストに切り替え |
| 完了トーストタップ | 作成されたメモ詳細画面へ遷移、トーストを非表示 |
| 失敗トーストタップ | AI整形処理を再試行 |
| 失敗トースト長押し | 処理を破棄、トーストを非表示 |
| トーストスワイプ | トーストを非表示(任意で閉じる) |
| 画面遷移 | 遷移先でもトーストを継続表示 |
表示トリガー
| トリガー | 説明 |
|---|---|
| 録音画面で「完了してAI整形する」押下 | 処理中トーストを表示し、ホーム画面へ遷移 |
API連携
| メソッド | エンドポイント | 用途 |
|---|---|---|
| GET | /api/memos/:id/status | メモのAI処理状態をポーリングで確認 |
ステータス値
| status | 説明 | トースト表示 |
|---|---|---|
processing | AI整形処理中 | 処理中トースト |
completed | AI整形完了 | 完了トースト |
failed | AI整形失敗 | 失敗トースト |
備考
- 処理はバックグラウンドで実行されるため、アプリ操作を妨げない
- 複数の処理が同時に走る場合の仕様は将来検討
- ネットワークエラー時はリトライ案内を表示予定
12-17
{
"memoId": "3fe8b039-f867-4403-a8bb-06e217f94b5a",
"title": "## ボイスブックLM 開発音声メモ",
"content": "## ボイスブックLM 開発音声メモ\n\nボイスブックLMの開発状況と今後の展望について音声で記録。\n* React NativeアプリのビルドでNode.jsのバージョン問題\n* Google Speech to TextとGemini APIによる文字起こしと整形\n* リアルタイム文字起こし、タグ自動付与の検討\n* 来週までにMVP完成を目指す\n\nTags: `Voicebook`, `AI`, `Development`, `Memo`",
"tags": [
"*",
"リアルタイム文字起こし、タグ自動付与の検討"
],
"transcription": "今日はボイスブック LM のテストも兼ねて今考えてることを音声でメモして行こうと思いますまず最初に今日行って作業振り返りから話します今日は午前中にリアクトネイティブとエキスポを使ったアプリのビルド周りを触っていました EAS ビルドを使って開発ビルドを作ろうとしたんですが NPM の警告がたくさん出てインフライトがディプリケーターだったりり胸付のバージョンが古いとかグローブの性格も出ていました後 Windows 環境のとアセンションふぇーみたいな色も出て喉 JS のバージョン磯ぽいなと感じましたこの辺りは後で整理して Node のバージョンを20系に固定するか nvm をちゃんと使うのかドキュメントにまとめたいと思っています次にボイスブック NM 自体の話をしますこのアプリでは音声を一気に録音してバックエンドに送信して Google Speech to text で文字起こしをしてその後に地味に\nゼロフラッシュを使ってタイトル先生とか本文の整形タグ付けを行う想定です例えば今日やったこととホームがやりたいことと悩んでいることが混ざった音声でもうまく整理してくれるかを試したいですここで今後やりたいことを話します直近ではリアルタイム文字起こしも行ってみたいなと思っています今は一括音声アップロード方式なんですが夜ソケットを使ってストリーミングで文字文字起こしてきたら会議メモとかにも使えそうだなと考えていますあとタグの児童扶養ももっと賢くしたくて例えば開発 react Native 音声認識 AI みたいなタグをユーザーが何もしなくてもつけてくれると嬉しいです少し話題を変えて個人的なメモを残しときます来週までにボイスケイレブの MVP を一旦完成させたいです最低限必要なのは音声録音文字起こし AI 整形一覧表示検索機能ですツールとしては一つ目音声アップロード API\n エラーハンドリング改善フタツメ文字起こしパイ市のリトライ処理見つめジェミニ API のレスポンスをもう少し安定させることこの三つは遊星の高めです最後にこの音声がちゃんと自然な文章に成形されて読みやすいメモになっていたら成功かなと思っていますもし可能ならタイトルはボイスブック LM 開発メモ SR とメモ AI 整形の継承みたいな感じになると嬉しいです以上です",
"transcriptionStatus": "COMPLETED",
"formattingStatus": "COMPLETED",
"processingTimeMillis": {
"transcription": 62634,
"formatting": 1421,
"persistence": 18,
"total": 64074
},
"fallback": {
"transcription": false,
"formatting": false
}
}
🎤 テスト音声 台本(そのまま読んでOK)
えーっと、今日は VoiceBook LM のテストも兼ねて、 今考えていることを音声でメモしていこうと思います。
まず最初に、今日やった作業の振り返りから話します。
今日は午前中に、React Native と Expo を使ったアプリのビルド周りを触っていました。 EAS Build を使って開発ビルドを作ろうとしたんですが、 npm の警告が結構たくさん出て、 inflight が deprecated だったり、rimraf のバージョンが古いとか、 glob の警告も出ていました。
あと、Windows 環境だと Assertion failed: new_time >= loop->time みたいなエラーも出て、 Node.js のバージョン依存っぽいなと感じました。
このあたりは後で整理して、 Node のバージョンを 20 系に固定するか、 nvm をちゃんと使うか、 ドキュメントにまとめたいと思っています。
次に、VoiceBook LM 自体の話をします。
このアプリでは、 音声を一気に録音して、 バックエンドに送信して、 Google Speech-to-Text で文字起こしをして、 その後に Gemini 2.0 Flash を使って タイトル生成とか、本文の整形、タグ付けを行う想定です。
例えば、 「今日やったこと」と 「今後やりたいこと」と 「悩んでいること」 が混ざった音声でも、 うまく整理してくれるかを試したいです。
ここで、今後やりたいことを話します。
直近では、 リアルタイム文字起こしもやってみたいなと思っています。 今は一括音声アップロード方式なんですけど、 WebSocket とかを使って ストリーミングで文字起こしできたら、 会議メモとかにも使えそうだなと考えています。
あと、 タグの自動付与ももっと賢くしたくて、 例えば 「開発」「React Native」「音声認識」「AI」 みたいなタグを ユーザーが何もしなくても付けてくれると嬉しいです。
少し話題を変えて、 個人的なメモも残しておきます。
来週までに、 VoiceBook LM の MVP を一旦完成させたいです。 最低限必要なのは、 音声録音、 文字起こし、 AI 整形、 一覧表示、 検索機能です。
TODO としては、
一つ目、 音声アップロード API のエラーハンドリング改善。
二つ目、 文字起こし失敗時のリトライ処理。
三つ目、 Gemini API のレスポンスを もう少し安定させること。
この三つは優先度高めです。
最後に、 この音声がちゃんと 自然な文章に整形されて、 読みやすいメモになっていたら成功かなと思っています。
もし可能なら、 タイトルは 「VoiceBook LM 開発メモ:ASR と AI 整形の検証」 みたいな感じになると嬉しいです。
文字起こし結果
今日はボイスブック LM のテストも兼ねて今考えてることを音声でメモして行こうと思いますまず最初に今日行って作業振り返りから話します今日は午前中にリアクトネイティブとエキスポを使ったアプリのビルド周りを触っていました EAS ビルドを使って開発ビルドを作ろうとしたんですが NPM の警告がたくさん出てインフライトがディプリケーターだったりり胸付のバージョンが古いとかグローブの性格も出ていました後 Windows 環境のとアセンションふぇーみたいな色も出て喉 JS のバージョン磯ぽいなと感じましたこの辺りは後で整理して Node のバージョンを20系に固定するか nvm をちゃんと使うのかドキュメントにまとめたいと思っています次にボイスブック NM 自体の話をしますこのアプリでは音声を一気に録音してバックエンドに送信して Google Speech to text で文字起こしをしてその後に地味に\nゼロフラッシュを使ってタイトル先生とか本文の整形タグ付けを行う想定です例えば今日やったこととホームがやりたいことと悩んでいることが混ざった音声でもうまく整理してくれるかを試したいですここで今後やりたいことを話します直近ではリアルタイム文字起こしも行ってみたいなと思っています今は一括音声アップロード方式なんですが夜ソケットを使ってストリーミングで文字文字起こしてきたら会議メモとかにも使えそうだなと考えていますあとタグの児童扶養ももっと賢くしたくて例えば開発 react Native 音声認識 AI みたいなタグをユーザーが何もしなくてもつけてくれると嬉しいです少し話題を変えて個人的なメモを残しときます来週までにボイスケイレブの MVP を一旦完成させたいです最低限必要なのは音声録音文字起こし AI 整形一覧表示検索機能ですツールとしては一つ目音声アップロード API\n エラーハンドリング改善フタツメ文字起こしパイ市のリトライ処理見つめジェミニ API のレスポンスをもう少し安定させることこの三つは遊星の高めです最後にこの音声がちゃんと自然な文章に成形されて読みやすいメモになっていたら成功かなと思っていますもし可能ならタイトルはボイスブック LM 開発メモ SR とメモ AI 整形の継承みたいな感じになると嬉しいです以上です
AI整形結果
ボイスブックLM 開発音声メモ\n\nボイスブックLMの開発状況と今後の展望について音声で記録。\n* React NativeアプリのビルドでNode.jsのバージョン問題\n* Google Speech to TextとGemini APIによる文字起こしと整形\n* リアルタイム文字起こし、タグ自動付与の検討\n* 来週までにMVP完成を目指す\n\nTags: Voicebook, AI, Development, Memo
AI整形
えーっと、来月あたりに京都へ旅行に行こうかなって考えていて、
期間は2泊3日くらいを想定しています。
初日はまず嵐山に行きたいなと思っていて、
竹林を歩いたりとか、時間があれば周辺も少し散策できたらいいなって感じです。
2日目は清水寺と祇園あたりを回る予定で、
いわゆる京都っぽい景色をゆっくり見て回りたいなと思っています。
最終日は伏見稲荷に行くつもりで、
あの鳥居がずっと続いているところを一度ちゃんと歩いてみたいなって思ってます。
体力と時間を見ながら、行けるところまで行けたらいいかなと。
宿については、移動しやすそうなので四条あたりで探そうと思っていて、
全体の予算はだいたい5万円くらいを目安に考えています。
そんな感じで、京都旅行の計画を立てているところです。
AI整形後
京都旅行の概要
来月、2泊3日の日程で京都旅行を計画している。 全体の予算は5万円を目安に検討を進めている。
観光スケジュール
1日目
初日は嵐山を訪れる予定だ。 竹林の散策を中心に、時間があれば周辺エリアも巡りたいと考えている。
2日目
2日目は清水寺と祇園を中心に観光する。 京都らしい風情をゆっくりと楽しむ一日とする予定だ。
3日目
最終日には伏見稲荷大社へ足を運ぶ。 千本鳥居を歩くことを目的とし、体力と時間に応じて散策範囲を決める。
宿泊地
宿泊先は移動の利便性を重視し、四条エリアで探す予定だ。
AI整形前
えーっと、今週の買い物なんですけど、まず食品で言うと、牛乳と卵とパンは買っておきたいなと思ってます。
あと、野菜も必要で、キャベツとかにんじんを買う予定です。
それから日用品なんですけど、洗剤がそろそろなくなりそうなので補充したいのと、ティッシュも在庫が少ないので一緒に買っておこうかなと思ってます。
AI整形後
今週の買い物について計画をまとめました。 主に食品と日用品の補充が必要となります。
食品の購入リスト
食品では、牛乳、卵、パンを優先的に購入します。 また、野菜はキャベツとにんじんが必要となるため、これらも購入する予定です。
日用品の補充
日用品では、洗剤の残量が少なくなっているため補充します。 加えて、ティッシュの在庫も減少しているため、この機会に購入する予定です。
TODO
- 食料品(牛乳、卵、パン、キャベツ、にんじん)を購入する
- 日用品(洗剤、ティッシュ)を購入する
AI整形前
えーっと、最近ちょっと思ったんですけど、音声で日記をつけられるアプリがあったら、けっこう便利なんじゃないかなって思ってて。
毎日こう、5分くらいでいいから、その日にあったこととか、感じたことをそのまま話すだけで、AIがいい感じに要約してくれたら楽だなって思うんですよね。
文字で日記を書くのって、正直ちょっと面倒な日もあるじゃないですか。
でも、話すだけなら通勤中とか、寝る前とかでもできそうだなって。
で、あとから読み返したときに、ちゃんと分かる文章にまとまってたら嬉しいなと思ってます。
それに、内容に応じて自動でタグ付けしてくれたり、あとから「あのとき何考えてたっけ」みたいに検索できる機能があったら、日記としても振り返りやすくなる気がします。
ただ記録するだけじゃなくて、自分の考えとか感情を整理するのを手伝ってくれる、そんな感じの音声日記アプリがあったらいいな、って思いました。
AI整形後
音声日記アプリの構想
最近、音声で手軽に日記をつけられるアプリがあれば、非常に便利だと感じています。毎日、約5分程度の短い時間で、その日にあった出来事や感じたことを話すだけで完結するのが理想です。
文字で日記を書くことは、正直なところ面倒に感じる日もありますが、音声入力であればそのハードルを下げられます。通勤中や寝る前など、隙間時間を活用して気軽に利用できるでしょう。
期待する機能
このアプリには、入力された音声をAIが自動で要約し、後から読み返したときに理解しやすい自然な文章にまとめる機能が必要です。これにより、日々の記録が簡潔に整理されます。
また、記録内容に応じて自動でタグ付けされる機能や、過去の記録をキーワードで検索できる機能も備わっていると便利です。これらの機能があれば、「あの時何を考えていたか」といった振り返りが容易になり、日記としての価値が高まります。
アプリの価値
単に日々の出来事を記録するだけでなく、自分の考えや感情を整理する手助けをしてくれるようなアプリを目指したいです。このような音声日記アプリは、忙しい現代において個人の内省を促し、自己理解を深める上で非常に有用だと考えられます。
VoiceBookLM 中間発表
発表日: 2024年12月18日
1. プロジェクト概要
VoiceBookLM は音声メモをAIで自動要約・整理するアプリケーションです。
2. 現在の実装状況(中間発表時点)
2.1 バックエンド(API)
実装完了 API(6/20)
| カテゴリ | API | 説明 |
|---|---|---|
| 認証 | POST /api/auth/google | Google OAuth ログイン |
| 認証 | POST /api/auth/refresh | トークンリフレッシュ |
| 認証 | POST /api/auth/logout | ログアウト |
| 認証 | DELETE /api/auth/account | アカウント削除 |
| 認証 | GET /api/auth/me | ユーザー情報取得 |
| 音声メモ | POST /api/voice/memos | 音声ファイルからメモ生成 |
バックエンド達成率
実装済み: 6 / 20 API(30%)
├── 認証 API: 5/5 ████████████████████ 100%
├── 音声メモ API: 1/1 ████████████████████ 100%
├── メモ API: 0/7 ░░░░░░░░░░░░░░░░░░░░ 0%
├── フォルダ API: 0/4 ░░░░░░░░░░░░░░░░░░░░ 0%
└── タグ API: 0/3 ░░░░░░░░░░░░░░░░░░░░ 0%
2.2 フロントエンド(画面)
実装完了画面(4/12)
| カテゴリ | 画面 | パス | 状態 |
|---|---|---|---|
| 認証 | ログイン | /login | ✅ |
| 録音 | 録音 | /record | ✅ |
| 録音 | 録音確認 | /record/preview | ✅ |
| 録音 | 処理中 | /record/processing | ✅ |
フロントエンド達成率
実装済み: 4 / 12 画面(33%)
├── 認証系: 1/2 ██████████░░░░░░░░░░ 50%
├── メイン系: 0/3 ░░░░░░░░░░░░░░░░░░░░ 0%
├── 録音系: 3/4 ███████████████░░░░░ 75%
└── 設定系: 0/3 ░░░░░░░░░░░░░░░░░░░░ 0%
2.3 実装済み機能の詳細
認証システム(バックエンド完成・フロント一部完成)
- Google OAuth によるソーシャルログイン
- JWT トークンによるセッション管理
- リフレッシュトークンによる自動更新
- セキュアなログアウト処理
- アカウント削除機能
音声メモ生成(バックエンド完成・フロント一部完成)
- 音声ファイルのアップロード
- AI による文字起こし
- 自動要約生成
- 録音〜処理中画面の実装
3. 合評会までの実装予定(全機能完成目標)
3.1 バックエンド(残り14 API)
メモ API(7個)
| メソッド | エンドポイント | 説明 |
|---|---|---|
| GET | /api/memos | メモ一覧取得 |
| GET | /api/memos/{id} | メモ詳細取得 |
| PATCH | /api/memos/{id} | メモ更新 |
| DELETE | /api/memos/{id} | メモ削除 |
| POST | /api/memos/{id}/resummarize | 再要約 |
| GET | /api/memos/{id}/transcription | 文字起こしテキスト取得 |
| POST | /api/memos/search/semantic | 意味検索(AI) |
フォルダ API(4個)
| メソッド | エンドポイント | 説明 |
|---|---|---|
| GET | /api/folders | フォルダ一覧取得 |
| POST | /api/folders | フォルダ作成 |
| PATCH | /api/folders/{id} | フォルダ更新 |
| DELETE | /api/folders/{id} | フォルダ削除 |
タグ API(3個)
| メソッド | エンドポイント | 説明 |
|---|---|---|
| GET | /api/tags | タグ一覧取得 |
| DELETE | /api/tags/{name} | タグ削除 |
| POST | /api/tags/merge | タグ統合 |
バックエンド目標達成率
目標: 20 / 20 API(100%)
├── 認証 API: 5/5 ████████████████████ 100%
├── 音声メモ API: 1/1 ████████████████████ 100%
├── メモ API: 7/7 ████████████████████ 100%
├── フォルダ API: 4/4 ████████████████████ 100%
└── タグ API: 3/3 ████████████████████ 100%
3.2 フロントエンド(残り8画面)
残り実装予定画面
| カテゴリ | 画面 | パス | 説明 |
|---|---|---|---|
| 認証 | スプラッシュ | /splash | アプリ起動時のロード画面 |
| メイン | ホーム | /home | メモ一覧、ディレクトリ表示 |
| メイン | 検索 | /search | キーワード・タグ検索 |
| メイン | メモ詳細 | /memo/:id | Markdown形式でメモ表示 |
| 録音 | 生成結果 | /record/result | 生成されたメモの確認 |
| 設定 | 設定 | /settings | 設定メニュー |
| 設定 | プロフィール | /settings/profile | ユーザー情報表示 |
| 設定 | 言語設定 | /settings/language | 文字起こし言語選択 |
フロントエンド目標達成率
目標: 12 / 12 画面(100%)
├── 認証系: 2/2 ████████████████████ 100%
├── メイン系: 3/3 ████████████████████ 100%
├── 録音系: 4/4 ████████████████████ 100%
└── 設定系: 3/3 ████████████████████ 100%
4. 開発ロードマップ
┌───────────────────────────────────────────────────────────────────────┐
│ 開発タイムライン │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ 中間発表 ───────────────────────────────────────► 合評会 │
│ (12/18) (全機能完成) │
│ │
│ 【バックエンド】 │
│ ✅ 認証 API (5個) │
│ ✅ 音声メモ API (1個) │
│ ┌────────────────────────────────────────────┐ │
│ │ 🚧 メモ API (7個) │ │
│ │ 🚧 フォルダ API (4個) │ │
│ │ 🚧 タグ API (3個) │ │
│ └────────────────────────────────────────────┘ │
│ │
│ 【フロントエンド】 │
│ ✅ ログイン画面 (1画面) │
│ ✅ 録音フロー (3画面) │
│ ┌────────────────────────────────────────────┐ │
│ │ 🚧 スプラッシュ画面 (1画面) │ │
│ │ 🚧 メイン画面 (3画面) │ │
│ │ 🚧 生成結果画面 (1画面) │ │
│ │ 🚧 設定画面 (3画面) │ │
│ └────────────────────────────────────────────┘ │
│ ↓ │
│ 全機能完成 │
│ (20 API + 12 画面) │
│ │
└───────────────────────────────────────────────────────────────────────┘
5. まとめ
現在の進捗状況
| 項目 | 中間発表時点 | 合評会目標 |
|---|---|---|
| バックエンド | 6 / 20 API(30%) | 20 / 20 API(100%) |
| フロントエンド | 4 / 12 画面(33%) | 12 / 12 画面(100%) |
中間発表時点で完成している機能
| カテゴリ | バックエンド | フロントエンド |
|---|---|---|
| 認証 | ✅ 完成(5 API) | 🚧 一部完成(1/2画面) |
| 音声メモ生成 | ✅ 完成(1 API) | 🚧 一部完成(3/4画面) |
| メモ管理 | 🚧 未着手 | 🚧 未着手 |
| フォルダ | 🚧 未着手 | 🚧 未着手 |
| タグ | 🚧 未着手 | 🚧 未着手 |
| 設定 | - | 🚧 未着手 |
次のマイルストーンまでの主要タスク
バックエンド
-
メモ CRUD 機能の実装
- 一覧取得・詳細取得・更新・削除
-
再要約・文字起こし機能の実装
- 既存メモの要約を再生成
- 文字起こしテキスト取得
-
意味検索機能の実装
- AIによるセマンティック検索
-
フォルダ機能の実装
- メモの整理・分類機能
-
タグ機能の実装
- タグ一覧・削除・統合
フロントエンド
-
メイン画面の実装
- ホーム(メモ一覧)
- 検索画面
- メモ詳細画面
-
録音フローの完成
- 生成結果画面
-
認証フローの完成
- スプラッシュ画面
-
設定画面の実装
- 設定メニュー
- プロフィール
- 言語設定
付録: ステータス凡例
| マーク | 意味 |
|---|---|
| ✅ | 実装済み |
| 🚧 | 未実装(MVP必須) |
| 📋 | 未実装(追加機能) |
| 🔮 | 将来実装予定 |
VoiceBookLM 中間発表
現在実装済み
- Google ログイン機能
- 音声録音・アップロード
- AI 文字起こし・要約生成
- ログイン画面
- 録音〜処理中画面
合評会までに実装予定
- メモ一覧・詳細・編集・削除
- 再要約・意味検索
- フォルダ管理
- タグ管理
- ホーム・検索・メモ詳細画面
- 設定画面
全体サマリー
| 機能 | 現在 | 合評会目標 |
|---|---|---|
| 認証 | ほぼ完成 | 完成 |
| 音声メモ生成 | ほぼ完成 | 完成 |
| メモ管理 | 未着手 | 完成 |
| フォルダ | 未着手 | 完成 |
| タグ | 未着手 | 完成 |
| 設定 | 未着手 | 完成 |
VoiceBookLM 操作説明書
1. はじめに
VoiceBookLMは、話すだけで整理されたメモが自動で作られるAI搭載ボイスメモアプリです。 本書では、アプリの基本的な操作方法について説明します。
2. アプリ起動・ログイン
2.1 アプリの起動
- ホーム画面で「VoiceBookLM」アイコンをタップします
- ウェルカム画面が表示されます
2.2 ログイン
- ウェルカム画面で「Googleでサインイン」ボタンをタップします
- Googleアカウントを選択してログインします
- ログイン完了後、ホーム画面に遷移します
3. ホーム画面の操作
3.1 画面構成
| 要素 | 説明 |
|---|---|
| ヘッダー | アプリロゴ、検索アイコンを表示 |
| メモ一覧 | 保存されたメモをカード形式で表示 |
| 録音ボタン | 画面下部中央の丸いボタン |
3.2 メモの確認
- メモ一覧から確認したいメモをタップします
- メモ詳細画面で内容を確認できます
3.3 メモの検索
- ヘッダーの検索アイコンをタップします
- 検索画面でキーワードを入力します
- 該当するメモが一覧表示されます
4. 録音操作
4.1 録音の開始
- ホーム画面下部の録音ボタン(マイクアイコン)をタップします
- 録音画面に遷移し、自動的に録音が開始されます
- 画面に録音時間が表示されます
4.2 録音の一時停止・再開
- 一時停止:一時停止ボタンをタップします
- 再開:再生ボタンをタップして録音を再開します
4.3 録音の完了とAI整形
- 録音が完了したら「完了してAI整形する」ボタンをタップします
- ホーム画面に戻り、画面下部にAI処理中のトーストが表示されます
- 処理完了後、メモ一覧に自動整形されたメモが追加されます
4.4 録音のキャンセル
- 録音を破棄する場合は「キャンセル」ボタンをタップします
- 確認ダイアログで「破棄」を選択すると録音データが削除されます
5. AI自動整形機能
5.1 自動生成される項目
| 項目 | 説明 |
|---|---|
| タイトル | メモ内容から自動生成 |
| 本文 | マークダウン形式で整形 |
| タグ | 内容に基づいて自動付与 |
5.2 処理時間
- 通常30秒以内で処理が完了します
- 処理中も他の操作が可能です
6. メモの管理
6.1 メモの編集
- メモ詳細画面で「編集」ボタンをタップします
- タイトル、本文、タグを編集できます
- 「保存」ボタンで変更を保存します
6.2 メモの削除
- メモ詳細画面で「削除」ボタンをタップします
- 確認ダイアログで「削除」を選択します
7. トラブルシューティング
よくある問題と解決方法
| 問題 | 解決方法 |
|---|---|
| 録音が開始されない | マイク権限を確認してください |
| AI整形が完了しない | ネットワーク接続を確認してください |
| ログインできない | Googleアカウント設定を確認してください |
8. お問い合わせ
アプリに関するお問い合わせは、設定画面の「サポート」からご連絡ください。
最終更新日:2026年1月20日
VoiceBookLM ビルド手順書
1. 概要
VoiceBookLMは以下の2つのリポジトリで構成されています。 各リポジトリのREADMEに詳細なビルド手順が記載されています。
2. リポジトリ一覧
フロントエンド(モバイルアプリ)
| 項目 | 内容 |
|---|---|
| リポジトリ | voicebooklm-frontend |
| 技術スタック | React Native + Expo |
| 詳細手順 | READMEを参照 |
バックエンド
| 項目 | 内容 |
|---|---|
| リポジトリ | voicebooklm-backend |
| 技術スタック | Spring Boot (Kotlin) + PostgreSQL |
| 詳細手順 | READMEを参照 |
3. システム構成
┌─────────────────────────────────────────────────────┐
│ VoiceBookLM │
├──────────────────────┬──────────────────────────────┤
│ 📱 Frontend │ 🖥️ Backend │
│ React Native │ Spring Boot │
│ + Expo │ + PostgreSQL │
└──────────────────────┴──────────────────────────────┘
4. 参考リンク
- フロントエンド: https://github.com/assari-harassment/voicebooklm-frontend
- バックエンド: https://github.com/assari-harassment/voicebooklm-backend
最終更新日:2026年1月20日
VoiceBookLM インストール手順書
1. 概要
VoiceBookLMは以下のプラットフォームで利用可能です。
2. 公開状況
| プラットフォーム | 状況 | 公開予定日 |
|---|---|---|
| 🌐 Web版 | 公開予定 | 2026年1月26日 |
| 🍎 App Store (iOS) | 準備中 | 未定 |
| 🤖 Google Play (Android) | 準備中 | 未定 |
3. Web版
アクセス方法
公開後、以下のURLからアクセスできます:
URL: (2026年1月26日 公開予定)
動作環境
| 項目 | 要件 |
|---|---|
| 対応ブラウザ | Chrome、Safari、Firefox、Edge(最新版推奨) |
| マイク | 音声録音に必要 |
利用開始手順
- WebブラウザでURLにアクセスします
- 「Googleでサインイン」をクリックします
- Googleアカウントでログインします
- ログイン完了後、すぐに利用開始できます
4. iOS版(App Store)
⏳ 準備中 - 公開日が決まり次第、更新します web 公開予定
公開後の予定
- App Storeで「VoiceBookLM」を検索してインストール
動作環境(予定)
| 項目 | 要件 |
|---|---|
| 対応OS | iOS 15.0以上 |
| 対応デバイス | iPhone 8以降 |
5. Android版(Google Play)
⏳ 準備中 - 公開日が決まり次第、更新します
公開後の予定
- Google Playストアで「VoiceBookLM」を検索してインストール
動作環境(予定)
| 項目 | 要件 |
|---|---|
| 対応OS | Android 10.0以上 |
6. 初回起動時の設定
権限の許可
アプリ利用時に以下の権限を許可してください:
| 権限 | 用途 | 必須 |
|---|---|---|
| マイク | 音声録音 | ○ |
| 通知 | AI処理完了通知 | 推奨 |
Googleアカウントでログイン
- 「Googleでサインイン」をタップ/クリックします
- 使用するGoogleアカウントを選択します
- ログイン完了後、ホーム画面に遷移します
7. サポート
ご不明な点がございましたら、以下までお問い合わせください:
- GitHub Issues: https://github.com/assari-harassment/voicebooklm-frontend/issues
最終更新日:2026年1月20日
VoiceNoteLM デプロイシステム構成図
全体構成
外部サービス連携
セキュリティグループ構成
データフロー
1. ユーザー認証フロー
2. 音声文字起こしフロー
コンポーネント詳細
Frontend (Vercel)
| 項目 | 値 |
|---|---|
| フレームワーク | React Native Web / Expo |
| ホスティング | Vercel |
| ドメイン | voicenotelm.app |
| SSL | Vercel自動SSL |
| ビルド | 自動(Git push時) |
環境変数:
| 変数名 | 値 |
|---|---|
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID | Google OAuth Client ID |
EXPO_PUBLIC_API_BASE_URL | https://api.voicenotelm.app |
EXPO_PUBLIC_WS_BASE_URL | wss://api.voicenotelm.app |
Backend (AWS EC2)
| 項目 | 値 |
|---|---|
| インスタンスタイプ | t3.micro |
| AMI | Amazon Linux 2023 |
| Java | Amazon Corretto 21 |
| フレームワーク | Spring Boot (Kotlin) |
| パス | /opt/voicenotelm/ |
| サービス管理 | systemd (voicenotelm) |
Database (AWS RDS)
| 項目 | 値 |
|---|---|
| エンジン | PostgreSQL 16 |
| インスタンスクラス | db.t4g.micro |
| ストレージ | 20 GiB gp2 |
| 自動バックアップ | 無効 |
| パブリックアクセス | なし |
| データベース名 | voicenotelm |
Nginx設定
server {
listen 80;
server_name api.voicenotelm.app;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket対応
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
DNS設定 (Cloudflare)
| レコード | タイプ | 名前 | 値 | Proxy |
|---|---|---|---|---|
| API | A | api | EC2 Elastic IP | DNS only (灰色) |
| Frontend | CNAME | @ | cname.vercel-dns.com | DNS only (灰色) |
| Frontend | CNAME | www | cname.vercel-dns.com | DNS only (灰色) |
想定コスト (月額)
| サービス | 費用 |
|---|---|
| EC2 t3.micro | 無料枠(750時間/月) |
| RDS db.t4g.micro | 無料枠(750時間/月) |
| Elastic IP | 無料(EC2起動中) |
| Vercel | 無料(Hobby) |
| Cloudflare | 無料 |
| 合計 | $0〜5 |
運用コマンド
EC2操作
# SSH接続
ssh -i <your-key.pem> ec2-user@<Elastic IP>
# アプリケーション再起動
sudo systemctl restart voicenotelm
# ステータス確認
sudo systemctl status voicenotelm
# ログ確認
sudo journalctl -u voicenotelm -n 50 --no-pager
# メモリ確認
free -h
RDS接続
# EC2経由でRDSに接続
psql -h <RDSエンドポイント> -U <username> -d <database>
デプロイ手順
# ローカルでビルド
cd voicebooklm-backend
./gradlew bootJar
# EC2に転送
scp -i <your-key.pem> build/libs/*.jar ec2-user@<IP>:/path/to/app.jar
# EC2で再起動
sudo systemctl restart voicenotelm