What Can You Build?

Connect Kit gets a talking 3D avatar on screen in under 15 minutes — and gives you a full platform to extend it as far as you need. Here is what is available today and what is on the roadmap.

1 — Out-of-the-Box

Everything you need for a lifelike avatar experience — ready to deploy the moment you pick your configuration.

🧑‍🎨

Avatar Catalog

Curated cast of realistic humans, cartoon characters, and VRM avatars. Pick one from the catalog and it's on-screen in minutes.

🎙️

Voice — Azure & Google TTS

Rich, human-sounding voices from Azure and Google TTS. Speech automatically drives the avatar's lip-sync — no extra setup required.

🤖

Chatbot

Upload a knowledge file, wire simple tool calls, and pair with the 3D Avatar for a fully voiced AI agent — no extra backend required.

🌐

Built to Run Everywhere

Focus on building your product — we handle the rest. All features run reliably on Chrome, Safari, and Edge across desktop and mobile with no platform workarounds needed.

2 — Integration with Your Own
🧠

Bring Your Own LLM

Use any LLM. Embed motion cues inline via Markup Motion Language so the avatar's body language matches the conversation.

🔊

Bring Your Own Voice

Pass your own audio (an ArrayBuffer from any TTS service or pre-recorded clip) directly via presenter.presentWithAudio(). The avatar lip-syncs to your audio and the Motion Director still drives gestures and expressions from the text — no Perxona TTS required.

🪆

Bring Your Own Avatar (VRM 1.0)

Upload a VRM 1.0 character to match your brand or audience and make it speak.

3 — Presentation Engine

Real-time avatar performances that stream instantly — no large file downloads, no video buffering, no game-engine install. The avatar responds the moment you call present().

🎬

In-house Motion Director

The engine reads the text and selects matching body motion and facial expressions automatically — the avatar's face and body react to what it's saying.

✏️

Be your own Motion Director

Override motion timing at the sentence level using Markup Motion Language — full creative control in plain text.

// Presentation Engine — available now
const presenter = document.querySelector("sv-presenter");

button.addEventListener("click", async () => {
  await presenter.resumeAudioPlayback();
  await presenter.initialize(connectToken, { avatarId, sceneId, voiceId });
  presenter.present("Hello world! I'm Perxona agent and I can talk to you.");
});
→ Quick Start

你能用 Connect Kit 做什麼?

不到 15 分鐘,一個會說話的 3D 虛擬人就能上線——還有完整的平台供你持續擴展。以下是現在可用的功能,以及即將推出的能力。

1 — 開箱即用

打造生動虛擬人體驗所需的一切——選好設定,立即上線。

🧑‍🎨

Avatar 目錄

精選的寫實人物、卡通風格、VRM 角色,從目錄挑選一個,幾分鐘內就在螢幕上。

🎙️

語音 — Azure & Google TTS

來自 Azure 與 Google TTS 的豐富真人語音。語音自動驅動角色的口型同步(Lip-sync)——無需額外設定。

🤖

Chatbot

上傳 knowledge file、設定簡單的 tool call,搭配 3D Avatar 打造全語音 AI 代理——不需要自建後端。

🌐

隨處穩定運作

你只需專注在打造自己的產品,其餘的我們來處理。所有功能穩定運作在 Chrome、Safari、Edge 的桌機與手機上,無需任何平台相容性處理。

2 — 與自有系統整合
🧠

接入你的 LLM

使用任何 LLM。透過 Markup Motion Language 在對話文字中內嵌動作指令,讓角色肢體語言與對話同步。

🔊

接入你的語音

透過 presenter.presentWithAudio() 直接傳入自己的音訊(任何 TTS 服務或預錄音檔的 ArrayBuffer)。 Avatar 對你的音訊做 口型同步,Motion Director 仍根據文字驅動肢體動作與表情——不需要 Perxona TTS。

🪆

接入你的 Avatar(VRM 1.0)

上傳 VRM 1.0 角色,讓你的產品更貼近你的品牌與客戶需求。

3 — 表演引擎

即時串流的角色表演——不用像影片串流或遊戲引擎一樣事先下載大型檔案。呼叫 present() 的瞬間,角色立即回應。

🎬

內建 Motion Director

引擎讀取文字語意,自動挑選最合適的肢體動作與臉部表情——角色的表情和動作會配合說話內容即時反應。

✏️

自訂 Motion Director

透過 Markup Motion Language 在句子層級自訂動作時間點——用純文字就能完全掌控角色表演。

// 表演引擎 — 現在就可以用
const presenter = document.querySelector("sv-presenter");

button.addEventListener("click", async () => {
  await presenter.resumeAudioPlayback();
  await presenter.initialize(connectToken, { avatarId, sceneId, voiceId });
  presenter.present("我想要吃早餐。");
});
→ 快速開始

Connect Kit で何が作れる?

15 分以内にしゃべる 3D アバターをオンラインにできます——さらに必要なだけ拡張できるプラットフォームも揃っています。現在利用可能な機能と近日公開予定の機能をご紹介します。

1 — すぐに使える

リアルなアバター体験に必要なすべてが揃っています——設定を選ぶだけですぐにデプロイできます。

🧑‍🎨

アバターカタログ

リアル系・カートゥーン系・VRM キャラの厳選キャスト。カタログから選ぶだけで数分で画面に登場します。

🎙️

音声 — Azure & Google TTS

Azure と Google TTS のリアルな人声。音声がアバターのリップシンクを自動駆動——追加設定は不要です。

🤖

チャットボット

ナレッジファイルをアップロードし、シンプルなツールコールを設定して 3D アバターと組み合わせると、フルボイスの AI エージェントが完成——バックエンド不要。

🌐

どこでも安定動作

開発者は自分のプロダクト作りに集中するだけ。すべての機能が Chrome・Safari・Edge のデスクトップ/モバイルで安定して動作し、プラットフォームごとの対応は不要です。

2 — 自前のものを統合
🧠

独自 LLM を接続

任意の LLM が使えます。Markup Motion Language でモーションキューをテキスト中に埋め込み、会話とアバターの動きを同期させます。

🔊

独自音声を使用

presenter.presentWithAudio() に任意の TTS サービスや録音済み音声の ArrayBuffer を直接渡すだけ。アバターがリップシンクし、 Motion Director がテキストから動きと表情を自動生成します——Perxona TTS は不要です。

🪆

独自アバター(VRM 1.0)

VRM 1.0 キャラをアップロードして、ブランドや顧客に合ったアバターで話させることができます。

3 — プレゼンテーションエンジン

リアルタイムのアバターパフォーマンスを即座にストリーミング——動画バッファリングもゲームエンジンのインストールも不要。present() を呼んだ瞬間にアバターが応答します。

🎬

インハウス Motion Director

エンジンがテキストの意味を読み取り、最適なボディモーションと表情を自動選択——アバターの顔と体が発話内容に合わせてリアルタイムに反応します。

✏️

カスタム Motion Director

Markup Motion Language を使って文単位でモーションのタイミングを制御——プレーンテキストで完全な演出が可能です。

// プレゼンテーションエンジン — 今すぐ使えます
const presenter = document.querySelector("sv-presenter");

button.addEventListener("click", async () => {
  await presenter.resumeAudioPlayback();
  await presenter.initialize(connectToken, { avatarId, sceneId, voiceId });
  presenter.present("朝ごはんが食べたいです。");
});
→ クイックスタート
Developer Handbook

Perxona Connect Kit

Build AI-powered avatars in minutes.

A minimal, self-contained sample that integrates the Perxona Connect API and the <sv-presenter> avatar Web Component. Pick an avatar, scene, and voice — make it speak. Clone to talking avatar in 5–15 minutes.

整合 Perxona Connect API<sv-presenter> 虛擬人 Web Component 的輕量範例。選擇 Avatar、場景與聲音,讓虛擬人開口說話。從 clone 到說話的虛擬人,只需 5–15 分鐘

Perxona Connect API<sv-presenter> アバター Web コンポーネントを統合した軽量サンプルです。アバター・シーン・ボイスを選んでしゃべらせましょう。クローンからしゃべるアバターまで 5〜15 分で完成します。

What is Perxona Connect Kit?

The Connect Kit is a ready-to-run Express + vanilla JS sample app that demonstrates the end-to-end integration of the Perxona Presentation Service (Connect API) and the <sv-presenter> Web Component. It is built for hackathons and partner integrations — fast to clone, easy to read, and designed as a starting point rather than a production-ready app.

There are two moving parts:

  • server.mjs — an Express backend that authenticates with the Connect API using your service credentials, caches a bearer token, and exposes a small proxy API for the browser.
  • public/demos/basic/app.js — a zero-dependency vanilla JS frontend that drives the <sv-presenter> Web Component loaded from Perxona's CDN.

什麼是 Perxona Connect Kit?

Connect Kit 是一個可立即執行的 Express + 原生 JS 範例應用程式,展示了 Perxona Presentation Service(Connect API)<sv-presenter> Web Component 的完整端到端整合流程。專為黑客松與合作夥伴整合設計——快速 clone、易於閱讀,是起點而非生產就緒應用程式。

💡
術語說明:本文中的「虛擬人」與技術文件、UI 和 API 中的 Avatar 指的是同一個角色資源。為了與 Avatar 下拉選單、API 欄位及程式碼保持一致,這些技術名稱會維持 英文 Avatar

主要有兩個部分:

  • server.mjs — 使用服務憑證向 Connect API 進行身份驗證的 Express 後端,快取 Bearer Token,並為瀏覽器公開小型代理 API。
  • public/demos/basic/app.js — 驅動從 Perxona CDN 載入的 <sv-presenter> Web Component 的零依賴原生 JS 前端。

Perxona Connect Kit とは?

Connect Kit は、Perxona Presentation Service(Connect API)<sv-presenter> Web コンポーネントのエンドツーエンド統合を示す、すぐに動かせる Express + バニラ JS サンプルアプリです。ハッカソンやパートナー統合向けに設計されており、素早くクローンでき、コードが読みやすく、出発点として使うことを想定しています。

主な構成要素は 2 つです:

  • server.mjs — サービス認証情報で Connect API に認証し、Bearer トークンをキャッシュして、ブラウザ向けプロキシ API を提供する Express バックエンド。
  • public/demos/basic/app.js — Perxona の CDN から読み込まれた <sv-presenter> Web コンポーネントを操作するゼロ依存のバニラ JS フロントエンド。

Get Your API Credentials

Before you can run the Connect Kit sample, you need a Perxona account. Registration is fully self-service — no approval or invite required. The three steps below take about two minutes.

