VParamix

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):

NameValue
VtsConnected1 while the Script bridge is connected; otherwise 0.
VtsModelLoaded1 when VTS reports a loaded model; otherwise 0.
VtsFaceFound1 when VTS reports active face tracking; otherwise 0.
VtsHotkeyEventSaturating total count of received hotkey events.
VtsAnimationEventSaturating 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) -> number

Returns 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) -> number

Returns 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) -> number

Queues 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")
end

Use -- @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) -> number

Queues 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) -> number

Queues an immediate absolute transform. Pass exactly three or four finite numbers.

ArgumentAccepted value
xClamped to -1000..1000.
yClamped to -1000..1000.
rotationDegrees, clamped to -360..360.
sizeOptional; 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
OptionTypeDefaultBehavior
onboolean/numbertrueEnables or disables post-processing. Zero is false; other numbers are true.
presetstringnoneTrimmed preset name. Cannot be combined with non-empty values.
fadenumber0.5Fade seconds, clamped to 0..2; must be finite.
reset_othersboolean/numberfalseResets unspecified values to defaults.
restrictedboolean/numberfalseEnables restricted effects.
randomizeboolean/numberfalseRandomizes all effects and clears preset/value updates.
chaosnumber0Randomization amount, clamped to 0..1; must be finite.
valuestableemptyEffect 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) -> number

Requests an ArtMesh selection. Calls are debounced for one second per program.

OptionTypeDefaultBehavior
art_meshesstring or string arrayemptyExact ArtMesh names; blanks and duplicates are removed.
selectedboolean/numbertrueReuses this program's current selection when art_meshes is empty.
countinteger0Requested selection count.
textstringnonePrompt text; retained only when its trimmed length is 4–1024.
helpstringnonePrompt help; retained only when its trimmed length is 4–1024.

vts.selected_art_mesh_count

vts.selected_art_mesh_count() -> number

Returns 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
OptionTypeDefaultBehavior
tint_allboolean/numberfalseTargets every ArtMesh.
art_meshesstring or string arrayemptyExact names; blanks and duplicates are removed.
selectedboolean/numbertrueReuses this program's selection when explicit names are empty.
r, g, b, anumber255Rounded and clamped to 0..255; nonfinite values use 255.
resetboolean/numberfalseForces RGBA to 255.
mixnumber1Scene-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

On this page