Liking cljdoc? Tell your friends :D

com.blockether.vis.ext.channel-tui.cinema

Headless session → MP4 screencast. Replays a persisted session's transcript through the REAL TUI render pipeline (screen/render-frame! painting into a Lanterna VirtualTerminal — no TTY needed), and encodes the captured frames to .mp4:

pure-JVM H.264 via jcodec's AWTSequenceEncoder (each frame rendered to a BufferedImage with Java2D). Pixel-exact because WE draw the glyphs — no external player font drift. No native deps, GraalVM-friendly.

The replay is HUMANIZED rather than a flat scroll-through: every disclosure COLLAPSED, the session is re-enacted turn by turn as if it were happening live — a user turn is TYPED IN character by character; before each answer a WORK beat holds the live Vis is calling the provider… spinner in the assistant's place; then the finished answer JUMPS IN and SLOWLY scrolls into view. See session->frames.

The heavy TUI stack (screen, Lanterna) is reached via requiring-resolve so merely loading this namespace stays cheap.

Headless session → MP4 screencast. Replays a persisted session's transcript
through the REAL TUI render pipeline (`screen/render-frame!` painting into a
Lanterna `VirtualTerminal` — no TTY needed), and encodes the captured frames
to `.mp4`:

  pure-JVM H.264 via jcodec's `AWTSequenceEncoder` (each frame rendered to a
  `BufferedImage` with Java2D). Pixel-exact because WE draw the glyphs — no
  external player font drift. No native deps, GraalVM-friendly.

The replay is HUMANIZED rather than a flat scroll-through: every disclosure
COLLAPSED, the session is re-enacted turn by turn as if it were happening
live — a user turn is TYPED IN character by character; before each answer a
WORK beat holds the live `Vis is calling the provider…` spinner in the
assistant's place; then the finished answer JUMPS IN and SLOWLY scrolls into
view. See `session->frames`.

The heavy TUI stack (`screen`, Lanterna) is reached via `requiring-resolve`
so merely loading this namespace stays cheap.
raw docstring

export!clj

(export! session-id opts)

Render session-id to an MP4 screencast file.

opts: :out output path (default: <session-id>.mp4 in the cwd) :cols :rows :fps :theme :font-size :type-cps :work-ms :jump-hold-ms :scroll-rows-per-frame :post-user-ms :post-assist-ms — see defaults

Returns {:path :format :frames :video-ms :cols :rows}.

Render `session-id` to an MP4 screencast file.

opts:
  :out      output path (default: <session-id>.mp4 in the cwd)
  :cols :rows :fps :theme :font-size
  :type-cps :work-ms :jump-hold-ms :scroll-rows-per-frame :post-user-ms :post-assist-ms  — see `defaults`

Returns `{:path :format :frames :video-ms :cols :rows}`.
sourceraw docstring

frames->mp4!clj

(frames->mp4! {:keys [cols rows frames]}
              out
              {:keys [font-size fps] :or {font-size 18 fps 8}})

Encode a session->frames result to out (an MP4 File/path) via jcodec's pure-Java AWTSequenceEncoder. Returns the output File.

Encode a `session->frames` result to `out` (an MP4 File/path) via jcodec's
pure-Java `AWTSequenceEncoder`. Returns the output File.
sourceraw docstring

session->framesclj

(session->frames session-id opts)

Replay session-id headless and return {:cols :rows :frames [{:grid :delay-ms} …] :video-ms}.

opts overrides defaults. The replay is HUMANIZED: rather than dumping the whole transcript and scrolling through it, it RE-ENACTS the session as if it were happening live, one message at a time, with every disclosure COLLAPSED (the natural resting view a live session shows, not an expanded dump):

• a USER turn is TYPED IN character by character — the bubble grows as the text lands, like a human at the keyboard — then a short beat; • before each ASSISTANT answer there is a WORK beat: the LIVE progress bubble holds in the assistant's place (⠿ Vis is calling the provider… 1.2s / Esc to cancel, spinner animating, elapsed clock ticking) so it reads as real work being done; • the finished answer then JUMPS IN whole (a bubble popping in near the bottom of the viewport), holds a beat, then SLOWLY scrolls into view; • a beat to read it, and on to the next turn.

Pacing is by FRAME COUNT at a constant fps (the encoder ignores per-frame delays): every 'beat' is that many repeated frames, and the whole clip length scales with the session's content. scroll/follow carries no :pos, so each captured frame SNAPS to its target — deterministic, no stray ease.

Replay `session-id` headless and return
`{:cols :rows :frames [{:grid :delay-ms} …] :video-ms}`.

`opts` overrides `defaults`. The replay is HUMANIZED: rather than dumping the
whole transcript and scrolling through it, it RE-ENACTS the session as if it
were happening live, one message at a time, with every disclosure COLLAPSED
(the natural resting view a live session shows, not an expanded dump):

  • a USER turn is TYPED IN character by character — the bubble grows as the
    text lands, like a human at the keyboard — then a short beat;
  • before each ASSISTANT answer there is a WORK beat: the LIVE progress
    bubble holds in the assistant's place (`⠿ Vis is calling the provider…
    1.2s / Esc to cancel`, spinner animating, elapsed clock ticking) so it
    reads as real work being done;
  • the finished answer then JUMPS IN whole (a bubble popping in near the
    bottom of the viewport), holds a beat, then SLOWLY scrolls into view;
  • a beat to read it, and on to the next turn.

Pacing is by FRAME COUNT at a constant `fps` (the encoder ignores per-frame
delays): every 'beat' is that many repeated frames, and the whole clip
length scales with the session's content. `scroll/follow` carries no `:pos`,
so each captured frame SNAPS to its target — deterministic, no stray ease.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close