Personaは他のアプリから操作できるローカルWebSocketサーバーを動かします。シーンの切り替え、レイヤーの追加と配置、表情の切り替え、モーションの再生、リップシンク付き音声の再生、トラッキング状態の取得、そしてモデルパラメータへの直接書き込みができます
既定ではオフです。設定 → プラグインAPIでオンにし、キーを作成して、そのトークンをプラグインに貼り付けてください
有効にする
| コントロール | 効果 |
|---|---|
| APIを有効にする | サーバーを起動する。キーがなければ何も接続できない |
| ポート | 既定は25034 |
| ローカルネットワークからのアクセスを許可 | ループバックを越えてバインドし、スマートフォンや別のマシンから接続できるようにする |
ローカルネットワークからのアクセスをオンにすると、このマシンが応答するアドレスが表示されるので、ブラウザをどこへ向ければよいか分かります
ポートがすでに使われている場合、このセクションは黙って失敗するのではなくエラーを表示します
APIキー
キーは必須です——認証のない接続は拒否されます。キーを作成でキーに名前を付けると、そのトークンが一度だけ全文表示されます。行にあるコピーボタンを押せば、いつでも全文を取り出せます
| 操作 | 効果 |
|---|---|
| トークンをコピー | 完全なトークンをクリップボードにコピーする |
| キーの名前を変更 | その場で名前を変更する |
| キーを失効させる | 削除する。そのキーを使っているセッションは閉じられ、再接続しないよう伝えられる |
各キーの行には接続中、未使用、または最終使用とその相対時刻が表示されます。クライアントが名乗ると、直近の名前とバージョンがその行に記録されるため、接続中のクライアントがいなくてもキーを見分けられます
トークンはOSの安全なストレージに保管されます。それが利用できないマシンでは、トークンを平文のファイルに書き込むのではなく、説明を添えてキーの作成が失敗します
プラグインフォルダ
プラグインはモデルやアセットのファイルを登録するようPersonaに依頼し、そのうえで読み込ませることができます。これが通るのはプラグインフォルダに追加したフォルダ内のファイルだけです——それ以外のパスはすべてforbidden-pathで拒否されます
接続中のクライアント
サーバーの動作中は、開いているセッションがすべて一覧表示されます。クライアントが申告した名前、バージョン、開発元、使用しているキー、そして接続元が表示されます。ブラウザのクライアントはページのオリジンを表示します
一度も名乗らないクライアントは不明なクライアントとして並びますが、機能はまったく同じです。行にある切断ボタンを押すとそのセッションが閉じられ、再接続しないよう伝えられます
トークンはパスワードと同じように扱ってください。アプリの操作権限を与えるもので、プラグインフォルダから登録されたあらゆるモデルやアセットの読み込みも含みます。ローカルネットワークからのアクセスをオンにしない限り、サーバーはループバックのみを待ち受けます
Webコンソール
persona.laplace.liveはこのAPIのブラウザ用フロントエンドです。サーバーが動いていることを確認する最速の手段であり、配信の途中でスマートフォンやタブレットから使えるリモコンでもあります
ホスト、ポート、キーを入力すれば、動作中のアプリを操作できます。シーン、レイヤー、表情、モーション、エフェクト、カメラとライティング、ショートカット、トラッキング、設定、そしてパラメータインジェクターです。レイアウトはデスクトップのコントロールパネルと同じで、左にレイヤーとその下に固定されたステージ・トラッキング・ショートカット・パラメータ・設定の5行、右に選択中のものの詳細が入り、ウィンドウが十分に広ければ左右に並びます——違うのは、ここでは各セクションがブックマークできる本物のURLだということです。表情とモーションは専用のページではなく、選んだモデルに属します。エフェクトもアプリと同じくレイヤー一覧の行で、開けばそれぞれのパラメータを調整できます。各セクションは選択中のインスタンスに実際にできることを基準に判定するので、その形式では応えられない機能はエラーを出さずに自ら無効化されます
レイヤー一覧の下にあるシーンに追加ボタンからは、アプリと同じインベントリが開き、中身はAPI経由でレジストリから読み込まれます。ブラウザはネイティブのファイルダイアログを開けないので、ここでの登録はパス指定です——プラグインフォルダに追加したフォルダ内のパスに限られます
シーンのアセットのうち、環境マップとLUTはアプリと同じようにそれぞれタブを持ち、行をクリックすると現在のシーンに適用され、トーストが確認を伝えます。アニメーションには専用のタブがありません。クリップを再生するメソッドがないからです——すべてタブの種類のピッカーから登録し、コンソール自身の選択…ボタンでレイヤーの待機アニメーションとして選びます
キーはブラウザに——暗号化なしで——記憶させることも、そのセッション中だけ保持することもできます。インターネットに出るデータはありません。このページは手元のマシンやローカルネットワーク上のPersonaと直接通信します
HTTPSで配信されるページは127.0.0.1にしかソケットを開けないので、ホスティング版のコンソールが操作できるのはブラウザと同じマシンのPersonaだけです。別の機器のPersonaに接続するには、コンソールを平文のHTTPで配信するか、Personaの前段にTLSプロキシを置いてTLSを使用
(wss://)
をオンにしてください。初回の接続では、ローカルネットワークの権限を求められることもあります
APIのないものはデスクトップアプリ側に残ります。アップデーター、APIキー、トレイアイコン、ウィンドウの位置とサイズ、ネイティブのファイル選択、ステージ上のハンドル、ショートカットの記録、そして3Dオブジェクトや環境に組み込まれたライトです。アプリとシーンのショートカットの作成もデスクトップ側だけで、コンソールからは実行しかできません
Stream Deck
Stream DeckプラグインはこのAPIのもう1つの公式クライアントで、モデルとシーンの切り替え、ホットキー、表情、モーション、そしてアバターの移動とスケールを物理キーの上に載せます
SDK
@laplace.live/persona-sdkは型付きのクライアントで、Node、Bun、ブラウザ、OBSブラウザソースのどこでも同じコードが動きます
import { PersonaClient } from "@laplace.live/persona-sdk";
const persona = new PersonaClient({ token: "sk-lp-v1-…" });
await persona.connect();
await persona.call("expression.toggle", { name: "Smile" });
persona.on("motion.started", (m) => console.log("playing", m.group));すべてのメソッドは1つの共有テーブルで型付けされているので、呼び出しのリクエストとレスポンスの形はメソッド名から決まります。SDKリファレンスでは、インストール、クライアントのオプション、認証、パラメータリース、そしてエクスポートされているすべての型を扱っています
イベント
セッションが受け取るのは、自分が購読したものだけです。SDKは再接続後に購読を張り直すので、ソケットが切れてもイベントの流れが黙って止まることはありません
| イベント | 発火のタイミング |
|---|---|
scene.changed | シーンへのあらゆる変更:作成、削除、名前の変更、適用、編集 |
scene.loading | シーンの適用やパイプラインのウォームアップの開始と終了 |
settings.changed | アプリの設定が変わったとき |
instance.loaded | モデルインスタンスのステージ上での読み込みが完了したとき |
selection.changed | 編集の選択対象が移ったとき。どこからの操作でも |
expression.changed | 適用中の表情の組み合わせが変わったとき |
expression.persistence | モデルの「表情を記憶する」フラグが切り替わったとき |
motion.started | モーションの再生が始まったとき |
motion.ended | モーションの再生が終わったとき |
speech.started | speech.playの発話が始まったとき |
speech.ended | 発話が終わったとき——再生完了、停止、上書きのいずれでも |
hotkey.state | ホットキーの設定が変わったとき |
shortcut.state | グローバルショートカットの一覧・名前・OS登録状態が変わったとき |
tracking.status | フェイストラッキングまたはボディトラッキングの状態が変わったとき |
registry.changed | モデルやアセットが登録されたとき——該当する一覧を読み直すこと |
メソッド一覧
モデルを対象とするメソッドは省略可能なinstanceIdを取り、既定ではシーンのメインモデルに作用します
| グループ | メソッド |
|---|---|
scene.* | list get activate create duplicate rename delete setShortcut patch |
instance.* | list get add setModel remove setVisible setTrackingSources reorder setPrimary setPlacement setMToon setIdle info |
selection.* | get set |
object.* | add rename setContent setSpace setPlacement attach setLightOverrides anchors |
expression.* | list active toggle getPersistence setPersistence |
motion.* | list play playing |
speech.* | play stop |
hotkey.* | list set trigger |
shortcut.* | list trigger |
model.* / asset.* | それぞれのlistとregister |
settings.* | get patch |
tracking.* / pose.* | tracking.addSource tracking.updateSource tracking.removeSource、setEnabled、setSource、加えてpose.setPortとtracking.status |
stage.* | resetTransform resetCamera shockwave |
app.* / session.* | app.info app.localAddresses app.stats、およびsession.identify |
storage.* | get set delete list |
param.* | inject release |
ケイパビリティ
接続先のビルドに何ができるかは、2段階のケイパビリティ一覧が示します。判定にはこれらを使い、バージョン番号は決して使わないでください
アプリ自身のものはhelloとapp.infoが報告します——現在はstorage、speech、shortcutsです。各インスタンス固有のものはinstance.listのcapabilitiesにあり、どのケイパビリティにも含まれないメソッドはunsupported-for-formatで拒否されます
トラッキングソース
Personaでは設定済みのトラッキングソースを複数同時に動かせます。settings.tracking.sourcesが一覧を返し、tracking.addSource、tracking.updateSource、tracking.removeSourceで管理します。instance.setTrackingSourcesはソースIDを使い、インスタンスのフェイスとボディのチャンネル(faceSourceIdとposeSourceId)を対応するソースへ割り当てます。nullを指定するとそのチャンネルのトラッキングが止まり、存在しないIDもnullと同じ扱いです。新しいインスタンスは各チャンネルの既定ソースに割り当てられ、1つのソースを複数のインスタンスで共有できます
フェイスソースはvts-iosかifacialmocapのいずれかで、省略可能なphoneIpで1台の送信元に固定できます。ボディソースはvmcを使い、それぞれが1つのportを持ちます。別のソースが使っているポートは拒否されます。廃止されたvts-ios-nativeはプロトコル上で拒否されます
tracking.statusはフェイスとボディの集約状態に加え、設定済みソースそれぞれの状態をsourcesマップで返します。tracking.statusイベントも同じ形です
従来の単一ソース用メソッドは、引き続き各チャンネルの先頭のソースを扱います。tracking.setSourceはその種類を変更し、pose.setSourceは必要ならVMCソースを作成してポートを返し、pose.setPortはそのポートを変更します。tracking.setEnabledとpose.setEnabledは今もチャンネル全体のマスタースイッチです
音声
speech.playは音声を再生し、その音量で口を動かします。動作するのはspeechケイパビリティを持つインスタンスだけです——これは形式ではなく描画エンジンによって決まるので、インスタンスのランタイムを見てください。現在は既定エンジンのLive2Dがこのケイパビリティを持ち、レガシーWebGLモードにはありません
| パラメータ | 説明 |
|---|---|
url | https:、http:(ローカルのTTSブリッジ)、またはインラインのdata:audio/*ペイロード |
volume | 省略可能。0..1 |
instanceId | 省略可能。既定はシーンのメインモデル |
1つのモデルにつき発話は1つで、新しい再生が現在のものを上書きします。呼び出しが返ってきたら再生が始まったということで、始まらなかった場合はinvalid-stateになります。speech.startedとspeech.endedが発話を挟み、speech.stopで途中終了できます
グローバルショートカット
shortcutsケイパビリティを持つビルドでは、アプリ自身のアプリのショートカット——一連のステージ変更をまとめて実行するマクロ——を一覧・実行できます
| メソッド | 効果 |
|---|---|
shortcut.list | すべてのショートカットを列挙 |
shortcut.trigger | idを指定して1つ実行 |
アクションの中身はアプリ側に留まります。一覧が返すのはid、title、accelerator、registered、そしてactionKindsの配列です——各アクションが何をするかを知らなくても、ボタンを一列描くには十分です。titleがnullのときはactionKindsからラベルを組み立ててください。SDKのshortcutLabelがやっているのがまさにこれです
acceleratorもnullになり得ます。エラーではなく、単にキーの組み合わせが割り当てられていないだけで、shortcut.triggerからは変わらず実行できます。一覧・名前・OS登録状態のいずれかが変わるたび、shortcut.stateが一覧をまるごと送り直します
actionKindsは今後も増える集合です。新しいビルドは、このSDKに名前のない種類を送ってくることがあります。エラーではなく未知のものとして扱ってください——shortcutActionLabelは汎用の名前にまとめます
プラグインストレージ
storage.*はプラグインに永続的なキーバリューストレージを提供し、名前空間はAPIキーごとに分かれます——キーがプラグインの身元であり、同じキー上のすべてのセッションが同じデータを共有し、キーを失効させるとデータも削除されます。値は任意のJSONです
| メソッド | 効果 |
|---|---|
storage.get | キーを読む。一度も書いていないキーはvalue: nullを返す |
storage.set | キーに書き込む |
storage.delete | キーを削除する。存在しないキーでも成功する |
storage.list | すべてのキーをソートして列挙する |
上限はキー名が128文字、シリアライズ後の値が1つあたり64 KB、APIキーあたり256個のキーです。キー数の上限を超えるstorage.setはinvalid-stateを返します
エラー
persona.callは文字列のcodeを持つPersonaApiErrorを投げます:
| コード | 意味 |
|---|---|
parse-error | フレームが妥当なJSONではない |
invalid-request | エンベロープの形式が不正 |
unknown-method | このビルドにそのメソッドがない |
invalid-params | パラメータが検証を通らなかった |
not-found | 参照されたIDが何にも解決されない |
unsupported-for-format | そのインスタンスの形式では実行できない——たとえばLive2DモデルへのMToonの設定 |
conflict | パラメータリースを別のセッションが保持している |
renderer-unavailable | ステージが応答できない——ウィンドウがない、または描画プロセスが再読み込み中 |
forbidden-path | パスが設定済みのどのプラグインフォルダにも含まれていない |
invalid-state | 現在は許可されていない:最後のシーンの削除、ストレージの上限超過、開始できなかった音声など |
internal | それ以外のすべて |
このコードの集合はプロトコルの一部です。クライアントは未知のコードを持つエラーフレームを破棄するので、新しいコードはプロトコルのバージョン更新とともにしか現れず、新たな失敗は既存のコードを再利用します
切断
クライアントは予期しない切断のあと自力で再接続します。サーバー側のクローズコードのうち2つは終端的で、このループを止めます。再接続しても決して成功しないからです:
| コード | 定数 | 原因 |
|---|---|---|
4001 | CLOSE_KEY_REVOKED | キーが失効した |
4002 | CLOSE_FORCE_DISCONNECTED | ユーザーがそのセッションを切断した |
どちらの場合もクライアントは最終的にclosed状態に落ち着きます。onCloseが指定されていれば終端的な切断はそちらへ通知され、onWarningは呼ばれません。onCloseがなければonWarningへフォールバックします。1001はこれに含まれません——サーバーが停止中であることを意味するので、復帰したら再接続してください
失効は即座に効きます。送信待ちのフレームは破棄され、ステージの応答を待っていたリクエストが書き込みに至ることはなく、失効と競合した接続は4001で閉じられます。すでにステージへ渡されたアクションは完了することがあります——失効の直前に届いた場合と同じです——が、そのレスポンスが届くことはありません
バージョンの不一致
プロトコルはバージョンを持っており、接続先のビルドと一致しない場合、SDKは警告を出します。古いPersonaが知らないイベントを購読しても致命的ではありません——SDKは1つずつ購読する方式にフォールバックし、通ったものを保持して、残りについては名前を挙げて警告します
最終更新日:2026年9月3日