VTube Studio API
Complete reference for VTube Studio values and actions in VParamix Lua scripts.
The global vts table reads VTube Studio events and buffers actions through VParamix's active VTube Studio connection. It is available only to Generic Script programs, not Face Tracking expressions.
Availability and return values
Call VTS helpers inside update(). Every action function returns 1 when VParamix accepts the action during the current update and 0 when it does not. Acceptance means queued, not confirmed by VTube Studio.
Actions require an active VTS bridge and valid arguments. Preview, stateless, disconnected, debounced, and queue-full evaluations return 0 and send nothing. If the script later fails, its buffered actions are discarded. Disabling Script or losing the VTS bridge clears queued Script actions.
Read VTube Studio state
These values are regular inputs read with vparamix.params.get(name) or get_previous(name):
| Name | Value |
|---|---|
VtsConnected | 1 while the Script bridge is connected; otherwise 0. |
VtsModelLoaded | 1 when VTS reports a loaded model; otherwise 0. |
VtsFaceFound | 1 when VTS reports active face tracking; otherwise 0. |
VtsHotkeyEvent | Saturating total count of received hotkey events. |
VtsAnimationEvent | Saturating total count of received animation events. |
Every program sees one immutable VTS snapshot per frame. Per-ID event counters survive disconnects; connection, model inventory, queued actions, and ArtMesh selections do not.
Event counters
vts.hotkey_count
vts.hotkey_count(hotkey_id: string) -> numberReturns the accumulated count for the trimmed VTS hotkey ID, or 0 when it has not been observed.
vts.animation_count
vts.animation_count(event_data: string) -> numberReturns the accumulated count for the trimmed animation event value, or 0 when it has not been observed.
VParamix retains at most 1,024 distinct IDs for each event type. Existing retained IDs continue incrementing after that limit.
local count = vts.hotkey_count("hotkey-id")
local previous = load("hotkey-count", 0)
local received = count > previous
save("hotkey-count", count)Trigger a hotkey
vts.hotkey
vts.hotkey(hotkey_id: string) -> numberQueues a trimmed, non-empty VTube Studio hotkey ID. The same program and hotkey ID are debounced for 250 ms.
if keyboard.pressed("Space") then
vts.hotkey("hotkey-id")
endUse -- @inspect source=vts.hotkey on a string literal to select an available hotkey in the editor.
Load a model
vts.load_model
vts.load_model(model_id: string) -> numberQueues a trimmed, non-empty VTube Studio model ID. All scripts and model IDs share a global two-second cooldown.
Use -- @inspect source=vts.model on a string literal to select an available model.
Move the active model
vts.move_model
vts.move_model(x: number, y: number, rotation: number, size?: number) -> numberQueues an immediate absolute transform. Pass exactly three or four finite numbers.
| Argument | Accepted value |
|---|---|
x | Clamped to -1000..1000. |
y | Clamped to -1000..1000. |
rotation | Degrees, clamped to -360..360. |
size | Optional; clamped to -100..100. Omitting it keeps the current size. |
Only the latest queued move remains; a new accepted move replaces older queued moves.
local accepted = vts.move_model(0, 0.2, 5, 0)
output.set("MoveAccepted", accepted)Configure post-processing
vts.post_processing
vts.post_processing(options: VtsPostProcessingOptions) -> number| Option | Type | Default | Behavior |
|---|---|---|---|
on | boolean/number | true | Enables or disables post-processing. Zero is false; other numbers are true. |
preset | string | none | Trimmed preset name. Cannot be combined with non-empty values. |
fade | number | 0.5 | Fade seconds, clamped to 0..2; must be finite. |
reset_others | boolean/number | false | Resets unspecified values to defaults. |
restricted | boolean/number | false | Enables restricted effects. |
randomize | boolean/number | false | Randomizes all effects and clears preset/value updates. |
chaos | number | 0 | Randomization amount, clamped to 0..1; must be finite. |
values | table | empty | Effect IDs mapped to Boolean, string, integer, or number values. Blank IDs and unsupported values are ignored. |
vts.post_processing({
on = true,
fade = 0.5,
values = {
Bloom_Strength = 0.8,
Bloom_Quality = "HIGH",
},
})Select ArtMeshes
vts.select_art_meshes
vts.select_art_meshes(options: VtsArtMeshSelectionOptions) -> numberRequests an ArtMesh selection. Calls are debounced for one second per program.
| Option | Type | Default | Behavior |
|---|---|---|---|
art_meshes | string or string array | empty | Exact ArtMesh names; blanks and duplicates are removed. |
selected | boolean/number | true | Reuses this program's current selection when art_meshes is empty. |
count | integer | 0 | Requested selection count. |
text | string | none | Prompt text; retained only when its trimmed length is 4–1024. |
help | string | none | Prompt help; retained only when its trimmed length is 4–1024. |
vts.selected_art_mesh_count
vts.selected_art_mesh_count() -> numberReturns the number of ArtMeshes currently stored for this program, or 0. A completed selection response updates the originating program's selection. Selection clears on disconnect or a model-load change.
if keyboard.pressed("Space") then
vts.select_art_meshes({ count = 1, text = "Select one ArtMesh" })
end
output.set("SelectedCount", vts.selected_art_mesh_count())Tint ArtMeshes
vts.tint_art_meshes
vts.tint_art_meshes(options: VtsArtMeshTintOptions) -> number| Option | Type | Default | Behavior |
|---|---|---|---|
tint_all | boolean/number | false | Targets every ArtMesh. |
art_meshes | string or string array | empty | Exact names; blanks and duplicates are removed. |
selected | boolean/number | true | Reuses this program's selection when explicit names are empty. |
r, g, b, a | number | 255 | Rounded and clamped to 0..255; nonfinite values use 255. |
reset | boolean/number | false | Forces RGBA to 255. |
mix | number | 1 | Scene-lighting mix, clamped to 0..1; must be finite. |
At least one target is required through tint_all, art_meshes, or the stored selection. A newly accepted tint replaces an older queued tint from the same program.
vts.tint_art_meshes({
selected = true,
r = 255,
g = 128,
b = 128,
a = 255,
mix = 1,
})Queue behavior
The shared Script action queue holds 64 actions, and the output worker processes at most four Script actions per cycle. Queue-full actions return 0 without blocking. Model moves coalesce globally to the latest queued move; ArtMesh tints coalesce per program. These limits make action helpers suitable for frame-driven scripts, but scripts should still trigger discrete actions from edges such as keyboard.pressed() instead of every frame.
Last updated on