Graphics and animation
All docs

Graphics and animation

A graphic is a small HTML page that plays over your video for a stretch of it: a title card, a name and role, an arrow pointing at a button, an animated chart. You write it (or ask Claude Code to), and Sonvo plays it in step with the video everywhere it's watched: on its page, in Slack and in embeds.

The workflow

The same loop you'd use to animate a video file on your own computer, with Sonvo doing the hosting and the playback:

Terminal
sonvo upload raw.mp4 --title "Product tour"      # or record it with Sonvo for Mac
sonvo get <id> --md                                # what's said, and when
sonvo get <id> --words --json                      # every word with its time, to time animations to speech
sonvo frames <id> --every 5s -o frames             # stills to look at
# write title.html ...
sonvo graphic preview <id> title.html --start 0:01 --for 4s --at 0:01.3,0:02.5,0:04.6 -o check
sonvo graphic add <id> title.html --at 0:01 --for 4s --name "Title"
sonvo open <id>

Ask Claude Code something like "animate this video beautifully: a title at the start, my name when I appear, and callouts for the three features" and it can do all of the above, checking its work with sonvo graphic preview before anything goes on the video.

Writing a graphic

  • One HTML page, up to 1 MB. Images, fonts, CSS and scripts in files next to it are put inside it when you add it. Google Fonts and scripts from cdn.jsdelivr.net, unpkg.com and esm.sh load from the web.
  • Transparent background. The video shows through everywhere you don't draw.
  • Laid out 1920 CSS pixels wide (change it with --width); the height follows the picture, 1080 for a 16:9 video. It's scaled to fit, so it looks the same in Slack's small player and full screen. Position things against the edges or the centre.
  • Keep it small. A graphic sits on top of someone's screen and face. On the 1920 canvas, titles of 36 to 48 pixels and supporting text of 22 to 28 read well at any player size; keep a card to about a third of the picture's width. An opening or chapter card can go bigger for a moment.
  • Animate position and opacity. Moving, scaling and fading stay smooth everywhere. Keep shadows small and other effects (drawing a line, blurs, colour changes) short.
  • Keep text in the safe area. Captions and the player's controls use the bottom of the picture, and Slack's player puts the title along the top. Keep anything important above the bottom 200 pixels and below the top 90.
  • The camera bubble sits wherever it was in the recording and is drawn over graphics, unless you add the graphic with --above-camera. Preview at the real frames to check.
  • Graphics can't be clicked and play no sound.

Timing

A graphic's clock is the video's. Its CSS animations and transitions start when it comes on, pause when the video pauses, jump when someone scrubs, and speed up at 1.5× or 2×. No code needed for that: write ordinary CSS animations with delays for staggered entrances.

For the exit, the graphic's length is in the CSS variable --sonvo-d:

CSS
.card {
  animation: in .7s cubic-bezier(.2, .8, .2, 1) both,
             out .45s ease-in calc(var(--sonvo-d) - 450ms) forwards;
}
@keyframes in  { from { opacity: 0; transform: translateY(24px) } }
@keyframes out { to   { opacity: 0; transform: translateY(12px) } }

For drawing with JavaScript (canvas, GSAP, Lottie), read the time from sonvo:

JavaScript
sonvo.time       // ms since the graphic came on
sonvo.duration   // its length in ms
sonvo.playing    // whether the video is playing
// Called every frame with the time:
sonvo.onFrame((t, playing) => draw(t));
// GSAP: let Sonvo drive the timeline
gsap.globalTimeline.pause();
sonvo.onFrame(t => gsap.globalTimeline.seek(t / 1000));

Commands

CommandWhat it does
sonvo graphics <id>The video's graphics, with their times
sonvo graphic add <id> <file.html> --at 0:12 --for 6sAdds one (--until 0:18 instead of --for; --name, --box x,y,w,h for part of the picture, --layer, --above-camera)
sonvo graphic update <id> <graphic> [file.html]Changes its HTML, times or place. --at alone moves it and keeps its length
sonvo graphic get <id> <graphic> -o file.htmlWrites its HTML back to a file, to edit it
sonvo graphic rm <id> <graphic|all>Removes one, or all of them
sonvo graphic bake <id> [graphic|all]Draws its frames for downloads. add and update do this for you
sonvo graphic preview <id> <file.html> --start 0:12 --at 0:13,0:15Saves PNGs of the video with the graphic on it, exactly as viewers will see it: the camera, the logo, captions and the other graphics too. Give a graphic's id instead of a file to check one already on the video, or --replace <graphic> to try a new version of one
sonvo graphic preview --no-video <file.html> --at 0.5,2The graphic on its own, on a checkerboard, before there's a video
sonvo frames <id> --at 0:03,0:10Saves stills of the video (--every 5s for a set)

Times are the video's as people watch it, after your edits. Previews and frames need ffmpeg (brew install ffmpeg), and previews need Google Chrome. sonvo help graphics prints this guide in the terminal.

In downloads

Downloads have the graphics in them, the way the player shows them, whether you download from the video's page or with sonvo download. When you add or change a graphic, the command line draws it frame by frame (30 a second, with a transparent background) and keeps those frames with it; downloads put them on the video at their moments.

  • Animate with CSS, sonvo.time or sonvo.onFrame. Animations that run on the real clock (setTimeout, Date.now) look right in the player but not in a download.
  • A graphic added from a computer without Google Chrome has no frames yet, and downloads leave it out until you run sonvo graphic bake on a computer that has it.
  • sonvo download --no-graphics saves the video without them.

In the editor

Graphics show while you edit, so you can cut around them. The Graphics tab lists them: click one to go to it, or remove it. A video's Markdown for AI (sonvo get <id> --md) lists its graphics and their times too.