🔑
One-time setup. Once you have your email and password, skip straight to Quick Start — the Express sample handles all subsequent logins automatically.
  1. Request a signup token

    Send your email address to the signup endpoint. The server returns 201 with no body and sends a plain-text token to your inbox.

    curl -X POST https://console.perxona.ai/asia/api/v1/connect/auth/signup \
      -H "Content-Type: application/json" \
      -d '{"email": "you@example.com"}'
  2. Check your email and copy the token

    Open the email from Perxona. It contains a short token string — not a clickable link. Copy the token; you will paste it in the next step.

    Perxona verification email showing the plain-text token
  3. Complete signup and set your password

    Pass the token, your email (used as username), and a password you choose. A successful response returns your access_token.

    curl -X POST https://console.perxona.ai/asia/api/v1/connect/auth/confirm-signup \
      -H "Content-Type: application/json" \
      -d '{
        "token":    "YOUR_TOKEN_FROM_EMAIL",
        "username": "you@example.com",
        "password": "YourPassword123!"
      }'

    Response: {"access_token": "eyJ..."}. Your account is now active.

Done. Head to Quick Start and fill in PERXONA_CONNECT_EMAIL and PERXONA_CONNECT_PASSWORD in your .env — the sample server handles all subsequent logins for you.

取得 API 憑證

在執行 Connect Kit 範例之前,你需要一個 Perxona 帳號。註冊完全自助——無需審核或邀請碼,以下三個步驟約需兩分鐘。

🔑
一次性設定。 取得帳號密碼後,直接前往 快速開始——Express 範例會自動幫你處理後續所有登入。
  1. 請求 signup token

    將你的 email 傳送至 signup 端點。伺服器回傳 201(無回應內容),並將 純文字 token 寄至你的信箱。

    curl -X POST https://console.perxona.ai/asia/api/v1/connect/auth/signup \
      -H "Content-Type: application/json" \
      -d '{"email": "you@example.com"}'
  2. 收信並複製 token

    開啟來自 Perxona 的信件。信中有一段短字串 token—— 不是可點擊的連結。複製這段 token,下一步會用到。

    Perxona 驗證信件,顯示純文字 token
  3. 完成註冊並設定密碼

    傳入 token、你的 email(作為 username)以及你設定的密碼。 成功後回傳 access_token,帳號即啟用。

    curl -X POST https://console.perxona.ai/asia/api/v1/connect/auth/confirm-signup \
      -H "Content-Type: application/json" \
      -d '{
        "token":    "YOUR_TOKEN_FROM_EMAIL",
        "username": "you@example.com",
        "password": "YourPassword123!"
      }'

    回應:{"access_token": "eyJ..."}。帳號已啟用。

完成。前往 快速開始,將 PERXONA_CONNECT_EMAILPERXONA_CONNECT_PASSWORD 填入 .env——範例伺服器會自動處理後續登入。

API 認証情報を取得

Connect Kit サンプルを実行する前に、Perxona アカウントが必要です。登録は完全セルフサービス——承認や招待コードは不要です。以下の 3 ステップで約 2 分で完了します。

🔑
一回限りの設定です。 メールアドレスとパスワードが揃ったら、 クイックスタート へ進んでください——Express サンプルがその後のログインをすべて自動で処理します。
  1. サインアップトークンをリクエスト

    メールアドレスをサインアップエンドポイントに送信します。サーバーは 201(本文なし)を返し、受信トレイに プレーンテキストのトークンを送信します。

    curl -X POST https://console.perxona.ai/asia/api/v1/connect/auth/signup \
      -H "Content-Type: application/json" \
      -d '{"email": "you@example.com"}'
  2. メールを確認してトークンをコピー

    Perxona からのメールを開いてください。クリック可能なリンクでは なく、短いトークン文字列が記載されています。 次のステップで使用するのでコピーしてください。

    Perxona 認証メール。プレーンテキストのトークンが表示されている
  3. サインアップを完了してパスワードを設定

    トークン、メールアドレス(username として使用)、 設定するパスワードを送信します。成功すると access_token が返されアカウントが有効になります。

    curl -X POST https://console.perxona.ai/asia/api/v1/connect/auth/confirm-signup \
      -H "Content-Type: application/json" \
      -d '{
        "token":    "YOUR_TOKEN_FROM_EMAIL",
        "username": "you@example.com",
        "password": "YourPassword123!"
      }'

    レスポンス:{"access_token": "eyJ..."}。アカウントが有効になりました。

完了です。クイックスタートへ進み、 PERXONA_CONNECT_EMAILPERXONA_CONNECT_PASSWORD.env に入力してください——サンプルサーバーがその後のログインを自動で処理します。

How It Works

Architecture

Both demos share the same three-layer foundation. <sv-presenter> is the innermost component — the CDN Web Component that handles all speech, motion, and lip-sync directly via the Connect API. The demos wrap it with different application layers depending on the use case.

Basic Demo

A single-page avatar presenter. The app provides catalog UI and a text input, then initializes <sv-presenter> with a Connect token — all rendering, synthesis, and playback happen inside the component.

