2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

さくらのAI Engine × Three.js(VRM)でモーションと音声が同期する3D AIチャットを作ってみた

2
Last updated at Posted at 2026-08-11

さくらインターネットの「さくらのAI Engine」を活用した記事投稿キャンペーン参加記事です。

今回は、Webブラウザ上で動作する 3Dアバター(VRM)+モーション(VRMA)+音声合成(VOICEVOX) を組み合わせたInteractive AIチャットアプリを作成し、その頭脳(LLM)として さくらのAI Engine を組み込んでみました。


1. 開発のきっかけと使用素材

VOICEVOX: ナースロボ_タイプT の声が好きで、「この声でリアクションしてくれる自分専用の3DのAIキャラクターを作りたい!」と思ったのが開発のきっかけです。
アバターは VRoid Studio を使用して自作し、動きには以下の素敵なモーション素材をお借りしました。


2. 実際の動作(デモ動画)

YouTubeに実際の動作映像をアップロードしました。AIの応答に合わせて、ナースロボタイプTの声で喋りながらアバターが自然にモーション(Vサインやお辞儀など)を行います。


3. アプリの構成と「さくらのAI Engine」採用の理由

  • フロントエンド: HTML5, Three.js (@pixiv/three-vrm, @pixiv/three-vrm-animation)
  • バックエンド: Node.js / Express
  • LLM (脳): さくらのAI Engine (gpt-oss-120b) ※Gemini / Ollama と切り替え可能
  • 音声合成 (声): VOICEVOX (ローカルサーバー)

なぜ「さくらのAI Engine」を使ったか?

  1. 完全無料枠の安心感
    • 「基盤モデル無償プラン」は月3,000リクエストまで無料で使えます。無料枠を超えても勝手に従量課金されずレートリミットがかかる仕様なので、個人開発でも安心して使えます。
  2. OpenAI互換APIで導入が超簡単
    • バックエンドの呼び出しコードはOpenAIの標準仕様(v1/chat/completions)と同じなので、非常に短時間で組み込むことができました。

4. 実装のポイント

① API認証トークンの設定

さくらのAI Engine(OpenAI互換API)の認証キーは、アクセスキー:シークレット の形式で結合して指定します。

.env

PORT=3000
SAKURA_AI_API_KEY=your_access_key:your_secret_key
SAKURA_AI_MODEL=gpt-oss-120b

② バックエンド(Node.js/Express)での転送処理

フロントエンドから届いたメッセージを、OpenAI互換エンドポイントへ転送します。

server.js (抜粋)

app.post('/api/chat/sakura', async (req, res) => {
  const apiKey = process.env.SAKURA_AI_API_KEY;
  const model = process.env.SAKURA_AI_MODEL || 'gpt-oss-120b';

  if (!apiKey) {
    return res.status(500).json({ error: { message: '.env が未設定です' } });
  }

  try {
    const response = await fetch('[https://api.ai.sakura.ad.jp/v1/chat/completions](https://api.ai.sakura.ad.jp/v1/chat/completions)', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
      },
      body: JSON.stringify({
        model: model,
        messages: req.body.messages,
        response_format: req.body.response_format,
        temperature: 0.7
      })
    });

    const data = await response.json();
    res.json(data);
  } catch (err) {
    res.status(500).json({ error: { message: err.message } });
  }
});

③ システムプロンプトで「JSONフォーマット」を強制

アバターの動き(モーション)と発言内容を同時に制御するため、以下のようなシステムプロンプトを渡しています。

【応答ルール】
返答は必ず以下のJSON形式のみで出力してください。
{
  "vrma": "モーションID",
  "text": "会話の返答文"
}

【選択可能なモーションID一覧】
- VRMA_01: 通常待機
- VRMA_02: 挨拶・お辞儀
- VRMA_03: 喜ぶ・Vサイン
...

5. LLM比較:さくらのAI Engine vs Gemini vs Ollama(ローカル)

本アプリではプロバイダーを簡単に切り替えられるように作ったため、3つのLLMを比較してみました。

比較項目 さくらのAI Engine (gpt-oss-120b) Gemini (gemini-3.6-flash) Ollama (llama3-elyza-jp)
応答スピード ★★★★☆ (非常に快適) ★★★★★ (爆速) ★★☆☆☆ (PCスペック依存)
JSONフォーマット遵守率 ★★★★★ (崩れなし) ★★★★★ (Structured Output対応) ★★★☆☆ (時々テキストが漏れる)
会話の自然さ ★★★★☆ (文脈に合った返答) ★★★★☆ (少し淡々としやすい) ★★★★☆ (キャラ設定は得意)
コスト・安心感 ★★★★★ (無料枠あり・超過課金なし) ★★★★☆ (従量課金注意) ★★★★★ (完全ローカル無料)

所感:
gpt-oss-120b は1200億パラメータ規模の大型モデルということもあり、日本語の理解力や文脈に応じたモーション指定(JSONフォーマット)の安定性が抜群でした。クラウドAPIでありながら勝手に課金される心配がないのも、開発者体験として非常に魅力的です。

最新モデルを一定枠まで無料で使える Gemini と比較すると性能面で譲る部分もありますが、さくらのAI Engine と Gemini をフォールバック(予備)や用途に応じて併用・使い分けることで、無料枠の制限をほぼ気にせず運用できる点が大きなメリットだと感じました。

なお、Ollama によるローカルモデルは、家庭用の一般的なノートPC環境では応答に30秒以上かかってしまいました。リアルタイムな会話レスポンスを重視するインタラクティブなアプリにおいては、クラウドAPI(さくらのAI Engine / Gemini)を利用するのが現実的で快適です。


6. まとめ

「ナースロボタイプTの声で話す自分専用の3D AIパートナーを作りたい」という目的からスタートした開発ですが、「さくらのAI Engine」を導入したことで、コストのリスクなく高品質なAIエージェントを作ることができました。

OpenAI互換仕様のおかげで組み込みの手間がほとんどかからないため、アバターアプリに限らずさまざまなWebツール・プロダクトにAIを組み込みたい方にも非常におすすめです!

また、今回は既存の素敵なモーションをお借りしましたが今後は自分でもモーション制作を勉強し、より自分専用のAIパートナーへと育てていきたいです。みなさんもぜひ、この記事を参考に自分だけのAIパートナーを作ってみてくださいね!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?