Personaは他のアプリから操作できるローカルWebSocketサーバーを提供します。シーンの切り替え、レイヤーの追加と配置、表情の切り替え、モーションの再生、リップシンク付き音声の再生、トラッキング状態の取得、そしてモデルパラメータへの直接書き込みができます
既定ではオフです。設定 → プラグインAPIでオンにし、キーを作成して、そのトークンをプラグインに貼り付けてください
有効にする
| コントロール | 効果 |
|---|---|
| APIを有効にする | サーバーを起動する。キーがなければ何も接続できない |
| ポート | 既定は25034 |
| ローカルネットワークからのアクセスを許可 | ループバックを越えてバインドし、スマートフォンや別のマシンから接続できるようにする |
ローカルネットワークからのアクセスをオンにすると、ブラウザからの接続に使えるアドレスが表示されます
ポートがすでに使われている場合、エラーが表示されます
APIキー
キーは必須です——認証のない接続は拒否されます。キーを作成でキーに名前を付けると、そのトークンが一度だけ全文表示されます。行にあるコピーボタンを押せば、いつでも全文を取り出せます
| 操作 | 効果 |
|---|---|
| トークンをコピー | 完全なトークンをクリップボードにコピーする |
| キーの名前を変更 | その場で名前を変更する |
| キーを失効させる | 削除する。そのキーを使っているセッションは閉じられ、再接続しないよう伝えられる |
各キーの行には接続中、未使用、または最終使用とその相対時刻が表示されます。クライアントが名乗ると、直近の名前とバージョンがその行に記録されるため、接続中のクライアントがいなくてもキーを見分けられます
トークンはOSの安全なストレージに保管されます。それが利用できないマシンでは、トークンを平文のファイルに書き込むのではなく、説明を添えてキーの作成が失敗します
プラグインフォルダ
プラグインはモデルやアセットのファイルを登録するようPersonaに依頼し、そのうえで読み込ませることができます。登録できるのはプラグインフォルダに追加したフォルダ内のファイルだけです——それ以外のパスはすべてforbidden-pathで拒否されます
接続中のクライアント
サーバーの動作中は、開いているセッションがすべて一覧表示されます。クライアントが申告した名前、バージョン、開発元、使用しているキー、そして接続元が表示されます。ブラウザのクライアントはページのオリジンを表示します
一度も名乗らないクライアントは不明なクライアントとして並びますが、機能はまったく同じです。行にある切断ボタンを押すとそのセッションが閉じられ、再接続しないよう伝えられます
接続を受け付けるたびに、どのクライアントがどのキーでどこから接続したかを示す無音のシステム通知も表示されます——キーが他人の手に渡っても、使われた時点で表に出ます。OSが通知を拒否する場合——署名のない開発ビルド、権限がオフ——は、同じ内容がコントロールパネルの表示中にトーストとして現れます。ステージには決して出ません。そこに出たものはキャプチャに写り込むからです
トークンはパスワードと同じように扱ってください。アプリの操作権限を与えるもので、プラグインフォルダから登録されたあらゆるモデルやアセットの読み込みも含みます。ローカルネットワークからのアクセスをオンにしない限り、サーバーはループバックのみを待ち受けます
Webコンソール
persona-console.laplace.liveは、このAPIの上に実装されたWebコンソールです。公式の「プラグイン」として、接続の確認や、配信中にスマートフォンやタブレットからPersonaを操作する際に使えます
ホスト、ポート、キーを入力すると、シーン、レイヤー、表情、モーション、エフェクト、カメラ、ライティング、オートメーション、トラッキング、設定を操作できます。デスクトップのコントロールパネルと同じく、左側にレイヤー一覧、その下にステージ・トラッキング・オートメーション・設定が並びます。幅に余裕があれば、選択した項目の詳細が右側に表示されます。各セクションにはブックマークできるURLがあります。表情とモーション、パラメータのバインドはモデルを選択して操作し、エフェクトはシーンエフェクトから選んでパラメータを調整します。選択したモデルや3Dオブジェクトには、それぞれ独自のレイヤーエフェクトもあります。選択中のインスタンスが対応していない項目は無効になります
レイヤー一覧の下にあるシーンに追加ボタンからインベントリを開けます。内容はAPI経由でPersonaのレジストリから取得します。コンソールからファイルを登録する場合は、デスクトップ側のマシン上のパスを入力してください。プラグインフォルダに設定したフォルダ内のファイルのみ登録できます
シーンのアセットには、環境マップとLUTのタブがあります。行をクリックすると現在のシーンに適用され、確認のトーストが表示されます。APIはクリップの直接再生に対応していないため、アニメーション専用のタブはありません。すべてタブで種類を選んで登録し、選択…ボタンからレイヤーの待機アニメーションに設定してください
シーンを選択すると、ライティングに3Dオブジェクトや環境に組み込まれたライトが並び、デスクトップと同じスイッチと強度スライダーで調整できます。読み込んだアセットのサイズやglTF拡張の情報もここに表示されます
キーは暗号化せずにブラウザへ保存するか、現在のセッション中だけ保持するかを選べます。操作リクエストは、手元のマシンまたはローカルネットワーク上のPersonaへ直接送信されます
HTTPSのホスティング版コンソールから暗号化されていないws://で接続する場合は、127.0.0.1を指定してブラウザと同じマシンのPersonaに接続してください。別の機器のPersonaに接続するには、コンソールを平文のHTTPで配信するか、Personaの前段にTLSプロキシを置いてTLSを使用
(wss://)
をオンにしてください。初回の接続では、ローカルネットワークの権限を求められることもあります
APIのないものはデスクトップアプリ側に残ります。アップデーター、APIキー、トレイアイコン、ウィンドウの位置とサイズ、ネイティブのファイル選択、ステージ上のハンドル、ショートカットの記録です。オートメーションの編集もデスクトップ側だけです。コンソールのオートメーションページでは一覧と実行ができ、その下の折りたたみ式のアバターショートカットセクションにメインモデルのショートカットが並びます。デスクトップで一時停止したオートメーションは一時停止中と表示され、実行できません
Stream Deck
Stream DeckプラグインはこのAPIのもう1つの公式クライアントで、モデルとシーンの切り替え、ホットキー、表情、モーション、そしてアバターの移動や拡大縮小を物理キーで操作できます
MCPサーバー
@laplace.live/persona-mcpは3つ目です。Model Context ProtocolのサーバーとしてこのAPIをAIアシスタント——Claude、Cursor、Codex——に渡し、タスク単位の20個ほどのツールとして提供します。それ以外はcall_apiから呼べ、stage.captureでアシスタント自身が結果を見られます
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-stopを持つホストではoneShotも付きます |
motion.ended | モーションの再生が終わったとき |
speech.started | speech.playの発話が始まったとき |
speech.ended | 発話が終わったとき——再生完了、停止、上書きのいずれでも |
hotkey.state | ホットキーの設定が変わったとき |
automation.state | オートメーションの一覧・名前・トリガーの種類・有効状態・OS登録状態が変わったとき |
tracking.status | フェイスまたはポーズのトラッキング状態、あるいは個々のソースの状態が変わったとき——ウェブカメラの顔・手・体のトラッキングを含む |
registry.changed | モデルやアセットが登録されたとき——該当する一覧を読み直すこと |
メソッド一覧
モデルを対象とするメソッドは省略可能なinstanceIdを取り、既定ではシーンのメインモデルに作用します
| グループ | メソッド |
|---|---|
scene.* | list get activate create duplicate rename delete patch inspect setLightFollowCamera |
instance.* | list get add setModel remove setVisible setEffects setTrackingSources reorder setPrimary setPlacement attach setMToon setIdle setControllerMovement setLipSync info |
binding.* | get preview set release inputs override |
controller.* | state rename setDeadZone remove assign |
selection.* | get set |
object.* | add addMany rename setContent setSpace setPlacement attach setLightOverrides anchors |
expression.* | list active toggle getPersistence setPersistence |
motion.* | list play playing stop |
speech.* | play stop |
hotkey.* | list set trigger |
automation.* | list run |
model.* / asset.* | それぞれのlistとregister、それにregistry.thumbnail |
settings.* | get patch |
tracking.* / pose.* | tracking.addSource tracking.updateSource tracking.removeSource、setEnabled、setSource、加えてpose.setPortとtracking.status |
lipSync.* | state configure restart calibrate |
stage.* | resetTransform resetCamera spawn clearSpawned capture |
app.* / session.* | app.info app.localAddresses app.stats、およびsession.identify |
storage.* | get set delete list |
param.* | inject release |
scene.createは空のシーンを追加してそれをアクティブにします——アプリ上で新規作成したときと同じです——ので、応答のactiveSceneIdが新しいシーンです。新しいシーンのidはここから読みます。シーン一覧の差分を取ってはいけません。その間に別のセッションが作成したシーンが紛れ込むことがあるからです
scene.patchは現在のシーンの背景、カメラ、ライト、環境、切り替え効果を編集します。シーンのアイテムはinstance.*とobject.*で扱います。enabledがfalseのライトは影ごと消えますが、ほかの設定は保持されます。このフィールドの既定値はtrueで、ライトをオフにできないビルドは送ってきません
vrmCameraは丸ごと置き換わります。orbit、fov(1 – 179°)、roll(視線の軸まわりの回転、ラジアン)、projection(perspectiveかorthographic)、clipAssetIdです。古いビルドにはrollとprojectionがなく、0とperspectiveとして扱われるので、これらのコントロールを出す前に返ってきたカメラを確認してください。オービットの角度は任意のラジアン値を、distanceは負の値も受け付けますが、マウスでの操作は従来の狭い範囲のままです。平行投影のビューは幅がabs(distance)になり、fovは保持されますが効かず、distanceが負だと両方の軸が反転します。stage.resetCameraはロールと投影もリセットします
object.addは省略可能なplace2dかplace3dを受け取り、オブジェクトは既定の配置で1フレーム描かれることなく、同じ編集の中でその配置に置かれます。値はobject.setPlacementと同じく範囲内に丸められます。object.addMany { objects }は同じ形のエントリを最大100個、1回のシーン編集として追加し——保存も取り消しも1回分です——instanceIdsをリクエストの順で返します。解決できないアセットが1つでもあると、何も追加されません
instance.attach { instanceId, attach }はLive2Dインスタンスをアイテムとして別のLive2Dモデルにピン留めします。attachはobject.attachと同じ形で、nullを渡すとその場で解除されます。attach.depthは{ kind: 'front' }、{ kind: 'behind' }、{ kind: 'artMesh', id }のいずれかで、最後のものは親モデルのそのアートメッシュのすぐ上にアイテムを差し込みます——親にないIDは前面として扱われます。attach.split、つまり{ itemArtMesh, depth }は、アイテム自身のアートメッシュの1つで切り分け、その下の部分を2つ目の深さへ送ります。object.anchorsの各行にはorderが付きます。リストを取得した時点でのそのアートメッシュの描画順で、深さのコントロールはこれで段を並べます。輪になるピン留めはinvalid-paramsを、VRMインスタンスへの呼び出しはunsupported-for-formatを返します。オブジェクトでは、今のところfrontだけが有効です
stage.captureはstage-captureケイパビリティを必要とし、{ dataUrl, width, height }を返します。ステージウィンドウの表示そのままで、アルファ付きのPNGです。最長辺がmaxEdge(64 – 2048、既定値1024)を超えないよう縮小され、拡大は行いません。画面を見られないクライアント——MCPサーバー経由のAIアシスタントなど——が自分の編集を確かめる手段です。1回のキャプチャごとにレンダリングが1フレーム止まるので、必要なときだけ取得し、ポーリングはしないでください。renderer-unavailableはステージウィンドウがなかったか、コピーできるフレームがなかったことを意味します。クラッシュしたステージは再読み込み後に描画するまでこれを返すので、諦めずに再試行してください
ケイパビリティ
対応機能はアプリとインスタンスそれぞれのケイパビリティ一覧で確認できます。バージョン番号を比較するのではなく、この一覧を使って判定してください
アプリ自身のものはhelloとapp.infoが報告します——現在はstorage、speech、automations、layer-effects、scene-transitions、area-lights、spot-lights、camera-follow-lights、shadow-filters、environment-map-model、spawn、tracking-lost、motion-stop、stage-capture、controllers、model-editing、asset-inspectionです。各インスタンス固有のものはinstance.listのcapabilitiesにあり、どのケイパビリティにも含まれないメソッドはunsupported-for-formatで拒否されます
後半の3つはそれぞれ共有エディタのメソッドを開きます。controllersはcontroller.*——接続中の機器と保存済みプロファイルの読み取り、改名、デッドゾーンの設定、削除、割り当ての開始——と、settings.patchから書くcontroller.enabledのマスタースイッチです。機器はデスクトップに接続されているものであって、ブラウザが動いているマシンのものではありません。model-editingはbinding.*(モデルのパラメータバインディングの読み取り・プレビュー・確定・解放と、短時間の入力オーバーライド)とinstance.setBreathです。binding.inputsは{ inputs, outputs }を返し、inputsは現在のトラッキング入力、outputsは各バインディング先のパラメータがモデル上でいま取っている値を出力idごとに返します——モーション・表情・物理演算まで適用した後の値で、読み取れないものは省かれます。asset-inspectionはscene.inspectとregistry.thumbnailです
instance.setControllerMovementはインスタンスのコントローラー移動の設定をマージします:enabled、slot(保存済みプロファイルの番号)、moveSpeed、turnSpeed、smoothing、VRMではさらにwalkEnabled、walkClip、walkSpeed、faceMovementです。範囲外の値は既定値か境界に丸められ、オブジェクトはunsupported-for-formatを返します。walkClipはinstance.setIdleと同じ参照を受け付けます
モーションとアイドル
motion.listはモデルのモーショングループを返します。Live2Dモデルでは、model3.jsonが宣言していない.motion3.jsonもモデルフォルダーからすべて列挙され、それぞれがファイル名を名前とするグループになります。デスクトップのモーションセクションで記録したモーションが再読み込みなしで現れるのはこのためです
motion.stop(アプリのケイパビリティmotion-stop)は再生中のモーションをフェードアウトさせ、アイドルに戻します。アイドルしか再生していないときは何もせず、{ stopped: false }を返します。motion.playingのoneShot(motion.startedにもあります)は、報告されたモーションがアイドルより優先されるもの——つまりstopが終わらせるもの——かどうかを示します。古いビルドではこのフィールドはありません
instance.setIdleはインスタンスのアイドル設定をマージします:
| フィールド | 意味 |
|---|---|
idleAnimation | アイドルのマスタースイッチ。falseはVRMのクリップを止め、Live2Dではモデル自身のIdleグループも含めてすべてのアイドルモーションを止めます |
idleClip | VRMのみ。アイドルクリップの参照 |
idleMotion | Live2Dのみ。インスタンスのケイパビリティidle-motionsが必要です。motion.listにあるモーションファイルを他のすべてのモーションの下でループします。nullはモデルのIdleグループをランダム再生します。モデルが列挙しなくなったファイルはnullと同じ扱いです |
trackingLostBehavior | tracking-lostが必要。holdは最後にトラッキングした姿勢を保ち、idleは約0.3秒かけてアイドルへ戻り、顔が戻ればまた戻ります |
trackingLostMotion | tracking-lostが必要。Live2Dのみ。顔が十分な時間見えなくなったらアイドルの代わりに再生するモーション。nullはアイドルのまま |
trackingLostDelay | tracking-lostが必要。その「十分な時間」の秒数、0〜60 |
instance.getはこれらをすべて報告します
ライティング
area-lightsケイパビリティを持つビルドは、種類がareaのSceneLightを受け付けます。x/y/zに置く長方形で、azimuth/elevation(度)で向きを、roll(−180 – 180°、既定値0)で自身の面内の回転を、widthとheight(それぞれ0.01 – 20シーン単位、既定値1)で大きさを決めます。PBRマテリアルとMToonのアバターを照らし——MToonはトゥーンシェーディングの中で4つのライトサンプルとして近似します——Live2Dには効かず、影も落としません。rangeと影の設定は、あとで種類を変えるときのために保持されます
spot-lightsケイパビリティを持つビルドは種類spotを受け付けます。x/y/z、azimuth/elevation、range(0.1 – 20シーン単位)を使います。方位角と仰角が0のとき光は−Z方向を向き、仰角が正だと下を向きます。angleは円錐の半角(1 – 89°、既定値30)、penumbraは縁の柔らかさ(0 – 1、既定値0.3)です。強度の範囲はポイントライトと同じ0 – 20です。スポットライトはPBRとMToonのマテリアルを照らし、通常のシャドウ品質と半径が使え、ボリューメトリックライティングの霧も照らせます。エリアライトとスポットライトは、新規作成でも種類の変更でも、対応するケイパビリティを持つビルドでだけ提示してください
shadowFilterは平行光源、ポイントライト、スポットライトごとにpcf(既定値)かpcssを選び、両方を同じシーンに混在させられます。shadowQualityは引き続きマップの解像度を決め、offで影を落とさなくなります。PCFはshadowRadius(シャドウマップのテクセル単位)でぼかします。PCSSは遮蔽物を探し、影を落とす物体から離れるほど半影を広げます。その幅を決めるshadowSourceSizeは光源の直径で、平行光源では度、ポイントライトとスポットライトではメートルで表します(0 – 10、既定値0.1)。0にすると影の縁が硬くなります。PCSSは保存済みのshadowRadiusを変えず、古いシーンはPCFとして読み込まれます。フィルターの選択はshadow-filtersケイパビリティで判定してください——ローカルで作ったライトは、対応していないビルドでもshadowFilterを持っていることがあります
camera-follow-lightsケイパビリティを持つビルドは、ライトのfollowCameraを受け付けます。環境光はこれを無視します。既定値はfalseで、trueにするとx/y/zと角度がカメラ基準になり、ライトは手動のカメラ編集にもカメラモーションの再生にも追従します。followCameraOptionsは何に追従するかを選び、どれも既定値はtrueです。positionはカメラの注視点とパン、rotationはロールを含むワールド空間での回転、distanceは符号付きの周回距離です。fovだけを変えてもライトは動きません。オフにした要素は代わりにfollowCameraReference——targetX、targetY、targetZ、distanceとワールド空間のrotationクォータニオン——を使い、その値はオフにした時点で固定されます。参照がなければ、注視点はゼロ、回転は単位回転、距離はゼロとして扱われます
scene.setLightFollowCamera { lightId, followCamera, options? }は、アクティブなシーンのライト1つの追従を切り替えるか、optionsをその選択にマージします。ライトは動かず、向きも変わりません。デスクトップは画面上のカメラ(再生中のカメラモーションを含む)に対してライトの座標を換算し、換算後の設定を{ light }で返します。ライトがもう存在しなければlight: nullです。scene.patchと保存済みのシーンは、書かれた値をそのまま使い、この換算はしません。フィールドもメソッドもcamera-follow-lightsで判定してください
SceneLight.volumetricは、ポイントライト、スポットライト、エリアライト1つごとに、光に照らされる霧をオンにします。既定値はfalseで、ほかの種類は無視します。古いビルドはこのフィールドを送らず、代わりにシーン全体で1つのスイッチを持つので、フィールドがあるか確かめてからコントロールを出してください。そのスイッチをオンにして保存したシーンは、霧を照らせるすべてのライトでvolumetricがオンの状態で読み込まれます
SceneEnvironmentには省略可能なvolumetricLightingとclusteredLightingの2つのフィールドが加わりました。古いビルドは送ってこないので、どちらのコントロールもフィールドがあるか確かめてから出してください。volumetricLightingはシーン全体の霧の見え方を決め、それ自体のスイッチはありません——点灯中のライトがどれも霧をオンにしていなければ、霧は出ません。現在のビルドは霧の設定をすべて返し、clusteredLightingを無効に補正します。編集はscene.patchで環境ごと行います
volumetricLightingのフィールド | 値 | 既定値 |
|---|---|---|
density | 0 – 10 | 1 |
intensity | 0 – 10 | 1 |
range | カメラから1 – 100シーン単位 | 20 |
quality | low、medium、high | medium |
speed | 0 – 5。0で霧が止まる | 0.2 |
霧はオンにしたライトのまわりで光り、深度で遮られ、照らされていない所は透明のままです。点灯中のシーンのライトが1つでも霧をオンにしていれば、3Dオブジェクトと環境モデルに含まれるポイントライト、スポットライト、エリアライトも加わります。透視投影のカメラが必要で、平行投影では設定は残りますが霧は描画されません。平行光源と環境光は関わらず、Live2Dも霧を遮りません。clusteredLighting: trueは、WebGPUの透視投影カメラで、範囲が有限で影を落とさないポイントライトが1 – 64個あるとき、表面のライティングを高速化します。範囲に上限のないポイントライトがある、数がそれを超える、あるいはレンダラーやカメラが対応していない場合は、通常のライティングのままです。影の描画コストは減らず、霧に使われるライトも変わりません
environment-map-modelを持つビルドでは、SceneEnvironmentにiblAssetIdとmodelAssetIdを同時に設定できます。このときbakeFromModelはマップを入力にしてモデルから照明を生成するかを選び、falseならマップで直接照らし、マップがなければモデル自身の空を使います。showSkyboxは表示だけを決め、どちらが照らしていても描くのはマップかその空です。片方のアセットを消してももう片方は残り、SDKのenvironmentClearPatch()がその編集を組み立てます。古いビルドは環境アセットを一度に1つしか持てないので、そこでは片方を設定するときにもう片方を消してください
さらに3つの省略可能なフィールドで、scene.patchからパノラマを調整できます。skyboxBlur(0 – 1、既定値0)とskyboxIntensity(0 – 2、既定値1)は見えているスカイボックスだけを変え、iblRotation(ラジアン、既定値0、1回転を超えて回り込んでよい)はパノラマとその照明をまとめて回します。モデルから生成する照明に使う空も含みます。古いビルドはこれらを送ってこないので、フィールドがあるときだけ対応するコントロールを出してください
物理演算
SceneEnvironment.physicsはシーンの物理演算のスイッチです。3Dオブジェクトがステージの床に落ち、VRMアバターの上にも着地します。既定値はfalseで、古いビルドは送ってきません。シミュレーション中の姿勢は保存されないので、読み返したオブジェクトの配置は書いたとおりのままで、physicsをオフにするとすべてのオブジェクトが元に戻ります
spawnケイパビリティを持つビルドはstage.spawnも受け付けます。登録済みのpropアセットを複製し、物理で動く物体としてステージに降らせるメソッドです。複製はレンダラーの中にだけ存在し——シーンのアイテムにもレイヤーの行にもならず、取り消しも保存もされません——同じファイルの複製はジオメトリ、テクスチャ、ドローコールを共有するので、数百個あっても軽く済みます。アクティブなシーンのphysicsがオフならinvalid-state、登録済みのpropではないアセットならnot-foundを返し、それ以外は{ spawned, alive }を返します。aliveはすべてのアセットの物体の数です
| フィールド | 意味 |
|---|---|
assetId | 登録済みのpropアセット |
count | 1 – 200、既定値1。ステージ上の物体が500個を超えると、古いものから消える |
origin | 散らばらせる立方体の中心。{ x, y, z }をメートルで指定。既定値は{ x: 0, y: 3, z: 0 }で、アバターが立つ位置の上 |
spread | 散らばらせる立方体の一辺。0 – 20メートル、既定値1 |
velocity | すべての物体に共通の初速度。{ x, y, z }をメートル毎秒で指定し、各軸±50以内。既定では静止 |
scale | 0.01 – 100、既定値1 |
ttlMs | 物体が残る時間。0 – 600000ミリ秒、既定値30000。0ならクリアするまで残る |
transition | { style, inMs, outMs }。この物体だけに使う表示・非表示のスタイルと、0 – 5000ミリ秒の出現・消失の長さ。省略したフィールドはシーンの設定を使う |
範囲外の数値は境界に補正されます。物体はttlMsが切れたとき、別のシーンに切り替えたとき、physicsをオフにしたとき、またはstage.clearSpawned {}で消えます。stage.clearSpawnedは{ cleared }を返し、アセットを読み込み中の生成も取り消します
シーン切り替え
scene.activateは切り替え先のシーンが読み込まれてステージを引き継ぐまで待ちます——その間も元のシーンは動作し続け、編集もできます——が、切り替え効果の終了までは待ちません。新しい切り替えは保留中のものを上書きするので、レスポンスが報告するのは実際に有効になったシーンで、要求したシーンとは限りません。SDKはシーンの切り替えを120秒まで待ちます。requestTimeoutMsを指定した場合はそちらが優先されます
scene-transitionsケイパビリティを持つビルドは、各シーンの切り替え効果——そのシーンに入るときに再生される効果——をScene.transitionに持ちます。scene.patch { transition }はこれを丸ごと置き換えますが、再生はしません:
| フィールド | 意味 |
|---|---|
type | cut、fade、wipe、circle、image、videoのいずれか |
durationMs | 100 – 10000ミリ秒 |
color | フェード、ワイプ、円形で覆うカバーの色(16進数) |
assetId | 登録済みの画像か動画、またはnull |
switchPoint | 動画のどこでシーンが切り替わるか。0.05 – 0.95。ステージ全体を覆うフレームを選んでください |
autoFade | 動画をフェードイン・フェードアウトさせる。既定はオフ |
fadeInMs / fadeOutMs | それぞれ再生時間で0 – 10000ミリ秒、既定は300。切り替え点より前・後の長さが上限。0でそのフェードをオフにする |
シーンの切り替えは、どの方法でも切り替え先のシーンの効果を使います。カット以外の効果はすぐに始まり、切り替え先の準備が整うまでステージを覆い続けます。読み込みが遅いときはdurationMsを超えて延長されます。動画はミュートで再生され、速度は長さに合わせて調整され、待つ間は切り替え点のフレームで止まります
表示・非表示
SceneEnvironment.itemTransition { style, durationMs }はシーンの表示・非表示の設定で、モデル、オブジェクト、生成された物体がどのように現れ、消えるかを決めます。古いビルドは送ってきません。styleはglitch(裂け目と焼けを伴うディザディゾルブ、既定値)、dither(余分な効果のないディザディゾルブ)、pop(拡大縮小で現れて消える)、cutのいずれかで、durationMsは0 – 5000、既定値は300です。cutはdurationMsの値にかかわらず変化せず、0もcutと同じ扱いです。編集はscene.patchで環境ごと行います
レイヤーエフェクト
layer-effectsケイパビリティを持つビルドでは、個々のモデルやオブジェクトが独自のエフェクトを持てます。シーンに合成される前に適用されるものです。どのシーンアイテムもシーンと同じ形のeffectsとeffectLayersを持ち、instance.setEffects { instanceId, effects, effectLayers? }で編集します:
effectsはcolor、levels、colorWheels、colorShift、selectColors、gradient、blur、bloom、diffusion、rim、outline、dropShadowの部分的な設定を受け付けます。省略した項目は今の値のままですeffectLayersを指定すると、追加済みエフェクトの一覧を置き換えます。有効なエフェクトは常に一覧に含まれます
レスポンスは補正後の結果です。値は範囲内に丸められ、未知のキーは捨てられます。形式が不正なエフェクトがあると、何も変更されないまま呼び出し全体が失敗します
レイヤーエフェクトがかかるのはモデルと3D空間のオブジェクトです。2Dオブジェクトはunsupported-for-formatを返します。保存された設定は残るので、空間を切り替えれば有効になります
トラッキングソース
Personaでは設定済みのトラッキングソースを複数同時に動かせます。settings.tracking.sourcesが一覧を返し、tracking.addSource、tracking.updateSource、tracking.removeSourceで管理します。instance.setTrackingSourcesはソースIDを使い、インスタンスのフェイス、ポーズ、ハンドのチャンネル(faceSourceId、poseSourceId、handSourceId)を対応するソースへ割り当てます。nullを指定するとそのチャンネルのトラッキングが止まり、存在しないIDもnullと同じ扱いです。新しいインスタンスは各チャンネルの既定ソースに割り当てられ、1つのソースを複数のインスタンスで共有できます
instance.setTrackingSourcesはhandTrackingModeも受け付けます。armsではトラッキングした手がVRMの指に加えて腕と手首も動かし、fingersでは指だけを動かすので、腕はVMCやmocopiの体のトラッキングに任せられます
フェイスソースはpersona-ios、ifacialmocap、vts-iosのいずれかで、省略可能なphoneIpで1台の送信元に固定できます。ポーズソースはvmcかmocopiです。portを持つのはvmc、mocopi、ifacialmocapで、別のソースが使っているポートは拒否されます——1つのソケットを共有できるのはifacialmocap同士だけです。persona-iosとvts-iosのポートはプロトコル側で固定されています。廃止されたvts-ios-nativeはプロトコル上で拒否されます
mediapipeはウェブカメラのソースです。作れるのは1つだけで、portもphoneIpもありません。mediapipeオプションで3つのタスク——チャンネルごとのface、hands、body——を切り替え、deviceId(''で既定のカメラ)、mirror、delegate(CPUかGPU)を設定します。既定ではミラー表示でCPUを使い、顔と手をトラッキングして体はトラッキングしません。tracking.addSourceとtracking.updateSourceは部分的なオブジェクトを受け付け、省略したオプションはそのまま保たれます。トラッキングした手は、注入にある手の入力も動かします
tracking.statusはネットワークのフェイスソースとポーズソースの集約状態に加え、設定済みソースそれぞれの状態をsourcesマップで返します。ウェブカメラも含まれます。tracking.statusイベントも同じ形で、1つのソースの状態だけが変わったときにも発火します
従来の単一ソース用メソッドは、引き続き各チャンネルの先頭のネットワークソースを扱います。tracking.setSourceはその種類を変更し、pose.setSourceは必要ならVMCソースを作成してポートを返し、pose.setPortはそのポートを変更します。tracking.setEnabledとpose.setEnabledは今もネットワークのフェイスソースとポーズソースのマスタースイッチです。ウェブカメラは自身のenabledだけに従い、これはtracking.updateSourceで設定します。タスクの選択とアバターの割り当ては保持されます
マイクによるリップシンク
リップシンクは、デスクトップのマイクで口を動かします。マイクと入力デバイスの一覧はデスクトップ側のもので、ブラウザが動いているマシンのものではありません。音声もキャリブレーションのデータもAPIを通りません。解析結果は注入にある声の入力も動かします
| メソッド | 効果 |
|---|---|
lipSync.state | 設定、キャプチャの状態(off、starting、listening、error)、デスクトップの入力デバイス、リアルタイムの音量と母音のサンプル、進行中のキャリブレーションを読み取る |
lipSync.configure | 部分的な設定——enabled、deviceId、gain(0 – 30 dB)、noiseGate(−60 – 0 dBFS)、smoothing(0 – 0.3秒)——をマージし、保存された結果を返す |
lipSync.restart | 次のフレームでキャプチャを再起動する。オフのマイクをオンにはせず、キャプチャの完了も待たないので、lipSync.stateをポーリングする |
lipSync.calibrate | キャリブレーションを1ステップ実行し、新しい状態を返す |
同じ設定はsettings.lipSyncにも現れ、settings.patchでも書き込めます。キャリブレーションはデスクトップで選択中のマイクを使い、デスクトップのパネルと共有されます。startで下書きを始め、recordにphoneme(A、I、U、E、O、または背景ノイズのS)を添えてその音を2秒録音し、6つすべて録り終えたらpreviewで下書きを適用し、saveかcancelで終えます。resetは現在のマイクを同梱のプロファイルに戻します。録音はすぐに返ってくるので、進み具合はlipSync.stateをポーリングして確認してください。そのcalibrationが段階を表すphase(ready、recording、verifying)、録音中の音、録り終えた音を報告します。現在の段階に合わないステップはinvalid-stateになります
instance.setLipSync { instanceId?, mode }は、マイクでモデルを動かすかどうかを設定します。always(既定)、when-untracked(顔がトラッキングされていないときだけ)、offのいずれかです。オブジェクトはunsupported-for-formatを返します
音声
speech.playは音声を再生し、その音量で口を動かします。動作するのはspeechケイパビリティを持つインスタンスだけで、現在は読み込み済みのLive2Dモデルです。判断は形式ではなくインスタンスのランタイムのケイパビリティで行ってください。0.53以前のバージョンは、削除されたレガシーWebGLエンジンではこのケイパビリティを報告しません
| パラメータ | 説明 |
|---|---|
url | https:、http:(ローカルのTTSブリッジ)、またはインラインのdata:audio/*ペイロード |
volume | 省略可能。0..1 |
instanceId | 省略可能。既定はシーンのメインモデル |
1つのモデルにつき発話は1つで、新しい再生が現在のものを上書きします。呼び出しが返ってきたら再生が始まったということで、始まらなかった場合はinvalid-stateになります。speech.startedとspeech.endedが発話を挟み、speech.stopで途中終了できます
オートメーション
automationsケイパビリティを持つビルドでは、アプリのオートメーション——ショートカット、イベント、リクエストから始まる一連のステージ変更——を一覧・実行できます
| メソッド | 効果 |
|---|---|
automation.list | すべてのオートメーションを列挙 |
automation.run | idを指定して1つ実行 |
アクションの中身、トリガーの設定、編集はアプリ側に留まります。一覧が返すのはid、title、accelerator、registered、enabled、そしてactionKindsとtriggerKindsの配列です——各アクションが何をするかを知らなくても、ボタンを一列描くには十分です。titleがnullのときはactionKindsからラベルを組み立ててください。SDKのautomationLabelがやっているのがまさにこれです。actionSceneIdsはactionKindsと位置が対応し、各switch-sceneの切り替え先シーン(ほかの種類はnull)を持つので、ラベルにシーン名を出せます——ただし、そのシーンはすでに削除されているかもしれません
オートメーションはどれもタイムラインで、そのタイミングはほかの中身と同じくアプリ側に留まるため、actionKindsの順序は実行の順番を表しません。アクションの種類には、タイムラインの開始前に準備として実行されるswitch-sceneとload-model、一時エフェクトのeffect-clip、play-camera-motionとstop-camera-motion、play-audioとaudio-control、そしてアバター向けのtoggle-expression、play-motion、remove-all-expressions、load-model、model-positionがあります。delayはなくなりました——タイムライン上の空白がその役目を果たします。音声には専用のメソッドがなく、ファイル・再生・出力デバイスはデスクトップ側に留まります。クライアントから音を鳴らすには、オートメーションを実行します。triggerKindsは、ショートカット以外にそのオートメーションが持つイベントトリガーの種類を並べたもので、現在はscene、model-loaded、motion、face-tracking、microphone、parameterです
キーボードやコントローラーのショートカットが割り当てられていないとき、acceleratorはnullになります——automation.runからは変わらず実行できます。一時停止中のオートメーションはenabledがfalseで、automation.runを含むすべてのトリガーを無視します。automation.runは実行を送り出した時点で返り、アクションの完了は待ちません。一覧・名前・トリガーの種類・有効状態・OS登録状態のいずれかが変わるたび、automation.stateが一覧をまるごと送り直します
actionKindsとtriggerKindsは今後も増える集合です。新しいビルドは、このSDKに名前のない種類を送ってくることがあります。エラーではなく未知のものとして扱ってください——automationActionLabelは未知のアクションを汎用の名前にまとめます
プラグインストレージ
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 | それ以外のすべて |
このコードの集合はプロトコルの一部です。クライアントは未知のコードを持つエラーフレームを破棄するので、新しいコードはプロトコルのバージョン更新とともにしか現れず、新たな失敗は既存のコードを再利用します
切断
クライアントは予期しない切断のあと、自動で再接続します。ただし、以下のクローズコードでは、キーの失効やユーザーによる切断を尊重して自動再接続を停止します:
| コード | 定数 | 原因 |
|---|---|---|
4001 | CLOSE_KEY_REVOKED | キーが失効した |
4002 | CLOSE_FORCE_DISCONNECTED | ユーザーがそのセッションを切断した |
どちらの場合もクライアントは最終的にclosed状態に落ち着きます。onCloseが指定されていれば終端的な切断はそちらへ通知され、onWarningは呼ばれません。onCloseがなければonWarningへフォールバックします。1001はこれに含まれません——サーバーが停止中であることを意味するので、復帰したら再接続してください
キーを失効させると、送信待ちのフレームは直ちに破棄され、そのキーを使う接続は4001で閉じられます。ステージの応答を待っているリクエストは書き込みを再開しません。すでにステージへ送信された操作は完了する場合がありますが、そのレスポンスは破棄されます
バージョンの不一致
プロトコルはバージョンを持っており、接続先のビルドと一致しない場合、SDKは警告を出します。古いPersonaが知らないイベントを購読しても致命的ではありません——SDKは1つずつ購読する方式にフォールバックし、通ったものを保持して、残りについては名前を挙げて警告します
現在のプロトコルは4です。これまでのバージョン更新ではいずれもワイヤーから何かが取り除かれたので、古いプロトコル向けに書かれたクライアントやプラグインは更新が必要です:
| プロトコル | 変更点 |
|---|---|
| 2 | Scene.behavior(カーソルを目で追う)が、シーンのデータとscene.patchの両方から削除された |
| 3 | stage.shockwaveが削除された。呼び出すとunknown-methodになる |
| 4 | shortcut.list、shortcut.trigger、shortcut.stateがautomation.list、automation.run、automation.stateになり、shortcutsケイパビリティはautomationsに改名された。ペイロードではautomationIdとautomationsを使う |
最終更新日:2026年9月20日