Fork me on GitHub

<tty-player>: <video>, but for ttyrec scripts

Introduction

Suppose you have a short screencast of doing something in a terminal. You might make a full recording of it and include it in your web page like this:

<video autoplay controls loop src=tty-screencast.webm></video>

There are plenty of problems with doing it this way, though:

OK, so you use something like ttyrec plus ttygif to record it and produce an animated GIF. But still:

This library offers the real solution: a player for your ttyrec scripts, implementing basically the same interface as <video> so that it’s almost a drop-in replacement.

So here is this library: it provides a <tty-player> element, just like <video> except taking a ttyrec file as its source. (And this particular little example is only 34KB, 8KB gzipped! Take that, traditional video formats! Even a screenshot of one frame of that thing only scrunches to 34KB with optipng -o7, 31KB gzipped.)

<tty-player autoplay controls loop src=tty-screencast.ttyrec></tty-player>

Examples

Using tty-player

  1. Install a tool that can record your terminal appropriately.

    I recommend termrec, because it records the terminal dimensions in the file (and this library knows what to do with it).

    You could also use ttyrec, but dimensions won’t be stored. Or anything else that supports the ttyrec format.

    You cannot use plain old script because even if it supports timing (Mac OS X’s doesn’t) it uses a different format.

  2. Record your terminal! I recommend using the .ttyrec extension, for no particularly good reason.

  3. Add the requirements to your web page:

  4. Start using the <tty-player> element just like you’d use a <video> element! Make sure you use the src attribute; you can’t use <source> elements.

  5. Spruce the styles up, if you like. What’s there at present by way of window chrome is borrowed from my own i3 arrangement.

Browser compatibility

Tested in current Firefox and Chromium on Linux and IE 11 on Windows.Should work across the board in modern browsers.I haven’t yet gone to the trouble of testing in a broader variety of browser,nor is there any semblence of a test suite.Ain’t the web great—if this were Real Life I’d actually feel obliged to write tests!

Miscellaneous notes

I like the word miscellany.

Intended future feature: put an <audio> inside the <tty-player> and playback will be synchronised between them. Text tracks might be implemented as a part of this; I haven’t decided at all. In the mean time, try mixing tty-player with Popcorn.js!

<tty-player> as a drop-in replacement for <video>

<tty-player> implements an interface which I will call HTMLTTYPlayerElement. Here’s its definition:

interface HTMLTTYPlayerElement : HTMLMediaElement {
           attribute DOMString defaultTitle;
           attribute DOMString title;

  readonly attribute unsigned long cols;
  readonly attribute unsigned long rows;
  void resize(unsigned long cols, unsigned long rows);

           attribute EventHandler ontitlechange;

  // This one is straight from HTMLVideoElement.
           attribute DOMString poster;

  // s/void/avoid/
  void pretendToBeAVideo();
}

As implemented, HTMLTTYPlayerElement does not extend HTMLMediaElement, so while document.createElement("video") instanceof HTMLMediaElement, !(document.createElement("tty-player") instanceof HTMLMediaElement. For the most part it would work fine, because all the standard properties of HTMLMediaElement.prototype are overridden in HTMLTTYPlayerElement.prototype, but any that are left will be liable to blow up as soon as you touch them—accessing an unknown property would in Firefox yield a TypeError, for example, because it does not acknowledge my type as implementing the interface HTMLMediaElement. Therefore I think it is safer overall to be content with HTMLElement.

Anyhow: because HTMLTTYPlayerElement implements the same interface in contents, if not in name, as HTMLVideoElement, it’s normally a drop-in replacement. Many things will actually work with it straight off. For those things that don’t, there’s a technique that gets even closer: HTMLTTYPlayerElement.pretendToBeAVideo(). This makes an HTMLTTYPlayerElement patch itself to implement the interface of HTMLVideoElement (width, height, videoWidth and videoHeight; it already has poster). And, for good (?) measure, to override the tagName property so that this.tagName == "VIDEO".

MediaElement.js works pretty well with <tty-player>s masquerading as <video>s, though the handling of the poster is not perfect (you end up with two play button overlays; text posters will probably need to be rasterised with the assistance of a canvas, too).

Popcorn.js doesn’t need the masquerade—give it a <tty-player> instead of a <video> and it’s perfectly happy. (Some plugins might potentially need the masquerade. I haven’t tried everything.)

Comparison of similar products

Terminology:

Features not assessed:

asciinema

This is the only one I’ve found that doesn’t use term.js.

Format:

Audio: no.

Recording:

Hosting: asciinema.org

Player:

showterm

Format: script -t plus initial screen dimensions.

Audio: no.

Recording:

Hosting platform:

Player:

TermRecord

A tool for producing self-contained HTML.

Format: proprietary but simple ([[text, total milliseconds]])

Audio: no.

Recording:

Hosting: n/a (it produces standalone HTML files)

Web client:

shelr

Apparently abandoned.

Format: script -t plus initial screen dimensions.

Audio: no.

Recording:

Hosting:

Player:

tty-player

(This library.)

Format: ttyrec (with support for the slightly non-standard termrec UTF-8 and screen dimension indicators).

Audio: no (but planned, having used the HTMLMediaElement base will make it easier).

Recording: termrec (or ttyrec). Not good for editing, unless someone’s made a tool to do that that I haven’t noticed? I would like to make one at some point, anyway.

Hosting: n/a (it’d be a separate project)

Player: