General examples

See also: Star Wars ASCIImation (through telnet), Popcorn.js interaction

Terminals have sizes

If you ue termrec to record, the size of the terminal is stored:

<tty-player controls src=sized.ttyrec></tty-player>

Where dimensions are not specified, the terminal defaults to 80 columns and 24 rows.

This demo also shows the controls attribute; the design of the controls is modelled fairly closely after Firefox’s controls for <video>.

Using data: URIs

The ttyrec format being binary, using base64 encoding is the easiest way. I’ve gone with the application/x-ttyrec MIME type, but it really doesn’t matter what you choose.

(This demo also shows the autoplay and loop attributes.)

<tty-player autoplay loop src="data:application/x-ttyrec;base64,

The poster

<video poster> is the URL for an image to display before the video is played; its intent is to give the impression of what the video is about.

<tty-player poster> works on the same principles, but with some differences:

<tty-player controls src=vim.ttyrec poster=npt:16.54></tty-player>


When the src attribute (or property) is set to something that isn’t a ttyrec file (either it doesn’t exist or it’s something else), the error property is set appropriately and the simple error event fired, just like with any other media element; there’s a nifty little error displayer included as seen below.

This demo also demonstrates the rows and cols attributes (mirrored as properties, of course). As mentioned earlier, if you use termrec to record your ttyrec scripts, it records the terminal dimensions in the file it writes; where both are specified, the recording wins and the attributes are ignored.

<tty-player src=non-existent-file cols=72 rows=7></tty-player>

Pretending to be a <video>

<tty-player> implements all of the HTMLMediaElement interface, but it doesn’t implement all of HTMLVideoElement (specifically, it does not implement width, height, videoWidth and videoHeight). Oh, and its tagName is "TTY-PLAYER" instead of "VIDEO". Thus, although it can mostly just be dropped in where a <video> is expected, it can’t entirely by default.

Occasionally what is normally close enough isn’t sufficient; for such cases there is a method that patches the differences up: HTMLTTYPlayerElement.pretendToBeAVideo().

To demonstrate this, we can call that method on all of the TTY players on this page and turn them into MediaElement.js players, and it Just Works™:

You may notice that this is not perfect at present; most notably, the handling of the poster chrome, errors and maybe resizing leave something to be desired. These should be fixed, but they’re fairly low priority for me at present.

MediaElement.js will probably also mess things up on browsers that don’t support <video>.

IDL attributes, events and such

The element implements the contents of the HTMLMediaElement interface plus a bit of the HTMLVideoElement interface. This means that you have properties (defined as IDL attributes) like currentSrc, loop and playbackRate. That last one is a particularly fun one. It’s also got a few additional properties of its own.

Want to see all the events as they get fired, show all the IDL attributes and let you tweak it all? That “Show internals” checkbox in the header does it. (Compare with a similar arrangement on <video>.) Bear in mind that this only applies from the point when the things are added; any events before that time won’t be counted.

Try a negative playbackRate—it works, though it’s rather inefficient (when playing backwards, each frame requires resetting the terminal and writing to that point again, which makes it very expensive for anything but small scripts; it probably works fine for this one)

Large scripts

Large scripts should work fine for playing, though there is no streaming. (XMLHttpReqest doesn’t do streaming and I haven’t determined what else might be able to be done yet.) This simplifies various things internally, but makes large scripts less convenient.

I recorded a 80×24 Vim session that lasted for an hour and a half while I was taking notes on a documentary film (Evolution’s Achilles’ Heel); this produced a 3MB ttyrec file containing 26,389 chunks; gzipped, it’s under 400KB, showing that enabling gzipping of the resource on the server gets a very good return.

Because rendering from start to end is such heavy work, the entire playback will never on my machine go under about 9 seconds, regardless of how high playbackRate is set; this has the effect that panning backwards is prohibitively slow, because it has to play back the entire script from the start; this could in the future be ameliorated by the introduction of keyframes, freezing the relevant state every so often and, rather than rendering from the start render from the latest keyframe. That would either be something that the client could introduce, making the first visit to a point slow but thereafter fast, or some extension of the ttyrec format, increasing size and requiring processing of files to introduce the keyframes.

Just like <video> and <audio>, <tty-player> can have preload=none, which will cause it to hold off on downloading the script until it needs to.

Do not combine preload=none with poster=npt:…; the latter will negate the former (actually, at present it’s implemented badly and poster won’t work at all with preloading disabled until load() is called).

<tty-player src=evolutions-achilles-heel-notetaking.ttyrec preload=none controls></tty-player>