encode

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package encode turns the driver's (frame, duration) stream into final outputs. PNGSink is the interchange: a directory of exact frames plus an ffconcat manifest with their exact durations — it is a driver.Sink, foley's native PNG output and ffmpeg's staging at once. GIF/MP4/WebM assemble it with ffmpeg through execx (palettegen recipe for GIF, libx264/vp9 for video). Byte-determinism ends at the PNGs and the manifest; the assembled videos are tool-versioned artifacts.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GIF

func GIF(ctx context.Context, framesDir, outPath string, loop int) error

GIF assembles framesDir (a closed PNGSink) into an animated GIF. The last frame's delay cannot come from pts deltas (the -t cut removes the marker entry), so it is passed explicitly via -final_delay — computed from the recording's own last duration, never a fixed default. loop follows ffmpeg's gif semantics (#633): 0 forever, -1 once, N extra repeats.

func MP4

func MP4(ctx context.Context, framesDir, outPath string) error

MP4 assembles framesDir into an H.264 MP4 (yuv420p + faststart: plays everywhere, streams instantly).

func WebM

func WebM(ctx context.Context, framesDir, outPath string) error

WebM assembles framesDir into a VP9 WebM.

func WebP

func WebP(ctx context.Context, framesDir, outPath string) error

WebP assembles framesDir into an animated WebP (#50): libwebp with the recording's exact vfr timing. ffmpeg has no native webp ENCODER, so a build without libwebp cannot produce this format — the error says so and names the way out.

func WriteCast

func WriteCast(path string, cols, rows int, events []CastEvent) error

WriteCast writes an asciicast v2 file (asciinema's format): a JSON header line, then one `[time, "o", data]` event per output burst. Deterministic by construction: no wall-clock header timestamp, and event times are formatted as exact integer microseconds (%d.%06d) — no float formatting crosses the output boundary. Multibyte runes torn across bursts are re-joined by carrying the incomplete tail into the next event: JSON strings must be valid UTF-8, and a replacement character would corrupt the stream a player sees.

Types

type CastEvent

type CastEvent struct {
	At   time.Duration
	Data []byte
}

CastEvent is one observed pty output burst on the recording's timeline (virtual in deterministic mode, wall-elapsed in realtime).

type Frame

type Frame struct {
	Path string
	Dur  time.Duration
}

Frame is one playable entry of a closed recording: a PNG on disk and exactly how long it holds on screen.

func Manifest

func Manifest(framesDir string) ([]Frame, error)

Manifest lists a closed recording's frames in playback order with their exact durations — what `foley play` replays on the wall clock. The manifest's trailing repeated file (the quirk that makes the last duration effective for ffmpeg's concat demuxer) is a boundary marker, not a frame, and is dropped.

type PNGSink

type PNGSink struct {
	// contains filtered or unexported fields
}

PNGSink is the encode interchange: frame-%05d.png files plus an ffconcat manifest carrying the driver's exact durations. Stills land next to them as still-<name>.png. It implements driver.Sink; images are consumed synchronously (encoded to disk before Add returns), honoring the borrowed-buffer contract.

func NewPNGSink

func NewPNGSink(opts PNGSinkOptions) (*PNGSink, error)

NewPNGSink creates the directory if needed and starts an empty recording.

func (*PNGSink) Add

func (s *PNGSink) Add(img *image.RGBA, d time.Duration) error

Add writes the frame and appends its manifest entry.

func (*PNGSink) Close

func (s *PNGSink) Close() error

Close finalizes the manifest. The concat demuxer honors the last duration only when the last file is listed once more — Close appends that entry. A recording with zero frames is an upstream bug and errors.

func (*PNGSink) Frames

func (s *PNGSink) Frames() int

Frames reports how many timeline frames were added. Safe to call from another goroutine while the recording runs — the progress pulse reads it live.

func (*PNGSink) Still

func (s *PNGSink) Still(name string, img *image.RGBA) error

Still writes a named screenshot outside the timeline.

type PNGSinkOptions

type PNGSinkOptions struct {
	// Dir receives the frames, stills and manifest; created if missing.
	Dir string
	// ZeroDuration replaces the one legal zero duration — the final
	// state of a recording that ended on an instant action (see
	// driver.Sink on d == 0) — so the closing frame keeps a visible
	// span. The zero value means 20ms; recorders wanting a longer close
	// set it (or script a trailing pause, which this never overrides).
	ZeroDuration time.Duration
}

PNGSinkOptions configures a PNGSink. Dir is required.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL