Pocket CFO — ElevenLabs 統合アーキテクチャ

3Dアバター × RAG知識ベース × 高品質日本語音声

1. 全体構成

Browser
フロントエンド
チャットUI
テキスト入力 / 表示
SSEストリーミング受信
Web Speech STT
音声入力 → テキスト変換
(Chrome, 無料)
TalkingHead 3D
Three.js アバター描画
ビジム同期リップシンク
表情・ジェスチャー制御
Audio再生
Web Audio API
ElevenLabs音声チャンク再生
テキスト
JSON
SSE
テキスト+
音声+
タイムスタンプ
Local Server
FastAPI バックエンド
RAG検索エンジン
ChromaDB (3,507チャンク)
Voyage Finance 2 埋め込み
書籍20冊 + YouTube知識
文バッファ
Claudeストリーミング受信
「。」「!」「?」で文を区切り
1文完成 → ElevenLabsへ送信
音声変換パイプライン
文字タイムスタンプ → ビジムマップ
音声Base64エンコード
SSEイベント生成
外部API
サービス連携
Claude API
Sonnet 4
ストリーミング応答
RAGコンテキスト注入
ElevenLabs API
Flash v2.5 (低遅延)
stream-with-timestamps
文字タイムスタンプ付き音声
Voyage AI
voyage-finance-2
検索クエリ埋め込み

2. リクエストの流れ(シーケンス)

ユーザー
ブラウザ
FastAPI
外部API
「WACCの計算方法を教えて」(テキスト or 音声)
POST /api/chat { message, history }
RAG検索
Voyage: query埋め込み
ChromaDB検索 → 上位5件取得
Claude ストリーミング
Claude API (system + RAG + user)
← テキストチャンク (streaming)
文バッファで「。」まで蓄積
文1 完成 → ElevenLabs
SSE: event=text「WACCとは...」
ElevenLabs: 文1テキスト送信
← 音声 + 文字タイムスタンプ
音声再生 + リップシンク
SSE: event=audio { base64, timestamps }
文字→ビジムマッピング
Audio API再生 + TalkingHead同期
🔊 アバターが話す
👄 口がシンクロ
並行して文2, 文3を
Claudeが生成中...

3. レイテンシ(体感速度)

RAG検索
Voyage
~200ms
Claude (文1まで)
Claude TTFB + 文1生成
~1.0s
ElevenLabs 文1
75ms
~75ms
🔊 音声再生開始
文1 再生 → 文2 再生 → 文3...
Claude 文2,3...
並行生成(文1再生中に完了)
0s0.5s1.0s1.5s2.0s2.5s3.0s3.5s4.0s

体感レイテンシ: 約1.3秒

ユーザーが質問してから音声が始まるまで。文1が再生されている間に残りの文が並行で生成・変換されるため、途切れなく会話が続きます。

4. リップシンクの仕組み

1
ElevenLabsが文字タイムスタンプを返す
/stream-with-timestamps APIで音声と同時に各文字の開始・終了時刻(秒)を取得。
例: 「W」0.00s, 「A」0.08s, 「C」0.15s...
2
日本語文字 → ビジム変換
ひらがな/カタカナは母音でグルーピング:
あ行(あかさたな...) → 口を開く
い行(いきしちに...) → 横に広げる
う行(うくすつぬ...) → 丸める
え行 → 半開き
お行 → 丸く開く
3
TalkingHead speakAudio()
タイムスタンプ付き単語リストと音声AudioBufferを渡す。
TalkingHeadが自動的にOculusビジムブレンドシェイプを補間してアニメーション。
4
同期再生
Web Audio APIで音声再生とTalkingHeadのビジムアニメーションが同じタイムラインで進行。
音声に合わせて口が動く。

5. SSEイベント設計

イベント名 タイミング データ ブラウザ側の処理
text Claudeからチャンク受信時 { "text": "WACCとは" } チャット欄にリアルタイム表示
audio ElevenLabsから音声変換完了時 { "audio": "base64...", "timestamps": [...], "text": "文1全文" } AudioBuffer作成 → 再生キューへ
viseme audioと同時 { "words": [...], "wtimes": [...], "wdurations": [...] } TalkingHead speakAudio()に渡す
done 全文生成完了時 { "full_text": "..." } 会話履歴に保存
error エラー発生時 { "error": "..." } エラーメッセージ表示

6. 必要なAPIキー

キー 用途 取得先 無料枠
ANTHROPIC_API_KEY Claude API (LLM応答生成) console.anthropic.com $5クレジット(新規)
ELEVENLABS_API_KEY 音声合成 + タイムスタンプ elevenlabs.io 10,000文字/月
VOYAGE_API_KEY RAG検索クエリ埋め込み dash.voyageai.com ✅ 設定済み

7. ファイル構成

CFO/webapp/
├── server.py            # FastAPI: Claude + RAG + ElevenLabs + SSE
│   ├── POST /api/chat     # メインチャット(SSEストリーミング)
│   ├── GET  /api/health   # ヘルスチェック
│   └── GET  /              # 静的ファイル配信
├── requirements.txt
└── static/
    ├── index.html         # メインページ
    ├── css/
    │   └── style.css      # ダークテーマ
    └── js/
        ├── app.js         # 初期化・統合
        ├── chat.js        # SSE受信 + チャットUI
        ├── voice.js       # STT + 音声再生キュー
        └── avatar.js      # TalkingHead + ビジムマッピング

8. コスト試算

月間利用想定: 1日10回 × 30日 = 300回の会話

1回の回答: 約200文字(3-5文)

サービス消費量月額
Claude API (Sonnet)~300回 × 2K tokens~$3-5
ElevenLabs300回 × 200文字 = 60,000文字$5 (Starterプラン)
Voyage AI300回 × 1クエリ~$0.1
合計~$8-10/月