pub fn write_cast(
writer: &mut impl Write,
size: Size,
frames: &[CapturedFrame],
) -> Result<()>Expand description
Exports frames as asciicast v3
newline-delimited JSON, written to writer.
frames comes from FrameRecorder or the pty feature’s capture
source. Writes a header line ({"version": 3, "term": {"cols", "rows"}}) sized to size, then one
[interval_seconds, "o", ansi_text] event line per captured frame: interval_seconds is the
time since the previous event (since FrameRecorder::new for the
first), and ansi_text repositions the cursor to
each changed cell (\x1b[{row};{col}H, grouping horizontally-adjacent runs to avoid a move
per cell) and writes its glyph, switching SGR state only when
the style actually changes – exactly what a real terminal session emitting that frame would
have sent, and exactly what an asciicast player (asciinema-player) or converter (agg,
svg-term) expects to replay.
Hand-rolled (via serde_json, not the asciicast/asciicast-rs crates) because this crate
only ever writes v3, never parses any version – a parser’s surface would be pure dead
weight here.
No timestamp header field is emitted: it would be wall-clock-dependent, and this exists for
deterministic, insta-snapshottable captures.
§Known limitation
Buffers and serializes every frame at once rather than streaming events to writer as they’re
captured, so a session’s full cost (memory in FrameRecorder, then
this function’s formatting work) is paid up front. Matches
FrameRecorder’s own whole-session-in-memory limitation; fine for
docs/demo-length captures.
§Errors
Returns an error if writer fails to write.
§Examples
use retroglyph_core::backend::{DrawCell, Headless, Output};
use retroglyph_core::color::Style;
use retroglyph_core::grid::Pos;
use retroglyph_core::tile::Tile;
use retroglyph_recorder::{write_cast, FrameRecorder};
let mut recorder = FrameRecorder::new(Headless::new(3, 1));
let tile = Tile::new('a', Style::default());
recorder
.draw_layers(std::iter::once(DrawCell::new(Pos::new(0, 0), &tile)))
.unwrap();
let mut out = Vec::new();
write_cast(&mut out, recorder.inner().size(), &recorder.frames()).unwrap();
let text = String::from_utf8(out).unwrap();
assert!(text.contains("\"version\":3"));
assert!(text.contains("\"o\""));