asciinema-player

Embed a lightweight, timing-accurate terminal-session player in any web page, no video files required.

Library
npm
v3.17.0
2,921stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
85/100Excellent
Development Activity96
Maintenance84
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture85
Code Quality80
Innovation88
Learning Curve50

asciinema-player is a web player for terminal session recordings. Unlike a typical video player that streams heavyweight .mp4/.mov files, it replays lightweight, text-based asciicast recordings (and ttyrec/typescript captures) frame by frame, so terminal output stays copy-pasteable, crisp at any zoom level, and tiny to download. It ships as an npm package or a standalone IIFE bundle and drops into any HTML page with a single line of JavaScript.

Under the hood the player pairs a Solid.js UI with a Rust-compiled-to-WASM terminal emulator (vt-js, built on the avt crate) for accurate VT100/xterm rendering, and supports multiple input drivers beyond static files, including WebSocket and Server-Sent Events for live terminal streaming, plus idle-time compression, markers, themes, keystroke overlays, and a JS API for programmatic playback control.

What You Get

  • A single AsciinemaPlayer.create(src, element, opts) call that mounts a full player UI (terminal, control bar, overlays) into any DOM element
  • A Rust/WASM terminal emulator (vt-js, built on the avt crate) for accurate VT100/xterm-style rendering instead of naive text replay
  • Built-in drivers for static recordings, live WebSocket/EventSource streams, benchmarking, and a synthetic clock/random source for demos
  • A programmatic control API (play, pause, seek, getCurrentTime, getDuration, addEventListener) for building custom playback UIs
  • Configurable color themes, adjustable playback speed, idle-time compression, markers with auto-pause, keystroke overlays, and a full-screen mode

Common Use Cases

  • Embedding a CLI tool demo or terminal walkthrough directly in project documentation or a README-rendered site
  • Showing a live, streaming terminal session on a status page or conference-talk slide via the WebSocket/EventSource drivers
  • Replacing screen-recording video files in blog posts and tutorials with a lightweight, text-based, copy-pasteable recording
  • Building a custom playback UI on top of the player’s JS API (custom scrubber, playlist, or synced captions)

Under The Hood

Architecture A Core class (src/core.js) owns the recording/playback state machine: it resolves a src value into one of six pluggable drivers (recording, websocket, eventsource, benchmark, random, clock) and, for file-based recordings, one of three parsers (asciicast, ttyrec, typescript), then serializes every play/pause/seek/step call through an internal command queue so operations always run after driver initialization and in the order they were issued. Rendering is fully decoupled: view.js mounts a Solid.js component tree (Player.js composing Terminal, ControlBar, and overlay components) that talks to Core only through its public methods and an event-handler map, so the state machine has no knowledge of the DOM. The terminal emulation itself is pushed further down into a Rust/WASM module (src/vt), keeping VT100 parsing off the reactive UI layer entirely.

Tech Stack The JS side is plain ES modules built with Rollup (rollup.config.mjs) and Babel’s Solid preset, targeting “defaults and supports wasm” browsers with no transpilation of newer syntax. The UI layer uses Solid.js 1.x for fine-grained reactivity without a virtual DOM. The terminal engine is a separate Rust crate (vt-js, Rust 2024 edition) built on the avt VT100 emulator crate and wasm-bindgen/serde-wasm-bindgen, compiled via @wasm-tool/rollup-plugin-rust and optimized for small code size (opt-level = "z", stripped). Styling is authored in Less and compiled separately. The build produces both a monolithic ESM/IIFE bundle and a split UI/worker bundle pair for offloading emulation to a Web Worker on high-frame-rate streams.

Code Quality Testing is comprehensive and layered: Playwright drives full browser end-to-end specs (tests/player.spec.js and friends) against real .cast fixture files covering initialization, option handling, and error paths, while dedicated unit specs cover parsers (asciicast, ttyrec, typescript), drivers (recording, buffer, segmented/full playback), and utilities (colors, keystrokes, theme, option parsing) in isolation. ESLint 9’s flat config with the Solid plugin and a strict no-unused-vars rule, plus Prettier formatting and a GitHub Actions build workflow, keep style consistent. The public JS API has no TypeScript source but ships a hand-maintained index.d.ts covering options, events, and the returned player object, so type safety is enforced only at the API boundary rather than throughout the implementation.

API Design A single create() entry point returns a small, focused player object (play, pause, seek, getCurrentTime, getDuration, dispose, addEventListener) rather than exposing internal state, and option parsing (opts.js) tolerates both camelCase and legacy-cased keys plus JSON-null values from non-JS embedders. The driver/parser registry pattern makes adding a new recording source or format additive rather than invasive, and the index.d.ts typings give consumers autocomplete and event-payload shapes even though the implementation itself is untyped JS.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search