ローカルAPI
自作スクリプトからHTTPやWebSocket経由でコマンド実行、イベント発動、配信の監視を行う
自作スクリプト
POST /api/trigger
Host: 127.0.0.1:21424
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
{
"name": "hype",
"data": {
"name": "mochi"
}
}{"ok":true}イベント
APIトリガー
hype
POST /api/trigger は、その名前を持つAPIトリガーが設定されたすべてのマッピングを発動します。
同一PC上で動作するスクリプト、Stream Deckプラグイン、自作アプリなどからVfinityを操作できます。JSONメッセージを送信して任意のアプリコマンドを実行したりイベントを発動したりできるほか、WebSocketを介してギフト、チャット、結果をリアルタイムで受信できます。
ローカルAPIはOBSオーバーレイと同じサーバー(オーバーレイポート)を共有します。このPC上で動作しているプログラムからのリクエストにのみ応答し、アクセストークンによる認証が必要です。
アルファ版について
Vfinity 2.0 はアルファ版であり、バージョン間で仕様が変わる可能性があります。アップデート後は本番配信の前に必ず動作確認を行ってください。
ローカルAPIを有効化する
ローカルサーバーカードを開く
設定接続 に移動し、詳細 までスクロールします。ローカルサーバー カードを開きます。サーバーが起動しているときは状態欄に http://127.0.0.1:21424 で受信中 と表示されます。
有効にする
ローカルAPIを有効化 をオンにします。初回の有効化時に APIアクセストークン が自動生成されます。
トークンとアドレスをコピーする
トークンの下にある コピー をクリックし、スクリプトに貼り付けます。カードにはステータスURLとWebSocket URLの2つのアドレスも表示されており、クリックしてコピーできます。
トークンを生成 をクリックするとトークンが再生成されます。古いトークンを使用しているすべてのスクリプトは即座に切断されます(オーバーレイや配信接続には影響ありません)。トークンは32〜256文字の英数字、ハイフン、アンダースコアを使って手動で指定することも可能です。
待機ポートは同じカード内の 共有サーバーポート で変更できます。新しいポートはVfinityを再起動した後に有効になります。起動時にポートが使用されていた場合、Vfinityは別の空きポートを自動選択し、実際に使用されているアドレスがカードに表示されます。
このPC
Vfinityはポート8001でVTube Studio APIに接続し、ホットキーの実行やモデルの操作を行います。
Vfinityはポート4455でOBS内蔵のWebSocketサーバーに接続し、シーンの切り替えやソースの表示を行います。
OBSブラウザソースはVfinity自体のサーバー(ポート21424)を開き、投擲、アラート、ウィジェットを描画します。
自作スクリプトはトークンを用いて同じポート21424のローカルAPIにアクセスします。
TikTok LIVE、Twitch、Kick、YouTubeはインターネット経由で通信します。各接続はVfinity自身が直接開始します。
矢印:接続を開始する側
ポート:待ち受ける側
リクエストの検証ルール
すべてのHTTPリクエストおよびWebSocket接続には、以下のヘッダーが必要です:
Authorization: Bearer YOUR_TOKEN他のPCからのリクエスト、トークンが欠落または誤っているリクエスト、あるいはブラウザの Origin ヘッダーを含むリクエストはすべて拒絶されます。最後のルールにより、同一PC上で開かれたWebページであってもAPIを直接呼び出すことはできません。ヘッダーを設定できるデスクトップスクリプトやツールを使用してください。
別のPCのOBSにオーバーレイへのアクセスを許可してもAPIがネットワークに公開されることはなく、オーバーレイのアクセスキーはAPIトークンとしては機能しません。
APIが応答するにはVfinityが起動している必要があります(システムトレイに格納されていても構いません)。アプリを終了すると待機は停止します。
HTTP経由でリクエストを送信する
| リクエスト | ボディ | 応答内容 |
|---|---|---|
GET /api/state | なし | 実行可能なコマンド、登録イベント、配信の各種数値、TikTokの接続状態 |
POST /api/trigger | {"name":"…","data":{…}} | トリガーが受理されると {"ok":true} |
POST /api/command | {"name":"…","args":…} | {"ok":true,"result":…} または {"ok":false,"error":"…"} |
すべての POST リクエストには Content-Type: application/json を指定してください。ボディのサイズは最大64 KiBです。
# 状態と利用可能なコマンドを取得
curl -H "Authorization: Bearer YOUR_TOKEN" http://127.0.0.1:21424/api/state
# サブアソンタイマーに30秒追加
curl -X POST http://127.0.0.1:21424/api/command \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"timer.add","args":30}'$headers = @{ Authorization = "Bearer YOUR_TOKEN" }
# 状態と利用可能なコマンドを取得
Invoke-RestMethod -Uri http://127.0.0.1:21424/api/state -Headers $headers
# サブアソンタイマーに30秒追加
Invoke-RestMethod -Method Post -Uri http://127.0.0.1:21424/api/command `
-Headers $headers -ContentType "application/json" `
-Body '{"name":"timer.add","args":30}'イベントを発動する
イベントに APIトリガー と トリガー名 を設定し、その名前を /api/trigger にPOSTします。名前は大文字と小文字を区別せずに照合されます。
curl -X POST http://127.0.0.1:21424/api/trigger \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"raid_alarm","data":{"message":"Raid incoming","level":3}}'data 内の各フィールドは、イベントのステップで利用できるテンプレート変数になります(例えば {message} を含む読み上げステップは「Raid incoming」と読み上げます)。文字列、数値、真偽値が渡せます。ネストしたオブジェクトや配列は渡せません。フィールド名は英字で始まる必要があり、先頭の50フィールドまでが処理されます。
{"ok":true} という応答は、Vfinityがトリガーを受理したことを意味します。イベントがオフの場合、一時停止中の場合、またはクールダウン中の場合は動作しないため、実際に何が実行されたかを確認したい場合はWebSocketの actionResult を監視してください。
コマンドを実行する
コマンドとは、ホットキー、クイックデッキのパッド、コマンドステップが使用するのと同じ名前付きアクションです。GET /api/state を実行すると現在利用可能なコマンドの一覧を取得できます(一部のコマンドは対応する機能が起動している間だけ存在します)。
{ "name": "control.panic" }
{ "name": "deck.press", "args": "拍手" }
{ "name": "giveaway.draw" }
{ "name": "sceneCard.showBrb" }
{ "name": "mapping.trigger", "args": "YOUR_EVENT_ID" }mapping.trigger は、トリガーが発動したかのように特定のイベントを強制実行し、開始された実行数を返します。イベントのIDまたはAPIトリガー名を引数に取ります。イベントIDを取得するには、「イベント」タブで行を右クリックして イベント ID をコピー を選択します。
全コマンドとその引数は コマンド に記載されています。
スクリプトからTikTok LIVEに接続する
| コマンド | 引数 | 動作 |
|---|---|---|
tiktok.connect | 任意 {"username","autoRejoin","waitForLive"} | 保存済みの設定で接続(今回のセッションのみ上書き可能) |
tiktok.disconnect | なし | LIVEから退出して再接続を停止 |
tiktok.cancelRejoin | なし | 待機や再接続を中止(参加中のLIVEはそのまま維持) |
{
"name": "tiktok.connect",
"args": { "username": "yourname", "autoRejoin": true, "waitForLive": true }
}{"ok":true,"result":{"accepted":true}} という応答はリクエストがキューに追加されたことを意味し、まだLIVEに参加したわけではありません。/api/state の tiktok 部分、またはWebSocketの tiktokStatus を監視してください(VfinityがLIVEに参加すると room.state が "connected" になります)。
WebSocketでリアルタイム受信する
同じ Authorization ヘッダーを付けて ws://127.0.0.1:21424/api/ws に接続します。HTTPと同様のリクエストを任意の requestId を付けて送信できるほか、配信上で発生したイベントがリアルタイムでストリーミングされます。
// npm install ws
const WebSocket = require('ws');
const socket = new WebSocket('ws://127.0.0.1:21424/api/ws', {
headers: { Authorization: 'Bearer YOUR_TOKEN' },
});
socket.on('open', () => {
socket.send(JSON.stringify({ type: 'command', name: 'timer.add', args: 30, requestId: '1' }));
});
socket.on('message', (raw) => {
const message = JSON.parse(raw);
if (message.type === 'event' && message.event === 'gift') {
console.log(`${message.data.nickname} sent ${message.data.giftName}`);
}
if (message.type === 'response') console.log(message.requestId, message.data);
});送信するメッセージ
{ "type": "state", "requestId": "1" }
{ "type": "command", "name": "timer.add", "args": 30, "requestId": "2" }
{ "type": "trigger", "name": "raid_alarm", "data": {}, "requestId": "3" }それぞれに対して1つの応答が返されます:{"type":"response","requestId":"2","data":{"ok":true}}。
Vfinityから送信されるメッセージ
プロパティ
型
コンボの一部であるギフト(giftType が 1)は、コンボの継続中に更新通知を送信します。Vfinityと同様に、repeatEnd が false でないときのみ処理を行ってください。タイムスタンプはUnixミリ秒です。
配信データはリアルタイムのみです。過去のデータは再送されないため、読み込みが遅いクライアントはメッセージを取りこぼす可能性があります。
制限とエラーコード
| 応答 | 原因 |
|---|---|
| HTTP 401 | トークンが欠落または誤っている、あるいは Origin ヘッダーが存在する |
| HTTP 403 | 外部のPCからリクエストが送信された |
| HTTP 503 | ローカルAPIを有効化 がオフになっている |
| HTTP 413 | リクエストボディが64 KiBを超えている |
| HTTP 429 | 同時接続可能な16台のWebSocketクライアント上限に達している |
"busy" | 応答待ちのリクエストが32件に達している |
"timeout" | 10秒以内に応答しなかった(開始済みのコマンドは裏で継続実行されます) |
"unknownCommand" | その名前のコマンドは現在利用できない |
"failed" | コマンドの実行に失敗した(message に理由が記載) |
"invalidName" | name が欠落、空、または200文字を超えている |
通常バックアップでは安全のためトークンは除外され、復元時はAPIが無効の状態で読み込まれます。トークンを保持したい場合はバックアップ時に パスワードやトークンを含める にチェックを入れてください。
逆方向に接続する(Trigger API)
詳細 の下にある トリガーAPI カードは、接続の向きを逆にします:Vfinityがクライアントとして、あなたが起動したWebSocketサーバーへ接続します。ゲームや外部ボットなど、すでにWebSocketサーバーが存在する環境に適しています。
自作スクリプトがポート21424でVfinityにトークン付きで接続します。コマンド実行、イベント発動、状態取得、全ライブイベントの受信が可能です。
Vfinityがあなたのサーバー(デフォルトは localhost:8080)へトークンなしで接続します。あなたのサーバーからトリガーやコマンドを送信したり、APIイベント一覧を要求したりできます。
トリガーAPI をオンにし、WebSocketホスト と WebSocketポート を入力して APIに接続 をクリックします。サーバーから以下のようなメッセージを送信できます:
{ "type": "trigger", "name": "raid_alarm", "data": { "message": "Raid incoming" } }
{ "type": "command", "name": "timer.add", "args": 30, "requestId": "abc-1" }
{ "type": "request", "requestType": "event_list", "requestId": "abc-2" }requestId 付きのコマンドには、{"type":"response","requestType":"command","requestId":"abc-1","data":{"name":"timer.add","ok":true}} のような応答が返されます。event_list はAPIトリガーを持つ全イベントとそのステップ、有効状態を返し、stats は接続状態やイベント数を返します。
あなたのサーバーにアクセスできるプログラムはすべてこれらのコマンドを実行できるため、サーバーをこのPC内に限定するか、手前に認証を挟んで保護してください。