Vendetta Visual Stream

โ† Back to Index ยท โ† For Visual Artists


Purpose

This page defines the Vendetta Visual Stream Schema (v1) for developers consuming realtime engine output over WebSocket.

This is the contract between vendetta-engine and downstream visual systems.


Transport and Time Model

  • Transport format: line events
  • Event types: stream.meta, stream.frame, stream.transition
  • Time model unit: milliseconds + beat/bar indices
  • t_ms is wall-clock elapsed since playback started
  • beat and bar are musical indices from the engine tick clock

Enums

story_phase

Entering | Sustaining | Transitioning

variance_direction

Rising | Stable | Falling

trigger

PresenceOpened
PresenceClosed
VarianceChanged
WeightBandChanged
SustainChanged
MultiChange

story_label (deterministic, explicit)

absence
escalation_heavy_dry
escalation_heavy_mid
escalation_heavy_wet
groove_heavy_dry
groove_heavy_mid
groove_heavy_wet
wind_down_heavy_dry
wind_down_heavy_mid
wind_down_heavy_wet
build_medium_dry
build_medium_mid
build_medium_wet
drive_medium_dry
drive_medium_mid
drive_medium_wet
cool_medium_dry
cool_medium_mid
cool_medium_wet
rise_light_dry
rise_light_mid
rise_light_wet
minimal_light_dry
minimal_light_mid
minimal_light_wet
fade_light_dry
fade_light_mid
fade_light_wet

Event Schemas

stream.meta

playback_started required fields

  • audio: string (path)
  • bpm: number
  • source: string (spec | reactive_audio)
  • beatmap: string
  • bpmmap: string
  • bpm_hint: string (number-formatted or auto)

When source=spec, the playback input should follow the Song Spec Sheet format.

playback_finished required fields

  • None

stream.frame required fields

  • t_ms: integer >= 0
  • beat: integer >= 0
  • bar: integer >= 0
  • story: story_label
  • phase: story_phase
  • duration: integer >= 0 (beats in current story)
  • weight: number [0..1]
  • presence: number [0..1]
  • var_dir: variance_direction
  • var_mag: number [0..1]

Semantics:

  • Primary continuous controls: weight, presence, var_mag
  • Primary structural controls: story, phase
  • Use phase=Transitioning to pre-blend visual states

stream.transition required fields

  • t_ms: integer >= 0
  • beat: integer >= 0
  • bar: integer >= 0
  • trigger: trigger
  • bridged: boolean
  • from: Story object/string representation
  • to: Story object/string representation
  • requested: Story object/string representation

Semantics:

  • Fire one-shot cues on this event
  • If bridged=true, the engine inserted an intermediate legal transition

Visual Mapping Guidelines

Continuous

  • weight -> scale/intensity/depth
  • presence -> opacity/clarity/saturation
  • var_mag -> motion energy/turbulence rate

Categorical

  • story -> palette/layout/scene family
  • phase -> enter/sustain/exit animation state machine

Transitions

  • Use stream.transition as a hard cue boundary
  • Use stream.frame continuity for smooth interpolation

Stability Contract

  • Story changes only on confirmed state changes (temporal thresholds)
  • absence is outside the matrix and maps to dedicated visual behavior
  • Do not assume every beat changes story

Minimal WebSocket Consumer Pattern

type StreamEventType = "stream.meta" | "stream.frame" | "stream.transition";

interface BaseEvent {
  type: StreamEventType;
}

function handleLine(raw: string) {
  const event = JSON.parse(raw) as BaseEvent & Record<string, unknown>;
  switch (event.type) {
    case "stream.meta":
      // playback_started / playback_finished
      break;
    case "stream.frame":
      // continuous + structural frame data
      break;
    case "stream.transition":
      // one-shot transition cue
      break;
  }
}

Use stream.frame for smooth state and stream.transition for discrete cue triggers.