┌─ Browser ─────────────────────────────────────────────────────┐
│  ┌─ demos/basic/app.js ──────────────────────────────────┐    │
│  │  Catalog pickers · Launch button · Text / audio input │    │
│  │                                                       │    │
│  │  ┌─ <sv-presenter>  (Web Component, CDN) ──────────┐  │    │
│  │  │  Audio synthesis  ·  Motion playback            │  │    │
│  │  │  Lip-sync rendering  ·  Token auto-refresh      │  │    │
│  │  └─────────────────────────────────────────────────┘  │    │
│  └───────────────────────────────────────────────────────┘    │
└───────────────────────────────────────────────────────────────┘
       │  /api/*  (proxy)                   │  direct (bearer token)
       ▼                                    ▼
┌─ server.mjs ────────────┐     ┌─ Connect API ─────────────┐
│  /api/config            │     │  /assets  (catalog)       │
│  /api/connect-token     │────►│  /presentation            │
│  /api/avatars           │     │  /voice-tokens/tts        │
│  /api/scenes            │     └───────────────────────────┘
│  /api/voices            │
│  /api/chat  (opt-in)    │
└─────────────────────────┘
 Browser (app.js)        server.mjs                      Connect API
       │                      │                               │
  1.   ├─ GET /api/config ───►│                               │
       │◄─ presenterUrl ──────┤                               │
  2.   ├─ load <script> from presenterUrl (CDN)               │
       │                      │                               │
  3.   ├─ GET /api/avatars ──►│                               │
       ├─ GET /api/scenes ───►│                               │
       ├─ GET /api/voices ───►│                               │
       │◄─ catalog items ─────┤                               │
  4.   ├─ GET /api/connect-token ────────────────────────────►│
       │◄─ connect_token ─────────────────────────────────────┤
  5.   ├─ presenter.initialize(token, { avatarId, ... }) ────►│
       │◄─ PRESENTER_STATUS: Ready ───────────────────────────┤
  6.   ├─ presenter.present("Hello!") ───────────────────────►│
       │◄─ avatar speaks ─────────────────────────────────────┤

Chatbot Demo

Adds a full chatbot layer on top of Basic. A Chatbot Manager handles bot CRUD, knowledge files, and function tools. The Chat Panel drives multi-turn conversations — each AI reply is piped straight into <sv-presenter> for live speech.

┌─ Browser ───────────────────────────────────────────────────────┐
│  ┌─ demos/chatbot/app.js ───────────────────────────────────┐   │
│  │  ┌─ Chatbot Manager ────┐  ┌─ Avatar Stage ─────────┐    │   │
│  │  │  Bot picker (CRUD)   │  │  ┌─ <sv-presenter> ─┐  │    │   │
│  │  │  Knowledge upload    │  │  │  (CDN Component) │  │    │   │
│  │  │  Function tools      │  │  │  initialize()    │  │    │   │
│  │  └──────────────────────┘  │  │  present(reply)  │  │    │   │
│  │                            │  └──────────────────┘  │    │   │
│  │  ┌─ Chat Panel ─────────┐  └────────────────────────┘    │   │
│  │  │  Multi-turn history  │                                │   │
│  │  │  User → AI reply     │                                │   │
│  │  └──────────────────────┘                                │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
       │  /api/*  (proxy)                   │  direct (bearer token)
       ▼                                    ▼
┌─ server.mjs ───────────────────┐  ┌─ Connect API ──────────────┐
│  /api/chatbots  (CRUD)         │  │  /chatbots                 │
│  /api/chatbots/:id/chat        │─►│  /chatbots/:id/chat        │
│  /api/chatbots/:id/knowledge   │  │  /assets · /presentation   │
│  /api/connect-token            │  └────────────────────────────┘
└────────────────────────────────┘
 Browser (app.js)        server.mjs        Connect API
       │                      │                 │
  1-4. ├─ [config → catalog → connect-token → presenter.initialize()]
       │                      │                 │
  5.   ├─ POST /api/chatbots ──────────────────►│ create bot
       │◄─ { id, name, status } ────────────────┤
  6.   ├─ POST /api/chatbots/:id/knowledge ────►│ upload file
       │◄─ { knowledge: { status } } ───────────┤
  7.   ├─ POST /api/chatbots/:id/chat ─────────►│
       │  { messages: [{ role, parts }] }       │ AI response
       │◄─ { reply_text } ──────────────────────┤
  8.   ├─ presenter.present(reply_text) ───────►│
       │◄─ avatar speaks ───────────────────────┤

Auth Model

⚠️
Demo auth only. Every browser visitor shares one upstream Connect identity (the .env service account). Fine for demos and hackathons — not a production multi-tenant design.
  1. The server reads PERXONA_CONNECT_EMAIL / PERXONA_CONNECT_PASSWORD from .env.
  2. On the first request to a protected route, the server logs in and caches the bearer token in memory.
  3. The browser calls GET /api/connect-token — the server validates and returns the cached token.
  4. The browser passes the token into presenter.initialize(connectToken, { avatarId, sceneId, voiceId }).
  5. From that point, <sv-presenter> talks to the Connect API directly — speech and motion are handled by the component, not the server.
  6. If the cached token expires (401/403 from upstream), the server re-logs in and retries once — transparent to the browser.

運作原理

架構

兩個 Demo 共用相同的三層基礎。 <sv-presenter> 是最內層的核心元件——一個 CDN Web Component,直接透過 Connect API 處理語音、動作與口型同步。Demo 以不同的應用層包裝它。

Basic Demo

單頁式虛擬人 presenter。應用程式提供 catalog UI 與文字輸入框,然後以 Connect token 初始化 <sv-presenter>——所有渲染、合成與播放都在元件內部完成。

┌─ Browser ─────────────────────────────────────────────────────┐
│  ┌─ demos/basic/app.js ──────────────────────────────────┐    │
│  │  Catalog pickers · Launch button · Text / audio input │    │
│  │                                                       │    │
│  │  ┌─ <sv-presenter>  (Web Component, CDN) ──────────┐  │    │
│  │  │  Audio synthesis  ·  Motion playback            │  │    │
│  │  │  Lip-sync rendering  ·  Token auto-refresh      │  │    │
│  │  └─────────────────────────────────────────────────┘  │    │
│  └───────────────────────────────────────────────────────┘    │
└───────────────────────────────────────────────────────────────┘
       │  /api/*  (proxy)                   │  direct (bearer token)
       ▼                                    ▼
┌─ server.mjs ────────────┐     ┌─ Connect API ─────────────┐
│  /api/config            │     │  /assets  (catalog)       │
│  /api/connect-token     │────►│  /presentation            │
│  /api/avatars           │     │  /voice-tokens/tts        │
│  /api/scenes            │     └───────────────────────────┘
│  /api/voices            │
│  /api/chat  (opt-in)    │
└─────────────────────────┘
 Browser (app.js)        server.mjs                      Connect API
       │                      │                               │
  1.   ├─ GET /api/config ───►│                               │
       │◄─ presenterUrl ──────┤                               │
  2.   ├─ load <script> from presenterUrl (CDN)               │
       │                      │                               │
  3.   ├─ GET /api/avatars ──►│                               │
       ├─ GET /api/scenes ───►│                               │
       ├─ GET /api/voices ───►│                               │
       │◄─ catalog items ─────┤                               │
  4.   ├─ GET /api/connect-token ────────────────────────────►│
       │◄─ connect_token ─────────────────────────────────────┤
  5.   ├─ presenter.initialize(token, { avatarId, ... }) ────►│
       │◄─ PRESENTER_STATUS: Ready ───────────────────────────┤
  6.   ├─ presenter.present("Hello!") ───────────────────────►│
       │◄─ avatar speaks ─────────────────────────────────────┤

Chatbot Demo

在 Basic 之上新增完整的 chatbot 層。Chatbot Manager 處理 bot CRUD、knowledge file 與 function tools。Chat Panel 驅動多輪對話——每個 AI 回覆直接串接至 <sv-presenter> 即時發話。

┌─ Browser ───────────────────────────────────────────────────────┐
│  ┌─ demos/chatbot/app.js ───────────────────────────────────┐   │
│  │  ┌─ Chatbot Manager ────┐  ┌─ Avatar Stage ─────────┐    │   │
│  │  │  Bot picker (CRUD)   │  │  ┌─ <sv-presenter> ─┐  │    │   │
│  │  │  Knowledge upload    │  │  │  (CDN Component) │  │    │   │
│  │  │  Function tools      │  │  │  initialize()    │  │    │   │
│  │  └──────────────────────┘  │  │  present(reply)  │  │    │   │
│  │                            │  └──────────────────┘  │    │   │
│  │  ┌─ Chat Panel ─────────┐  └────────────────────────┘    │   │
│  │  │  Multi-turn history  │                                │   │
│  │  │  User → AI reply     │                                │   │
│  │  └──────────────────────┘                                │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
       │  /api/*  (proxy)                   │  direct (bearer token)
       ▼                                    ▼
┌─ server.mjs ───────────────────┐  ┌─ Connect API ──────────────┐
│  /api/chatbots  (CRUD)         │  │  /chatbots                 │
│  /api/chatbots/:id/chat        │─►│  /chatbots/:id/chat        │
│  /api/chatbots/:id/knowledge   │  │  /assets · /presentation   │
│  /api/connect-token            │  └────────────────────────────┘
└────────────────────────────────┘
 Browser (app.js)        server.mjs        Connect API
       │                      │                 │
  1-4. ├─ [config → catalog → connect-token → presenter.initialize()]
       │                      │                 │
  5.   ├─ POST /api/chatbots ──────────────────►│ create bot
       │◄─ { id, name, status } ────────────────┤
  6.   ├─ POST /api/chatbots/:id/knowledge ────►│ upload file
       │◄─ { knowledge: { status } } ───────────┤
  7.   ├─ POST /api/chatbots/:id/chat ─────────►│
       │  { messages: [{ role, parts }] }       │ AI response
       │◄─ { reply_text } ──────────────────────┤
  8.   ├─ presenter.present(reply_text) ───────►│
       │◄─ avatar speaks ───────────────────────┤

驗證模型

⚠️
僅適用於 Demo 的驗證。每個瀏覽器訪客共用同一個 Connect 身份(.env 的服務帳號)。適合 Demo 和黑客松——不適合生產環境的多租戶設計。
  1. 伺服器從 .env 讀取 PERXONA_CONNECT_EMAIL / PERXONA_CONNECT_PASSWORD
  2. 在第一次請求受保護路由時,伺服器登入並將 Bearer Token 快取在記憶體中。
  3. 瀏覽器呼叫 GET /api/connect-token——伺服器驗證並回傳快取的 token。
  4. 瀏覽器將 token 傳入 presenter.initialize(connectToken, { avatarId, sceneId, voiceId })
  5. 從此時起,<sv-presenter> 直接與 Connect API 通訊——語音和動作由元件處理,而非伺服器。
  6. 若快取的 token 過期(來自上游的 401/403),伺服器會重新登入並重試一次——對瀏覽器透明。

仕組み

アーキテクチャ

両方のデモは同じ 3 層構成を共有しています。 <sv-presenter> は最内層のコアコンポーネント —— Connect API を通じて音声・モーション・リップシンクを直接処理する CDN Web コンポーネントです。デモは用途に応じて異なるアプリケーション層でラップします。

Basic Demo

単一ページのアバター Presenter。アプリはカタログ UI とテキスト入力を提供し、Connect トークンで <sv-presenter> を初期化します——レンダリング・合成・再生はすべてコンポーネント内で行われます。

┌─ Browser ─────────────────────────────────────────────────────┐
│  ┌─ demos/basic/app.js ──────────────────────────────────┐    │
│  │  Catalog pickers · Launch button · Text / audio input │    │
│  │                                                       │    │
│  │  ┌─ <sv-presenter>  (Web Component, CDN) ──────────┐  │    │
│  │  │  Audio synthesis  ·  Motion playback            │  │    │
│  │  │  Lip-sync rendering  ·  Token auto-refresh      │  │    │
│  │  └─────────────────────────────────────────────────┘  │    │
│  └───────────────────────────────────────────────────────┘    │
└───────────────────────────────────────────────────────────────┘
       │  /api/*  (proxy)                   │  direct (bearer token)
       ▼                                    ▼
┌─ server.mjs ────────────┐     ┌─ Connect API ─────────────┐
│  /api/config            │     │  /assets  (catalog)       │
│  /api/connect-token     │────►│  /presentation            │
│  /api/avatars           │     │  /voice-tokens/tts        │
│  /api/scenes            │     └───────────────────────────┘
│  /api/voices            │
│  /api/chat  (opt-in)    │
└─────────────────────────┘
 Browser (app.js)        server.mjs                      Connect API
       │                      │                               │
  1.   ├─ GET /api/config ───►│                               │
       │◄─ presenterUrl ──────┤                               │
  2.   ├─ load <script> from presenterUrl (CDN)               │
       │                      │                               │
  3.   ├─ GET /api/avatars ──►│                               │
       ├─ GET /api/scenes ───►│                               │
       ├─ GET /api/voices ───►│                               │
       │◄─ catalog items ─────┤                               │
  4.   ├─ GET /api/connect-token ────────────────────────────►│
       │◄─ connect_token ─────────────────────────────────────┤
  5.   ├─ presenter.initialize(token, { avatarId, ... }) ────►│
       │◄─ PRESENTER_STATUS: Ready ───────────────────────────┤
  6.   ├─ presenter.present("Hello!") ───────────────────────►│
       │◄─ avatar speaks ─────────────────────────────────────┤

Chatbot Demo

Basic の上に完全なチャットボット層を追加します。Chatbot Manager がボットの CRUD・ナレッジファイル・ファンクションツールを処理します。Chat Panel がマルチターン会話を駆動し、各 AI の返答は直接 <sv-presenter> に渡されてライブで発話されます。

┌─ Browser ───────────────────────────────────────────────────────┐
│  ┌─ demos/chatbot/app.js ───────────────────────────────────┐   │
│  │  ┌─ Chatbot Manager ────┐  ┌─ Avatar Stage ─────────┐    │   │
│  │  │  Bot picker (CRUD)   │  │  ┌─ <sv-presenter> ─┐  │    │   │
│  │  │  Knowledge upload    │  │  │  (CDN Component) │  │    │   │
│  │  │  Function tools      │  │  │  initialize()    │  │    │   │
│  │  └──────────────────────┘  │  │  present(reply)  │  │    │   │
│  │                            │  └──────────────────┘  │    │   │
│  │  ┌─ Chat Panel ─────────┐  └────────────────────────┘    │   │
│  │  │  Multi-turn history  │                                │   │
│  │  │  User → AI reply     │                                │   │
│  │  └──────────────────────┘                                │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
       │  /api/*  (proxy)                   │  direct (bearer token)
       ▼                                    ▼
┌─ server.mjs ───────────────────┐  ┌─ Connect API ──────────────┐
│  /api/chatbots  (CRUD)         │  │  /chatbots                 │
│  /api/chatbots/:id/chat        │─►│  /chatbots/:id/chat        │
│  /api/chatbots/:id/knowledge   │  │  /assets · /presentation   │
│  /api/connect-token            │  └────────────────────────────┘
└────────────────────────────────┘
 Browser (app.js)        server.mjs        Connect API
       │                      │                 │
  1-4. ├─ [config → catalog → connect-token → presenter.initialize()]
       │                      │                 │
  5.   ├─ POST /api/chatbots ──────────────────►│ create bot
       │◄─ { id, name, status } ────────────────┤
  6.   ├─ POST /api/chatbots/:id/knowledge ────►│ upload file
       │◄─ { knowledge: { status } } ───────────┤
  7.   ├─ POST /api/chatbots/:id/chat ─────────►│
       │  { messages: [{ role, parts }] }       │ AI response
       │◄─ { reply_text } ──────────────────────┤
  8.   ├─ presenter.present(reply_text) ───────►│
       │◄─ avatar speaks ───────────────────────┤

認証モデル

⚠️
デモ専用の認証です。すべてのブラウザ訪問者が 1 つの Connect ID(.env のサービスアカウント)を共有します。デモやハッカソンには適していますが、本番のマルチテナント設計には不向きです。
  1. サーバーが .env から PERXONA_CONNECT_EMAIL / PERXONA_CONNECT_PASSWORD を読み込みます。
  2. 保護されたルートへの最初のリクエスト時、サーバーはログインしてメモリに Bearer トークンをキャッシュします。
  3. ブラウザが GET /api/connect-token を呼び出し、サーバーはキャッシュしたトークンを検証して返します。
  4. ブラウザがトークンを presenter.initialize(connectToken, { avatarId, sceneId, voiceId })に渡します。
  5. その後、<sv-presenter> は Connect API と直接通信します——音声とモーションはコンポーネントが処理し、サーバーは関与しません。
  6. キャッシュしたトークンが期限切れ(上流から 401/403)の場合、サーバーは再ログインして 1 回リトライします——ブラウザには透過的です。

Configuration

All configuration lives in .env. Copy .env.example.env and fill in your values. Never commit .env — it is in .gitignore.

設定

所有設定透過 .env 進行。將 .env.example 複製為 .env 並填入你的值。絕對不要提交 .env——它已在 .gitignore 中。

設定

すべての設定は .env で行います。.env.example.env にコピーして値を入力してください。.env は絶対にコミットしないでください——.gitignore に含まれています。

Variable Required必填必須 Default預設值デフォルト Description說明説明
PERXONA_API_BASE_URL Region-specific Connect API base URL. Ask your Perxona contact. 區域專屬的 Connect API 基底 URL。向 Perxona 聯絡人取得。 地域別の Connect API ベース URL。Perxona 担当者に確認してください。
PERXONA_CONNECT_EMAIL Service account email. The server signs in with this. 服務帳號 Email。伺服器以此登入。 サービスアカウントのメールアドレス。サーバーがこれでログインします。
PERXONA_CONNECT_PASSWORD Service account password. 服務帳號密碼。 サービスアカウントのパスワード。
PORT 8083 Port the server listens on. 伺服器監聽的連接埠。 サーバーがリッスンするポート。
PRESENTER_URL cdn.perxona.ai/…/presenter.js Presenter engine CDN URL. Override only if your Perxona contact provides a specific URL. Presenter 引擎 CDN URL。僅在 Perxona 聯絡人提供特定 URL 時覆蓋。 Presenter エンジンの CDN URL。Perxona 担当者から特定の URL が提供された場合のみ上書きしてください。
LLM_API_KEY Set to enable the chat panel. Any OpenAI-compatible key works, including local Ollama via LLM_BASE_URL. 設定以啟用聊天面板。支援任何 OpenAI 相容金鑰,包括透過 LLM_BASE_URL 的本地 Ollama。 チャットパネルを有効にするために設定します。LLM_BASE_URL 経由のローカル Ollama を含む OpenAI 互換のキーが使えます。
LLM_BASE_URL https://api.openai.com/v1 LLM endpoint URL (override for Ollama or other providers). LLM 端點 URL(Ollama 或其他供應商時覆蓋)。 LLM エンドポイント URL(Ollama 等に上書き)。
LLM_MODEL gpt-4o-mini LLM model name passed to the chat endpoint. 傳遞給聊天端點的 LLM 模型名稱。 チャットエンドポイントに渡す LLM モデル名。

Quick Start

The sample app is a single Node/Express server that serves two runnable browser demos, both built on the same <sv-presenter> integration: Presenter — the Basic demo: browse the avatar catalog, launch the presenter, and drive speech (with optional LLM chat); and Chatbot — full chatbot CRUD, a persistent multi-turn conversation, and knowledge files plus function tools. Run the server once, then open either demo. The steps below get you from clone to a talking avatar.

Get from clone to a talking avatar in 5–15 minutes. You need Node >=22 and Perxona service account credentials.
  1. Clone the sample

    git clone https://github.com/XRSPACE-Inc/perxona-connect-kit.git
    cd perxona-connect-kit
  2. Create your local config

    cp .env.example .env

    Open .env and fill in the three required values:

    PERXONA_API_BASE_URL=https://console.perxona.ai/asia
    PERXONA_CONNECT_EMAIL=your@email.com
    PERXONA_CONNECT_PASSWORD=your-password
  3. Install dependencies

    npm install

    Requires Node >=22. If your Node is too old, npm install refuses with a clear upgrade message.

  4. Start the server

    npm run dev    # with live reload (node --watch)
    # or
    npm start      # without watch

    The terminal prints the local URL, e.g. http://localhost:8083.

  5. Launch the avatar

    Open the URL in your browser. The landing page offers two demos — Basic and Chatbot — each highlighting a different set of product capabilities. Open either demo, pick an Avatar, Scene, and Voice, then click Launch. The avatar appears and speaks.

快速開始

範例應用是一個單一的 Node/Express 伺服器,提供兩個可執行的 browser demo,都建立在相同的 <sv-presenter> 整合之上: Presenter——Basic demo:瀏覽 avatar catalog、啟動 presenter 並驅動語音(可選搭配 LLM chat);以及 Chatbot——完整的 chatbot CRUD、持久多輪對話,以及 knowledge file 與 function tools。伺服器只需啟動一次,即可開啟任一 demo。以下步驟帶你從 clone 到說話的虛擬人。

從 clone 到說話的虛擬人只需 5–15 分鐘。需要 Node >=22 與 Perxona 服務帳號憑證。
  1. Clone 範例

    git clone https://github.com/XRSPACE-Inc/perxona-connect-kit.git
    cd perxona-connect-kit
  2. 建立本機設定檔

    cp .env.example .env

    開啟 .env 並填入三個必填值:

    PERXONA_API_BASE_URL=https://console.perxona.ai/asia
    PERXONA_CONNECT_EMAIL=your@email.com
    PERXONA_CONNECT_PASSWORD=your-password
  3. 安裝依賴套件

    npm install

    需要 Node >=22。若版本過舊,npm install 會顯示明確的升級訊息並拒絕執行。

  4. 啟動伺服器

    npm run dev    # 啟動並監聽檔案變更
    # 或
    npm start      # 不監聽變更

    終端機會印出本機 URL,例如 http://localhost:8083

  5. 啟動虛擬人

    在瀏覽器開啟該 URL。首頁提供兩個範例—— BasicChatbot——分別展示不同的產品功能與整合能力。進入任一範例,選擇 AvatarSceneVoice,點擊 Launch,虛擬人將出現並開始說話。

クイックスタート

サンプルアプリは 1 つの Node/Express サーバーで、同じ <sv-presenter> 統合の上に構築された 2 つの実行可能なブラウザデモを提供します: Presenter——Basic デモ:avatar カタログを閲覧し、presenter を起動して発話を駆動(任意で LLM チャット);および Chatbot——チャットボットの完全な CRUD、永続的なマルチターン会話、ナレッジファイルと function tools。サーバーを一度起動すれば、どちらのデモも開けます。以下の手順で、クローンからしゃべるアバターまで進めます。

クローンからしゃべるアバターまで 5〜15 分Node >=22 と Perxona サービスアカウントの認証情報が必要です。
  1. サンプルをクローン

    git clone https://github.com/XRSPACE-Inc/perxona-connect-kit.git
    cd perxona-connect-kit
  2. ローカル設定ファイルを作成

    cp .env.example .env

    .env を開いて 3 つの必須値を入力してください:

    PERXONA_API_BASE_URL=https://console.perxona.ai/asia
    PERXONA_CONNECT_EMAIL=your@email.com
    PERXONA_CONNECT_PASSWORD=your-password
  3. 依存関係をインストール

    npm install

    Node >=22 が必要です。古いバージョンの場合、npm install は明確なアップグレードメッセージとともに失敗します。

  4. サーバーを起動

    npm run dev    # ライブリロード (node --watch)
    # または
    npm start      # ウォッチなし

    ターミナルにローカル URL(例:http://localhost:8083)が表示されます。

  5. アバターを起動

    ブラウザで URL を開いてください。ランディングページには BasicChatbot の 2 つのデモが表示されます——それぞれ異なる製品機能と統合能力を体験できます。どちらかのデモを開き、AvatarSceneVoice を選択して Launch をクリックしてください。アバターが表示されてしゃべります。

Presenter

The demos/basic/ demo is the essential <sv-presenter> integration every Connect app needs, in ~300 lines of vanilla JS. It teaches four things: catalog browsing (fetch avatars, scenes, and voices), presenter initialization (exchange server credentials for a Connect token and hand it to initialize()), driving speech (send text to present(), or supply your own audio via presentWithAudio()), and an optional LLM chat that pipes replies back through the presenter. Here is the page lifecycle:

  1. Page load: app.js calls GET /api/config, dynamically injects the presenter engine <script> from presenterUrl, then loads the catalog (/api/avatars, /api/scenes, /api/voices) to populate the dropdown selectors.
  2. Launch click: Calls presenter.resumeAudioPlayback() to unlock autoplay (must be in the click handler), fetches GET /api/connect-token, then calls presenter.initialize(connectToken, { avatarId, sceneId, voiceId }).
  3. Ready state: The presenter fires PRESENTER_STATUS with detail = "Ready" — the UI reveals the performance controls.
  4. Playback: Preset buttons and the free-text box call presenter.present(text). The Stop button calls presenter.interruptPresentation().
  5. Chat (optional): If LLM_API_KEY is set, the chat panel appears. User messages go to POST /api/chat, and the LLM response is spoken via presenter.present().

Presenter

demos/basic/ demo 是每個 Connect 應用都需要的核心 <sv-presenter> 整合,以約 300 行的原生 JS 呈現。它示範四件事:catalog 瀏覽(取得 avatar、scene 與 voice)、presenter 初始化(以伺服器憑證換取 Connect token 並傳給 initialize())、驅動語音(將文字傳給 present(),或透過 presentWithAudio() 提供自己的音訊),以及可選的 LLM chat,將回覆回傳給 presenter 發話。以下是頁面生命週期:

  1. 頁面載入:app.js 呼叫 GET /api/config,從 presenterUrl 動態注入 presenter 引擎 <script>,然後載入 catalog(/api/avatars/api/scenes/api/voices)以填充下拉選單。
  2. Launch 點擊:呼叫 presenter.resumeAudioPlayback() 解鎖自動播放(必須在點擊處理器中),取得 GET /api/connect-token,然後呼叫 presenter.initialize(connectToken, { avatarId, sceneId, voiceId })
  3. 就緒狀態:presenter 觸發 PRESENTER_STATUSdetail = "Ready"——UI 顯示演出控制項。
  4. 播放:預設按鈕和自由文字輸入框呼叫 presenter.present(text)。停止按鈕呼叫 presenter.interruptPresentation()
  5. 聊天(可選):若設定了 LLM_API_KEY,聊天面板出現。使用者訊息傳送至 POST /api/chat,LLM 回應透過 presenter.present() 發話。

Presenter

demos/basic/ デモは、すべての Connect アプリに必要な基本的な <sv-presenter> 統合を、約 300 行のバニラ JS で示します。次の 4 つを学べます:カタログの閲覧(avatar・scene・voice の取得)、presenter の初期化(サーバー資格情報を Connect トークンと交換し initialize() に渡す)、発話の駆動(テキストを present() に送るか、 presentWithAudio() で独自の音声を提供)、そして任意の LLM チャット(応答を presenter に戻して発話)。ページのライフサイクルは以下の通りです:

  1. ページ読み込み:app.jsGET /api/config を呼び出し、presenterUrl から presenter エンジンの <script> を動的に注入し、カタログ(/api/avatars/api/scenes/api/voices)を読み込んでドロップダウンを設定します。
  2. Launch クリック:presenter.resumeAudioPlayback() を呼び出して自動再生をアンロック(クリックハンドラー内で必須)、GET /api/connect-token を取得し、presenter.initialize(connectToken, { avatarId, sceneId, voiceId }) を呼び出します。
  3. 準備完了状態:presenter が detail = "Ready"PRESENTER_STATUS を発行——UI がパフォーマンスコントロールを表示します。
  4. 再生:プリセットボタンとフリーテキスト入力が presenter.present(text) を呼び出します。停止ボタンが presenter.interruptPresentation() を呼び出します。
  5. チャット(オプション):LLM_API_KEY が設定されている場合、チャットパネルが表示されます。ユーザーのメッセージは POST /api/chat に送信され、LLM の応答が presenter.present() で発話されます。

Chatbot

The demos/chatbot/ demo integrates the Perxona Connect Chatbot API with the same <sv-presenter> stage. On top of the Presenter demo it adds full chatbot CRUD, a persistent multi-turn conversation, and knowledge files plus function tools. Every assistant reply is piped into presenter.present(), so the avatar speaks each response in real time. Messages use the Connect parts-based format ({ role, parts: [{ type: 'text', text }] }) and are sent as a 20-message sliding window to avoid upstream timeouts. Open http://localhost:8083/demos/chatbot/. Here is the lifecycle:

  1. Launch the presenter. Pick an Avatar, Scene, and Voice, then click Launch Presenter. The avatar loads in the right-hand stage — identical to the Basic demo.
  2. Create or select a chatbot. Click + New Chatbot, enter a name and optional system instructions, and click Save. The chatbot is created via POST /api/chatbots and immediately selected. To edit or delete an existing chatbot, pick it from the dropdown.
  3. Chat. Type a message and press Send. The avatar enters Thinking state while the LLM processes (POST /api/chatbots/:id/chat). The reply appears in the chat log and is spoken aloud via presenter.present(reply_text). If the presenter is not yet launched, chat still works as text-only.
  4. Optional — Knowledge file & function tools. Upload a .txt, .pdf, .doc, .docx, or .csv file in the chatbot editor to ground the chatbot in your own content. Add a tools array when creating or updating a chatbot to let it call external HTTP APIs during a conversation.

Chatbot

demos/chatbot/ demo 將 Perxona Connect Chatbot API 整合到相同的 <sv-presenter> 舞台上。在 Presenter demo 的基礎上,它新增了完整的 chatbot CRUD、持久的多輪對話,以及 knowledge filefunction tools。每個助手回覆都會傳入 presenter.present(),讓 avatar 即時發話。訊息使用 Connect 的 parts 格式({ role, parts: [{ type: 'text', text }] }),並以 20 則訊息的滑動視窗送出以避免上游逾時。開啟 http://localhost:8083/demos/chatbot/。生命週期如下:

  1. 啟動 presenter。選擇 Avatar、Scene 和 Voice,點擊 Launch Presenter。Avatar 載入右側舞台——與 Basic Demo 完全相同。
  2. 建立或選取 chatbot。點擊 + New Chatbot,輸入名稱和可選的系統指令,點擊 Save。Chatbot 透過 POST /api/chatbots 建立並立即選取。若要編輯或刪除現有 chatbot,從下拉選單中選取。
  3. 聊天。輸入訊息並按送出。Avatar 進入 Thinking 狀態,等待 LLM 處理(POST /api/chatbots/:id/chat)。回覆顯示在聊天記錄中,並透過 presenter.present(reply_text) 大聲發話。若 presenter 尚未啟動,聊天仍以純文字模式運作。
  4. 可選——Knowledge file 與 function tools。在 chatbot 編輯器中上傳 .txt.pdf.doc.docx.csv 檔案,讓 chatbot 根據自有內容回答。建立或更新 chatbot 時傳入 tools 陣列,讓 chatbot 在對話中呼叫外部 HTTP API。

Chatbot

demos/chatbot/ デモは、Perxona Connect Chatbot API を同じ <sv-presenter> ステージと統合します。Presenter デモの上に、チャットボットの完全な CRUD、永続的なマルチターン会話、そして ナレッジファイルfunction toolsを追加します。すべてのアシスタント応答は presenter.present() に渡され、アバターが各応答をリアルタイムで発話します。メッセージは Connect の parts 形式({ role, parts: [{ type: 'text', text }] })を使用し、上流のタイムアウトを避けるために 20 件のスライディングウィンドウで送信されます。 http://localhost:8083/demos/chatbot/ を開いてください。ライフサイクルは以下の通りです:

  1. Presenter を起動。Avatar・Scene・Voice を選択して Launch Presenter をクリック。アバターが右側のステージに読み込まれます——Basic デモと同じ手順です。
  2. チャットボットを作成または選択。 + New Chatbot をクリックし、名前と任意のシステム指示を入力して Save をクリック。チャットボットが POST /api/chatbots で作成され、即座に選択されます。既存のチャットボットを編集・削除するにはドロップダウンから選択してください。
  3. チャット。メッセージを入力して送信。LLM が処理する間(POST /api/chatbots/:id/chat)アバターが Thinking 状態に入ります。返答がチャットログに表示され、presenter.present(reply_text) でアバターが音声で発話します。Presenter が未起動の場合はテキストのみで動作します。
  4. オプション——ナレッジファイルとファンクションツール。チャットボットエディターで .txt.pdf.doc.docx.csv ファイルをアップロードして、独自コンテンツをもとに回答させることができます。チャットボット作成・更新時に tools 配列を渡すと、会話中に外部 HTTP API を呼び出せます。

API Reference

The Express server exposes these routes. All /api/* endpoints return JSON. The server proxies catalog reads to the Connect API using its shared cached bearer token — there is no per-request browser auth.

API 參考

Express 伺服器公開以下路由。所有 /api/* 端點均回傳 JSON。伺服器使用其共享快取的 Bearer Token 將 catalog 讀取代理至 Connect API——不需要每個請求的瀏覽器驗證。

API リファレンス

Express サーバーは以下のルートを公開します。すべての /api/* エンドポイントは JSON を返します。サーバーは共有キャッシュの Bearer トークンを使って Connect API へカタログ読み取りをプロキシします——リクエストごとのブラウザ認証は不要です。

Direct Connect API 直接呼叫 Connect API Connect API を直接呼び出す

POST/api/v1/connect/presentation
Generate a one-shot presentation payload. Call the Connect API directly with a Connect Bearer token; this route is not proxied by the Express sample server. Required fields: avatar_id and message. Optional fields: voice_id, emotion, and intensity. 產生單次 presentation payload。請使用 Connect Bearer Token 直接呼叫 Connect API;Express 範例伺服器不會代理此路由。必填欄位: avatar_idmessage;選填欄位: voice_idemotionintensity ワンショットの presentation payload を生成します。Connect Bearer Token を使って Connect API を直接呼び出してください。このルートは Express サンプルサーバーではプロキシされません。必須フィールドは avatar_idmessage、任意フィールドは voice_idemotionintensity です。
{
  "avatar_id": "YOUR_AVATAR_ID",
  "voice_id": "YOUR_VOICE_ID",
  "message": "Welcome to our hackathon demo!",
  "emotion": "excitement",
  "intensity": "high"
}
emotion sets the message's emotional tone and intensity sets its strength. Together, they guide facial-expression selection for suggested motions and act as soft ranking signals for motion candidates. Both are optional; when both are omitted, no facial expression is attached. Supported emotion values: joy, excitement, admiration, caring, gratitude, sadness, disappointment, annoyance, embarrassment, curiosity, surprise, realization, and confusion. Supported intensity values: low, neutral, and high. emotion 指定訊息的情緒,intensity 指定情緒強度。兩者會引導建議動作的臉部表情選擇,並作為動作候選的軟性排序訊號。 兩者皆為選填;若兩者皆省略,則不會附加臉部表情。支援的 emotion 值為:joyexcitementadmirationcaringgratitudesadnessdisappointmentannoyanceembarrassmentcuriositysurpriserealizationconfusion;支援的 intensity 值為:lowneutralhigh emotion はメッセージの感情、intensity はその強さを指定します。両者は提案モーションの表情選択を導き、モーション候補のソフトなランキングシグナルとしても使われます。どちらも任意で、両方を省略すると表情は付与されません。対応する emotion の値は joyexcitementadmirationcaringgratitudesadnessdisappointmentannoyanceembarrassmentcuriositysurpriserealizationconfusion です。 intensity の値は lowneutralhigh です。

Health & Config 健康檢查與設定 ヘルスチェックと設定

GET/api/health
Liveness + upstream diagnostics. Always returns 200. Response: { status: "ok", upstream: "reachable" | "unreachable" }. Probes the upstream API on every call. 存活檢查與上游診斷。始終回傳 200。回應:{ status: "ok", upstream: "reachable" | "unreachable" }。每次呼叫都會探測上游 API。 稼働状況と上流診断。常に 200 を返します。レスポンス:{ status: "ok", upstream: "reachable" | "unreachable" }。毎回上流 API にプローブを実行します。
GET/api/config
Static per-process flags. Response: { mock: boolean, chat: boolean, presenterUrl: string }. No upstream probe — cheap to call. chat reflects presence of LLM_API_KEY only, never the key itself. 靜態的每個程序標誌。回應:{ mock: boolean, chat: boolean, presenterUrl: string }。不探測上游——可低成本呼叫。chat 僅反映 LLM_API_KEY 的存在,不包含金鑰本身。 プロセスごとの静的フラグ。レスポンス:{ mock: boolean, chat: boolean, presenterUrl: string }。上流探索なし——低コストで呼び出せます。chatLLM_API_KEY の存在のみ反映し、キー自体は返しません。

Connect Token

GET/api/connect-token
Mint / reuse the shared Connect bearer JWT. Response: { connect_token: string }. Pass this directly into presenter.initialize(connectToken, { avatarId, sceneId, voiceId }). Validates the cached token before returning; re-logs in on 401/403. Cache-Control: no-store. 鑄造/重用共享 Connect Bearer JWT。回應:{ connect_token: string }。直接傳入 presenter.initialize(connectToken, { avatarId, sceneId, voiceId })。回傳前驗證快取的 token;在 401/403 時重新登入。Cache-Control: no-store 共有 Connect Bearer JWT を発行/再利用します。レスポンス:{ connect_token: string }。これを直接 presenter.initialize(connectToken, { avatarId, sceneId, voiceId })に渡します。返す前にキャッシュしたトークンを検証し、401/403 で再ログインします。Cache-Control: no-store

Catalog 目錄 カタログ

GET/api/avatars
List avatars. Response: Page { items: [{ id, name, thumbnail_urls, … }] }. (id is normalized from the upstream avatar_id.) 列出 Avatar。回應:Page { items: [{ id, name, thumbnail_urls, … }] }。(id 從上游的 avatar_id 正規化。) アバター一覧。レスポンス:Page { items: [{ id, name, thumbnail_urls, … }] }。(id は上流の avatar_id から正規化されています。)
GET/api/avatars/:id
Avatar detail (raw, includes lod_urls, lipsync_configs, etc.). Avatar 詳細資訊(原始格式,含 lod_urlslipsync_configs 等)。 アバター詳細(生形式、lod_urlslipsync_configs など含む)。
GET/api/avatars/:id/motions
Motions for an avatar. Response: Page { items: […] }. Motions are a sub-resource of an avatar — there is no top-level motions collection. 某個 Avatar 的動作。回應:Page { items: […] }。動作是 Avatar 的子資源——沒有頂層的 motions 集合端點。 アバターのモーション。レスポンス:Page { items: […] }。モーションはアバターのサブリソースです——トップレベルのモーションコレクションエンドポイントはありません。
GET/api/scenes
List scenes. Response: Page { items: [{ id, name, … }] }. (id normalized from scene_id.) 列出場景。回應:Page { items: [{ id, name, … }] }。(idscene_id 正規化。) シーン一覧。レスポンス:Page { items: [{ id, name, … }] }。(idscene_id から正規化。)
GET/api/scenes/:id
Scene detail. 場景詳細資訊。 シーン詳細。
GET/api/voices
List voices. Response: Page { items: [{ id, name, … }] }. 列出聲音。回應:Page { items: [{ id, name, … }] } 音声一覧。レスポンス:Page { items: [{ id, name, … }] }

Chatbot Chatbot チャットボット

GET/api/chatbots
List chatbots. Response: Page { items: [{ id, name, status }] }. 列出所有 chatbot。回應:Page { items: [{ id, name, status }] } チャットボット一覧。レスポンス:Page { items: [{ id, name, status }] }
POST/api/chatbots
Create a chatbot. Body: { name: string (required), custom_instructions?: string, tools?: Array }. Response: ChatBotDetailResponse { id, name, status, custom_instructions, tools }. 建立 chatbot。請求主體:{ name: string(必填), custom_instructions?: string, tools?: Array }。 回應:ChatBotDetailResponse { id, name, status, custom_instructions, tools } チャットボットを作成します。ボディ:{ name: string(必須), custom_instructions?: string, tools?: Array }。 レスポンス:ChatBotDetailResponse { id, name, status, custom_instructions, tools }
GET/api/chatbots/:id
Chatbot detail. Response: ChatBotDetailResponse (includes id, name, custom_instructions, status, tools). Chatbot 詳細資訊。回應:ChatBotDetailResponse(含 idnamecustom_instructionsstatustools)。 チャットボット詳細。レスポンス:ChatBotDetailResponseidnamecustom_instructionsstatustools を含む)。
PATCH/api/chatbots/:id
Update a chatbot. Body: partial { name?, custom_instructions?, tools? }. Response: updated ChatBotDetailResponse. 更新 chatbot。請求主體:部分欄位 { name?, custom_instructions?, tools? }。 回應:更新後的 ChatBotDetailResponse チャットボットを更新します。ボディ:部分フィールド { name?, custom_instructions?, tools? }。 レスポンス:更新後の ChatBotDetailResponse
DELETE/api/chatbots/:id
Delete a chatbot. Returns 204 No Content. 刪除 chatbot。回傳 204 No Content チャットボットを削除します。204 No Content を返します。
POST/api/chatbots/:id/knowledge
Upload a knowledge file. Body: { filename: string, content_base64: string, mime_type?: string }. Accepted types: .txt, .pdf, .md, .csv (max ~7.5 MB). The server decodes the base64 payload and forwards it to the upstream API as multipart. 上傳 knowledge file。請求主體:{ filename: string, content_base64: string, mime_type?: string }。 接受格式:.txt.pdf.md.csv(最大約 7.5 MB)。 伺服器解碼 base64 後以 multipart 格式轉發至上游 API。 ナレッジファイルをアップロードします。ボディ:{ filename: string, content_base64: string, mime_type?: string }。 対応形式:.txt.pdf.md.csv(最大約 7.5 MB)。 サーバーが base64 をデコードして multipart で上流 API に転送します。
DELETE/api/chatbots/:id/knowledge
Remove the knowledge file from a chatbot. 移除 chatbot 的 knowledge file。 チャットボットのナレッジファイルを削除します。
POST/api/chatbots/:id/chat
Send a message to the chatbot. Body: { messages: Array } — Connect parts format: [{ role: "user", parts: [{ type: "text", text: "…" }] }]. Response: { id, status, reply_text }. Pass reply_text to presenter.present() to have the avatar speak it. 向 chatbot 傳送訊息。請求主體:{ messages: Array }——Connect parts 格式: [{ role: "user", parts: [{ type: "text", text: "…" }] }]。 回應:{ id, status, reply_text }。將 reply_text 傳入 presenter.present() 讓 avatar 發話。 チャットボットにメッセージを送信します。ボディ:{ messages: Array }——Connect parts 形式: [{ role: "user", parts: [{ type: "text", text: "…" }] }]。 レスポンス:{ id, status, reply_text }reply_textpresenter.present() に渡してアバターに発話させます。

Chat

POST/api/chat
Opt-in LLM chat. Request: { messages: Array } (OpenAI message format). Returns 501 until LLM_API_KEY is set. Returns 400 if messages is empty or absent. 可選的 LLM 聊天。請求:{ messages: Array }(OpenAI 訊息格式)。在設定 LLM_API_KEY 前回傳 501。若 messages 為空或缺失則回傳 400 オプションの LLM チャット。リクエスト:{ messages: Array }(OpenAI メッセージ形式)。LLM_API_KEY が設定されるまで 501 を返します。messages が空または欠如の場合は 400
📄
Full contract: The endpoints above are the Express demo's proxy API. For the exact field shapes and schemas of the direct Connect API, see the OpenAPI spec at samples/express/docs/openapi.yaml. For TypeScript presenter types, install @perxona/presenter-types@latest. 完整合約:上方列出的是 Express demo 的 proxy API。如需 direct Connect API 精確的欄位格式與 schema,請參考 OpenAPI spec:samples/express/docs/openapi.yaml。如需 TypeScript presenter 型別,請安裝 @perxona/presenter-types@latest 完全なコントラクト:上記は Express demo の プロキシ API です。direct Connect API の正確な フィールド形式とスキーマは、OpenAPI spec samples/express/docs/openapi.yaml を参照してください。 TypeScript の presenter 型は @perxona/presenter-types@latest をインストールしてください。

Presenter API

The <sv-presenter> Web Component is loaded from Perxona's CDN. Interact with it through its JavaScript API after it upgrades in the DOM.

Loading the Component

Fetch the CDN URL from GET /api/config → presenterUrl and inject it dynamically — no hardcoded URLs in your HTML:

Presenter API

<sv-presenter> Web Component 從 Perxona 的 CDN 載入。在 DOM 中升級後透過其 JavaScript API 進行互動。

載入元件

GET /api/config → presenterUrl 取得 CDN URL 並動態注入——HTML 中不要硬編碼 URL:

Presenter API

<sv-presenter> Web コンポーネントは Perxona の CDN から読み込まれます。DOM でアップグレードされた後、JavaScript API を通じて操作します。

コンポーネントの読み込み

GET /api/config → presenterUrl から CDN URL を取得して動的に注入します——HTML に URL をハードコードしないでください:

index.html
<!-- Declare the element; do NOT load the engine script here -->
<sv-presenter hidden></sv-presenter>
app.js
const config = await fetch('/api/config').then(r => r.json());

// Load the presenter engine from the server-resolved CDN URL
await new Promise((resolve, reject) => {
  const script = document.createElement('script');
  script.type = 'module';
  script.src = config.presenterUrl;
  script.onload = resolve;
  script.onerror = () => reject(new Error('Presenter engine failed to load'));
  document.head.append(script);
});

const presenter = document.querySelector('sv-presenter');

Full Initialization Flow

完整初始化流程

完全な初期化フロー

// 1. Must run inside a direct user gesture (e.g. button click) to unlock autoplay
await presenter.resumeAudioPlayback();

// 2. Fetch the Connect bearer token the server minted
const { connect_token } = await fetch('/api/connect-token').then(r => r.json());

// 3. Initialize — the presenter resolves target against the Connect API directly
await presenter.initialize(connect_token, {
  avatarId: '<id from GET /api/avatars>',
  sceneId:  '<id from GET /api/scenes>',
  voiceId:  '<id from GET /api/voices>', // optional
});

// 4. Listen for status changes
presenter.addEventListener('PRESENTER_STATUS', (e) => {
  // e.detail: 'Uninitialized' | 'Initializing' | 'Ready'
  console.log('Presenter status:', e.detail);
});

// 5. Make the avatar speak — present() never rejects; check result.success
const result = await presenter.present('Hello from Perxona!');
if (!result.success) console.warn(result.code, result.message);

// 6. Stop playback and clear the queue
presenter.interruptPresentation();

API Members

API 成員

API メンバー

Member Description說明説明
initialize(token, target) Boot the presenter. Resolves target (avatarId/sceneId/voiceId) against the Connect API and mints a speech token. Returns a Promise — awaiting it means the presenter is ready. 啟動 presenter。將 target(avatarId/sceneId/voiceId)解析至 Connect API 並鑄造語音 token。回傳 Promise——await 後表示 presenter 已就緒。 Presenter を起動します。target(avatarId/sceneId/voiceId)を Connect API に解決してスピーチトークンを発行します。Promise を返します——await 後に Presenter が準備完了となります。
resumeAudioPlayback() Unlock browser autoplay policy. Must be called from a direct user gesture. Returns a Promise. Call this before initialize() in your click handler. 解鎖瀏覽器自動播放限制。必須從直接的使用者手勢呼叫。回傳 Promise。在點擊處理器中於 initialize() 之前呼叫此函式。 ブラウザの自動再生ポリシーをアンロックします。直接のユーザージェスチャーから呼び出す必要があります。Promise を返します。クリックハンドラー内で initialize() の前に呼び出してください。
present(content) Synthesize content into speech and play it on the avatar. Returns PresentationResult { success: boolean, code: string, message?: string }. Never rejects — always check result.success. content 合成為語音並在 avatar 上播放。回傳 PresentationResult { success: boolean, code: string, message?: string }永不 reject——始終檢查 result.success content を音声に合成してアバターで再生します。PresentationResult { success: boolean, code: string, message?: string } を返します。reject しません——常に result.success を確認してください。
presentWithAudio(audio, content) Play caller-supplied audio on the avatar, bypassing Perxona TTS. Pass an ArrayBuffer from any TTS service or pre-recorded clip. The Motion Director still runs — gestures and expressions are driven by content. Returns PresentationResult. Never rejects. 直接在 Avatar 上播放自訂音訊,略過 Perxona TTS。傳入任何 TTS 服務或預錄音檔的 ArrayBuffer。Motion Director 仍根據 content 驅動肢體動作與表情。回傳 PresentationResult永不 reject。 Perxona TTS を使わず、独自音声をアバターで直接再生します。任意の TTS または録音済み音声の ArrayBuffer を渡してください。Motion Director は content に基づき動きと表情を自動生成します。PresentationResult を返します。reject しません。
interruptPresentation() Stop the current performance and clear the queue immediately. 立即停止當前演出並清空佇列。 現在のパフォーマンスを停止してキューを即座にクリアします。
event PRESENTER_STATUS Fired as state changes. e.detail: "Uninitialized""Initializing""Ready". 狀態改變時觸發。e.detail"Uninitialized""Initializing""Ready" 状態変化時に発行されます。e.detail"Uninitialized""Initializing""Ready"
event CONNECT_TOKEN_EXPIRED Fired when the Connect API rejects the presenter's token. Handle by fetching a fresh token and calling presenter.refreshConnectToken(newToken). (Not wired in this sample — see Known Limitations.) 當 Connect API 拒絕 presenter 的 token 時觸發。處理方式:取得新 token 並呼叫 presenter.refreshConnectToken(newToken)(此範例未連接——見已知限制。) Presenter のトークンを Connect API が拒否した時に発行されます。新しいトークンを取得して presenter.refreshConnectToken(newToken) を呼び出して対応します。(このサンプルでは未接続——既知の制限を参照。)

Motion Browser

Motion Browser is a standalone developer tool that lets you explore Perxona's full motion catalog, preview every animation live on a 3D avatar, and compose scripts that mix free speech text with motion cues — all in one browser-based UI.

The core idea: the <sv-presenter> Web Component understands inline motion tags. Drop a [MOTION id:1] chip anywhere in your script, and the avatar performs that animation at exactly that point in the speech.

// The avatar says "I love", performs the wave motion, then finishes the line
await presenter.present("I love [MOTION wave:1] my avatar.");
💡
Motion Browser is the fastest way to discover which motions exist and copy their IDs into your own scripts — open it alongside your editor and use it as a live motion reference.

Demo

Features

  • Avatar Preview — Full-screen 3D rendering; switch characters instantly from the top selector.
  • Motion Library — Browse, search, and filter every available motion. Click any card to preview it live on the avatar.
  • Script Composer — Rich-text editor where you mix free speech text with motion chips. Press Play and the avatar speaks and performs motions in sequence.
  • Scene & Voice switching — Bottom control bar lets you swap scene and voice style without reloading.

Getting Started

cd tools/motion-browser
cp .env.example .env   # production values are pre-filled; no edits needed
pnpm install
pnpm dev

Open the URL printed by pnpm dev, sign in with your Perxona account, and pick an avatar. The presenter auto-initializes and the motion library loads automatically.

Composing a Script with Motion Tags

  1. Write your speech text

    Type the words you want the avatar to say in the Script Composer.

  2. Insert a motion chip

    Find the motion in the Motion Library panel. Place your cursor at the desired point in the text, then click + to insert it as a chip.

  3. Press Play

    The avatar speaks the full script and performs each motion at its marked position. The chip serializes to [MOTION <id>:1] and is passed directly to presenter.present().

Motion Browser

Motion Browser 是一個獨立的開發者工具,讓你瀏覽 Perxona 完整的動作目錄、在 3D Avatar 上即時預覽每個動畫,並撰寫混合說話文字與動作指令的腳本——全在瀏覽器中完成。

核心概念<sv-presenter> Web Component 支援行內動作標籤。在腳本文字中任意插入 [MOTION id:1],Avatar 就會在說話的對應時間點執行該動作。

// Avatar 說 "I love" 的同時執行揮手動作,再繼續說話
await presenter.present("I love [MOTION wave:1] my avatar.");
💡
Motion Browser 是快速探索可用動作、複製動作 ID 到自己腳本的最佳方式—— 在編輯器旁開啟它,隨時當作動作參考手冊使用。

示範

功能

  • Avatar 預覽 — 全螢幕 3D 渲染,可從頂部選擇器即時切換角色。
  • Motion Library — 瀏覽、搜尋、篩選所有可用動作。點擊任一卡片即可在 Avatar 上即時預覽。
  • Script Composer — 富文字編輯器,可在說話文字中混入動作 chip;按下 Play,Avatar 按順序說話並執行動作。
  • 場景與聲音切換 — 底部控制列可即時切換場景與聲音,無需重新載入。

快速開始

cd tools/motion-browser
cp .env.example .env   # 預設值已填入正式環境設定,無需修改
pnpm install
pnpm dev

pnpm dev 啟動後,開啟印出的 URL,以 Perxona 帳號登入並選擇 Avatar。 Presenter 會自動初始化並載入動作庫。

在腳本中插入動作標籤

  1. 輸入說話文字

    在 Script Composer 中輸入 Avatar 要說的話。

  2. 插入動作 chip

    在 Motion Library 面板找到目標動作。將游標放在文字中想要插入動作的位置,點擊 + 插入為 chip。

  3. 按下 Play

    Avatar 說完整腳本,並在每個標記位置執行對應動作。chip 會序列化為 [MOTION <id>:1] 並直接傳入 presenter.present()

Motion Browser

Motion Browser は、Perxona が提供するモーションカタログを探索し、3D アバター上でアニメーションをライブプレビューし、 テキストとモーション指定を組み合わせたスクリプトを作成できる、ブラウザベースの開発者ツールです。

中核となる考え方<sv-presenter> Web コンポーネントはインラインモーションタグを理解します。 スクリプトテキストのどこにでも [MOTION id:1] を挿入すると、アバターはその発話のタイミングでモーションを実行します。

// "I love" と言う際にウェーブモーションを実行し、発話を続けます
await presenter.present("I love [MOTION wave:1] my avatar.");
💡
Motion Browser は利用可能なモーションを発見し、IDをスクリプトにコピーする最速の方法です—— エディターの横で開いて、ライブのモーションリファレンスとして活用してください。

デモ

機能

  • アバタープレビュー — フルスクリーン 3D レンダリング。上部セレクターからキャラクターをリアルタイム切り替え。
  • Motion Library — 利用可能なすべてのモーションを検索・フィルタリング。カードをクリックするとアバター上でライブプレビュー。
  • Script Composer — テキストにモーションチップを混在させるリッチテキストエディター。Play を押すとアバターがシーケンス通りに発話&モーション実行。
  • シーン・音声切り替え — 下部コントロールバーでシーンと音声をリロードなしに即時変更。

開始する

cd tools/motion-browser
cp .env.example .env   # 本番設定が事前入力済み、編集不要
pnpm install
pnpm dev

pnpm dev 起動後、表示された URL を開いて Perxona アカウントでサインインし、 アバターを選択します。Presenter が自動初期化してモーションライブラリが読み込まれます。

スクリプトにモーションタグを挿入する

  1. スピーチテキストを入力

    Script Composer にアバターに発話させたいテキストを入力します。

  2. モーションチップを挿入

    Motion Library パネルで目的のモーションを見つけます。テキスト中の挿入したい位置にカーソルを置き、+ をクリックしてチップとして挿入します。

  3. Play を押す

    アバターがスクリプト全体を発話し、各マーク位置でモーションを実行します。チップは [MOTION <id>:1] にシリアライズされ、presenter.present() に直接渡されます。

VRM Uploader

Perxona Connect Kit: VRM 1.0 Character Upload Now Available

Perxona Connect Kit lets you add your own VRM 1.0 characters to the avatar catalog with upload assistance from a Perxona team member — no extra infrastructure required. Whether you want a branded mascot for your product, a custom digital presenter for your audience, or a hand-crafted character for a personal project, this is the fastest path from a .vrm file to a live, speaking avatar.

🪆
Uploaded avatars are scoped to your Perxona organization account. Any member of the same org can select them from the Connect Kit avatar dropdown immediately after upload — no redeploy needed.
⚠️
Beta notice: Connect Kit is currently in closed beta. VRM avatars uploaded today are expected to expire after one month and will no longer be maintained. Perxona reserves the right to remove them. We will maintain VRM files uploaded after a future Connect Kit release.

To get your VRM file uploaded to your account, simply speak to a Perxona team member — they'll handle the upload and have your avatar ready to use right away.

Once the upload is complete, your new VRM character will appear in the avatar list returned by GET /assets/avatars, ready to use in your project.

VRM Uploader

Perxona Connect Kit:VRM 1.0 角色上傳功能正式推出

Perxona Connect Kit 可透過 Perxona 工作人員協助,將你自己的 VRM 1.0 角色加入 Avatar 目錄供選用——無需額外架設任何基礎設施。無論你想為產品打造品牌吉祥物、為受眾建立專屬的數位主持人,或是為個人專案製作原創角色,這都是從 .vrm 檔案到上線說話 Avatar 的最快路徑。

🪆
上傳的 Avatar 僅對你的 Perxona 組織帳號可見。同組織的成員在上傳完成後即可立即在 Connect Kit Avatar 下拉選單中選取——無需重新部署。
⚠️
封測提醒:Connect Kit 目前仍處於封測階段。今日上傳的 VRM 角色預計將於一個月後失效,且不再維護;Perxona 保留移除這些角色的權利。未來 Connect Kit 版本更新後,才會維護新上傳的 VRM 檔案。

如需將 VRM 檔案上傳至你的帳戶,請洽詢 Perxona 工作人員,他們將協助完成所有上傳步驟,讓你的 Avatar 立即可以使用。

上傳完畢後,你便可以在 GET /assets/avatars 的 Avatar 清單中找到剛上傳的 VRM 角色,並將其應用在你的作品中。

VRM アップローダー

Perxona Connect Kit:VRM 1.0 キャラクターアップロード機能が登場

Perxona Connect Kit では、Perxona スタッフのアップロード支援を 受けて、自分の VRM 1.0 キャラクターをアバターカタログに追加できます——追加のインフラ構築は一切不要です。ブランドマスコット、独自のデジタルプレゼンター、個人プロジェクト向けのオリジナルキャラクターなど、どんな用途でも .vrm ファイルからライブで話すアバターへの最速ルートです。

🪆
アップロードしたアバターは Perxona 組織アカウントにスコープされます。同じ組織のメンバーはアップロード完了後すぐに Connect Kit のアバタードロップダウンから選択できます——再デプロイは不要です。
⚠️
クローズドベータに関するお知らせ:Connect Kit は現在クローズドベータ段階です。本日アップロードした VRM アバターは約 1 か月後に失効し、以降は保守対象外となります。Perxona はこれらを削除する権利を留保します。今後の Connect Kit リリース以降にアップロードされた VRM ファイルを保守します。

VRM ファイルをアカウントにアップロードするには、Perxona スタッフにお声がけください。スタッフがアップロードをお引き受けし、すぐにご利用いただける状態にします。

アップロードが完了すると、GET /assets/avatars のアバターリストに新しい VRM キャラクターが表示され、すぐに作品に活用できます。

Known Limitations

  • Sample, not production. Demonstrates the happy path — not hardened, scaled, or feature-complete compared to the full API.
  • Shared credential model. All browser visitors share one Connect identity (the .env service account). Fine for demos; not a multi-tenant production design.
  • CONNECT_TOKEN_EXPIRED is not wired up. The presenter dispatches this event when its token is rejected. This sample doesn't handle it — reload the page to get a fresh token on long sessions.
  • Chat is opt-in. POST /api/chat returns 501 until LLM_API_KEY is set in .env.
  • Minimal UI. Intentionally framework-free vanilla JS — designed for readability, not production polish.

已知限制

  • 範例,非生產環境。展示正常路徑——與完整 API 相比,未經強化、擴展或功能完整。
  • 共享憑證模型。所有瀏覽器訪客共用同一個 Connect 身份(.env 的服務帳號)。適合 Demo;不適合生產環境的多租戶設計。
  • CONNECT_TOKEN_EXPIRED 未連接。presenter 的 token 被拒絕時會觸發此事件。此範例未處理——長時間 session 時請重新載入頁面以獲取新 token。
  • 聊天為可選功能。POST /api/chat.env 中設定 LLM_API_KEY 之前回傳 501
  • 極簡 UI。刻意使用無框架的原生 JS——設計為可讀性優先,非生產就緒。

既知の制限

  • サンプル、本番環境ではありません。ハッピーパスを示すもの——完全な API と比べて堅牢化・スケール・機能完備はされていません。
  • 共有認証情報モデル。すべてのブラウザ訪問者が 1 つの Connect ID(.env のサービスアカウント)を共有します。デモには適していますが、本番のマルチテナント設計には不向きです。
  • CONNECT_TOKEN_EXPIRED は未接続。Presenter のトークンが拒否された時にこのイベントが発行されます。このサンプルは処理しません——長時間セッションではページをリロードして新しいトークンを取得してください。
  • チャットはオプション。POST /api/chat.envLLM_API_KEY が設定されるまで 501 を返します。
  • 最小限の UI。意図的にフレームワークなしのバニラ JS——可読性を優先した設計で、本番向けではありません。

Troubleshooting

疑難排解

トラブルシューティング

Server exits immediately: "PERXONA_API_BASE_URL is required" or "PERXONA_CONNECT_EMAIL and PERXONA_CONNECT_PASSWORD are required" 伺服器立即退出:"PERXONA_API_BASE_URL is required""PERXONA_CONNECT_EMAIL and PERXONA_CONNECT_PASSWORD are required" サーバーが即座に終了:"PERXONA_API_BASE_URL is required" または "PERXONA_CONNECT_EMAIL and PERXONA_CONNECT_PASSWORD are required"

You haven't created .env or left a required value blank. Run cp .env.example .env and fill in the API base URL and your Perxona service account credentials. 你尚未建立 .env 或必填值為空白。執行 cp .env.example .env 並填入 API 基底 URL 和 Perxona 服務帳號憑證。 .env を作成していないか、必須の値が空白です。cp .env.example .env を実行し、API ベース URL と Perxona サービスアカウントの認証情報を入力してください。

Catalog fails to load — status shows 401 or 403 目錄載入失敗——狀態顯示 401403 カタログの読み込みが失敗——ステータスが 401 または 403 を表示

The server's PERXONA_CONNECT_EMAIL/PERXONA_CONNECT_PASSWORD are wrong, or PERXONA_API_BASE_URL points at the wrong region. Double-check the credentials you registered with via the signup/confirm-signup API and verify the API base URL. Check GET /api/health — the upstream field shows reachability. 伺服器的 PERXONA_CONNECT_EMAIL/PERXONA_CONNECT_PASSWORD 錯誤,或 PERXONA_API_BASE_URL 指向錯誤的區域。請重新確認透過 signup/confirm-signup API 註冊時使用的憑證,並檢查 API base URL。檢查 GET /api/health——upstream 欄位顯示可連線性。 サーバーの PERXONA_CONNECT_EMAIL/PERXONA_CONNECT_PASSWORD が誤っているか、PERXONA_API_BASE_URL が誤ったリージョンを指しています。signup/confirm-signup API で登録した認証情報と API base URL を再確認してください。GET /api/health を確認——upstream フィールドで到達可能性を確認できます。

Avatar doesn't appear after clicking Launch 點擊 Launch 後 Avatar 未出現 Launch をクリックしてもアバターが表示されない

Check the browser console for errors. Common causes: the presenter engine failed to load (CORS error — verify PRESENTER_URL with your Perxona contact), or initialize() rejected because the selected avatar/scene IDs don't exist in your account. 檢查瀏覽器控制台的錯誤。常見原因:presenter 引擎載入失敗(CORS 錯誤——向 Perxona 聯絡人確認 PRESENTER_URL),或 initialize() 因所選 avatar/scene ID 在你的帳號中不存在而失敗。 ブラウザのコンソールでエラーを確認してください。よくある原因:presenter エンジンの読み込み失敗(CORS エラー——PRESENTER_URL を Perxona 担当者に確認)、または選択した avatar/scene ID がアカウントに存在しないため initialize() が失敗した。

Avatar appears but doesn't speak Avatar 出現但不說話 アバターは表示されるがしゃべらない

Ensure resumeAudioPlayback() is called inside the Launch button's click handler — not in a timer or after an await that yields control back to the browser. Browsers block autoplay triggered outside a synchronous user gesture. 確保 resumeAudioPlayback() 在 Launch 按鈕的點擊處理器內部呼叫——不在計時器或讓出控制的 await 之後。瀏覽器會阻止在同步使用者手勢之外觸發的自動播放。 resumeAudioPlayback() が Launch ボタンのクリックハンドラー内で呼び出されていることを確認してください——タイマーやブラウザにコントロールを戻す await の後ではなく。ブラウザは同期的なユーザージェスチャー外でトリガーされた自動再生をブロックします。

npm install fails with a Node version error npm install 因 Node 版本錯誤而失敗 npm install が Node バージョンエラーで失敗する

This kit requires Node >=22. Run node --version. If using nvm, run nvm use (reads .nvmrc) or nvm install 22. 此套件需要 Node >=22。執行 node --version 確認版本。若使用 nvm,執行 nvm use(讀取 .nvmrc)或 nvm install 22 このキットには Node >=22 が必要です。node --version で確認してください。nvm を使っている場合は nvm use.nvmrc を読み込む)または nvm install 22 を実行してください。

Chat panel doesn't appear 聊天面板未出現 チャットパネルが表示されない

Set LLM_API_KEY in .env and restart the server. The panel is hidden until the key is present — GET /api/config will return chat: true once it's set. .env 中設定 LLM_API_KEY 並重新啟動伺服器。面板在金鑰存在前是隱藏的——設定後 GET /api/config 將回傳 chat: true .envLLM_API_KEY を設定してサーバーを再起動してください。キーが存在するまでパネルは非表示です——設定後は GET /api/configchat: true を返します。

Next Steps

Once the basic demo is running, here are natural paths forward:

  • Bring your own UI. Replace the vanilla JS frontend with React, Vue, or any framework — the server API (/api/*) stays unchanged.
  • Handle token refresh. Listen for the CONNECT_TOKEN_EXPIRED event and call presenter.refreshConnectToken(newToken) for long-running sessions.
  • Enable chat. Set LLM_API_KEY (and optionally LLM_BASE_URL + LLM_MODEL) in .env to unlock the LLM-powered chat panel.
  • Explore the full API contract. See the OpenAPI spec for the direct Connect API at samples/express/docs/openapi.yaml, and install @perxona/presenter-types@latest for presenter type declarations.
  • Try the Chatbot demo. Open http://localhost:8083/demos/chatbot/ to create and configure a chatbot with full CRUD, multi-turn conversation history, knowledge file upload, and optional function tools — all wired to the avatar presenter.
  • Follow updates and contribute. Star and watch the repository below to track new features and bugfixes.

後續步驟

基本 Demo 運行後,以下是自然的進一步方向:

  • 使用你自己的 UI。用 React、Vue 或任何框架取代原生 JS 前端——伺服器 API(/api/*)保持不變。
  • 處理 token 刷新。監聽 CONNECT_TOKEN_EXPIRED 事件並呼叫 presenter.refreshConnectToken(newToken) 以支援長時間 session。
  • 啟用聊天。.env 中設定 LLM_API_KEY(及可選的 LLM_BASE_URL + LLM_MODEL)以解鎖 LLM 聊天面板。
  • 探索完整 API 合約。參考 direct Connect API 的 OpenAPI spec samples/express/docs/openapi.yaml,並安裝 @perxona/presenter-types@latest 取得 presenter 型別宣告。
  • 嘗試 Chatbot Demo。開啟 http://localhost:8083/demos/chatbot/ 建立並設定 chatbot,支援完整 CRUD、多輪對話記錄、knowledge file 上傳與可選的 function tools——全部整合至 avatar presenter。
  • 追蹤更新並貢獻。Star 並 Watch 下方的 repository 以追蹤新功能和修復。

次のステップ

基本デモが動いたら、自然な次のステップを紹介します:

  • 独自の UI を使用。バニラ JS フロントエンドを React、Vue、または任意のフレームワークで置き換えてください——サーバー API(/api/*)は変わりません。
  • トークンリフレッシュの処理。長時間セッション向けに CONNECT_TOKEN_EXPIRED イベントを監視して presenter.refreshConnectToken(newToken) を呼び出してください。
  • チャットを有効化。.envLLM_API_KEY(オプションで LLM_BASE_URL + LLM_MODEL)を設定して LLM チャットパネルをアンロックしてください。
  • 完全な API コントラクトを探索。direct Connect API の OpenAPI spec samples/express/docs/openapi.yaml を参照し、 presenter 型宣告には @perxona/presenter-types@latest をインストールしてください。
  • チャットボットデモを試す。 http://localhost:8083/demos/chatbot/ を開いて、完全な CRUD・マルチターン会話履歴・ナレッジファイルアップロード・オプションのファンクションツールを備えたチャットボットを作成・設定してください——すべてアバター Presenter と連携しています。
  • アップデートをフォロー・貢献。下のリポジトリをスターしてウォッチし、新機能とバグ修正を追跡してください。

XRSPACE-Inc / perxona-connect-kit

Clone the sample, open issues, and follow updates on GitHub. 在 GitHub 上 clone 範例、提交 issue 並追蹤更新。 GitHub でサンプルをクローン、Issue を開いてアップデートをフォローしてください。