Sound design

Every render can carry sound, and Volito makes it the way it makes pictures: from code, from nothing. No sample library, no files to find, the same track every time.

volito render logo-sting --prop wordmark=VOLITO --style cobalt --sound --bed Dm --format mp4: eight cues read from the motion, on a D minor pad. Turn the sound on.

Sound from the motion

--sound reads the graphic's own motion. Every part's move leaves a mark, and each gets its sound: a spring pops, a move across the frame whooshes (louder the further it travels), letters tick, a typewriter types, a slam hits, a glitch zaps, a burst sparkles. Items nobody wrote sound for sound right out of the box, and a new mood or seed gets a new track to match.

volito render logo-sting --prop wordmark=VOLITO --sound --bed Dm --format mp4 --out sting.mp4
volito render lower-third --prop name="Priya Sharma" --sound --sound-out priya.wav   # ProRes + the track alone
volito sound lower-third --prop name="Priya Sharma" --out priya.wav                  # just the track

volito sound prints the cue list it made, so you can see what lands where:

priya.wav
  5.00 s · 5 cues · peak 0.75
    0.05 s  swell    ×0.70
    0.15 s  tick     ×0.66 +2.25 st pan L0.1
    0.21 s  tick     ×0.57 +4.5 st
    0.31 s  tick     ×0.49 +6.75 st pan R0.1
    0.60 s  whoosh   0.38 s ×0.65 pan R0.3

Options

OptionWhat it does
--soundA track synthesised by Volito, muxed into the video. Without a sound($) in the program, its cues are read from the motion.
--bed <key>A pad under it all, in a key: Dm, "F major", C#m. It steps back under every hit, stamp, sub and pop and comes back on its own.
--sound-level <x>The track's level, 1 by default.
--sound-out <file.wav>Also write the track alone, for an editor's timeline next to a ProRes overlay.

The track is stereo 48 kHz, limited, with a little room. MP4 and HEVC carry it as AAC, ProRes as PCM and WebM as Opus; PNG frames and GIF carry none.

A program's own sound

A program can design its sound beside its frames. function sound($) runs once with the same $ as frame(t, $) ($.dur, $.beat(name), $.at(word), $.data), so the cues land on the beats the picture uses:

function sound($) {
  return {
    cues: [
      { at: 0.2, kind: "riser", dur: 1.1 },
      { at: $.beat("in", 1.3), kind: "hit", level: 1.1 },
      { at: 1.5, kind: "shimmer", dur: 1.2, pan: 0.3 },
      { at: -0.6, kind: "ding", note: "A5", level: 0.6 },   // negative counts from the end
    ],
    bed: { key: "D", mode: "minor", from: 0.8, to: -0.4, level: 0.5 },
    auto: false,   // true adds the cues read from the motion on top
  };
}

Returning just an array of cues works too. Each cue takes at, kind, dur, level (0–2, 1 is the kind's own), pitch (semitones), note (for a tone, chord or ding), pan (−1 to 1) and seed. The whole track also takes level and room (0 dry to 1 wet).

The sounds

KindWhat it is
whoosh swell riser fallAir past, soft air rising, a climb into a moment, the fall after it.
hit stamp sub popAn impact, a heavy slam, a low drop, a bubble pop.
tick click type scratchOne letter or step, a UI click, keys for a while, pencil on paper.
shimmer ding zapSparkle, a bell (note: "A5"), a glitch.
tone chordA note, or the bed's chord: for a sting that resolves.

Keep a graphic's sound honest: one riser into its biggest moment, a hit or a sub when it lands, ticks for the small things, silence between.

From Node, agents and specs

import { findItem, renderVideo, renderSoundFile } from "volito";

await renderVideo(findItem("logo-sting"), { props: { wordmark: "VOLITO" }, sound: true, bed: "Dm", out: "sting.mp4" });
await renderSoundFile(findItem("lower-third"), { props: { name: "Priya Sharma" }, out: "priya.wav" });

Agents get the same through MCP: motion_render takes sound: true and bed, and motion_sound returns the track alone with its cues. In a Graphic spec, "sound": true or { "bed": "Dm", "level": 1.2 } keeps the sound with the graphic. The browser player plays pictures only.