Skip to Content
steep

Output formats

Every format reel writes, how big each is, and the options it takes.

An output is a path with optional query parameters, and its extension picks the format. All of these came from one recording of the shop, about six seconds long:

OutputSizeNeeds ffmpegGood for
.gif133.8 KBNoAnywhere an image goes
.webp80.1 KBYesWeb pages. It's the smallest image that animates.
.mp4107.0 KBYesSocial media, chat
.webm110.0 KBYesWeb video, with sharper colored text
.cast20.5 KBNoKeeping the recording, the inspector, asciinema players
.png87.6 KBNoA screenshot of the last frame, or one at each mark
.snap1.5 KBNoThe screen's text, for reading or comparing
.json87.9 KBNoThe screen's cells and state, for comparing or tools

Choosing one

  • For a README or docs page, use WebP. Terminal frames compress very well, it loops, and it stays sharp. These docs use it everywhere.
  • Where WebP won't display, use GIF. It needs no ffmpeg, and works everywhere, at the cost of a larger file and 256 colors per frame.
  • To post somewhere, use MP4. It plays nearly everywhere.
  • To keep the recording, use .cast. It's small, and every other format can be made from it, later.
  • To compare screens in a test, use .snap or .json.

Parameters

Each parameter only applies to some formats. An unknown or repeated one is an error, or one on the wrong format. marks and optimize can repeat.

ParameterFormatsValuesSets
quality.mp4, .webm, .webp0 to 100How close to the frames, from smallest to lossless. WebP is lossless by default, which for terminal frames is smaller than lossy at any useful quality, so a lower value is rarely what you want.
loop.gif, .webpforever, once, or a number of repeats from 1How the animation repeats
max-bytes.gifA size, such as 5MB or 1.5MiBDrops the oldest frames to stay under it
max-frames.gifA numberKeeps only the last frames
optimize.gif, .pngnone, all, frames, dirty, quantizeThe encoder's optimizations. The default is all for GIF, and none for PNG.
full-chroma.mp4, .webmA boolean4:4:4, which keeps thin colored text sharp. Many browsers and phones don't play it in H.264.
background.gif, .mp4, .webm, .webp#rgb or #rrggbbA solid background, which translucent pixels, such as a drop shadow's over a transparent margin, blend into
version.cast2 or 3The asciicast version. The default is 2.
marksAll but .castA mark's labelA still at that mark. The path must hold {mark}.
matchAll but .castA pattern, such as input:*A still at each matching mark. The path must hold {mark}.

Options shared by every output of a profile, such as FPS and Speed, are on the profile rather than here.

In Go

reel.MustFiles and reel.ParseFile read this syntax. To use a value at run time, or to handle errors, use ParseFile:

outputs := reel.MustFiles("out/{timestamp}.gif?max-bytes=5MB&loop=once", "out/{timestamp}.cast")

file, err := reel.ParseFile(os.Getenv("OUTPUT"))

An output can also be a file:// URL, whose path is percent-decoded. Other schemes are errors.

You can build a reel.File directly: its Options are sink.Option values, such as sink.WithQuality(90).

In steep and the CLI

The same syntax works in STEEP_EXPORT and reel -o. The configurator builds these for you.

What's different about each

GIF has one palette per frame and whole-centisecond delays. Cards and other inserted frames get a palette of their own.

PNG without marks is the last frame. It gets the badge of an end pause.

MP4 is H.264, from libx264. It has no transparency, and uses black without a background.

WebM is VP9, from libvpx-vp9.

WebP is from libwebp, and keeps transparency. Builds of ffmpeg without libwebp are common, so check ffmpeg -encoders | grep libwebp if it fails.

.snap is the screen's text at the end of the window, or at each mark. Effects don't change it, so it shows what a redaction hides.

.json is a reel.Screen in the same way. It's what a JSON snapshot holds.

.cast is the timeline itself, with the effects recorded as annotations. It can't be written with a concealer or a cutter.

Last updated on

On this page