<tty-player>
examples
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,
    AAAAAAttCwCBAAAAG1sxbRtbN20lG1syN20bWzFtG1ttICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgDSANAAAAACNtCwAXAAAAG10yO2NocmlzQGR1b25leDog
    L3RtcAcAAAAAZDsMAC4AAAANG1ttG1syN20bWzI0bRtbSg0KG1swMTszMm0bWzQ1bS90bXAbWzAw
    bSQgG1tLAAAAAJk7DAACAAAAGz0DAAAAg4QBAAEAAABwAwAAAOSsAgADAAAACHBhAwAAAOI2BAAB
    AAAAYwMAAADmNAcAAQAAAGEDAAAA6voIAAEAAAB1AwAAAFxvCgABAAAAcgMAAADNDQwAAQAAACAD
    AAAARQAOAAEAAAAtBAAAAE4/AgABAAAAUwQAAACEZwUAAQAAAHMEAAAARmcHAAEAAAAgBAAAALt4
    CwABAAAAdAQAAACvtA0AAQAAAHQEAAAA29oOAAEAAAB5BQAAAGhKAgABAAAAcgUAAADOlwMAAQAA
    AGUFAAAAOiIGAAEAAABjBQAAAH5RCQAbAAAAGz4NDQobXTI7cGFjYXVyIC1TcyB0dHlyZWMHBwAA
    AOoECACKAwAAG1sxOzM1bWF1ci8bWzBtG1sxbXR0eXJlYyAbWzE7MzJtMS4wLjgtMhtbMG0gKDM0
    KQ0KICAgIEEgdHR5IHJlY29yZGVyIGFuZCBwbGF5ZXINChtbMTszNW1hdXIvG1swbRtbMW10ZXJt
    cmVjIBtbMTszMm0wLjE3LTEbWzBtICgxMSkNCiAgICBBIHNldCBvZiB0b29scyBmb3IgcmVjb3Jk
    aW5nL3JlcGxheWluZyB0ZXh0LXRlcm1pbmFsIHNlc3Npb24sIGluIHRoZSB2ZWluIG9mIHR0eXJl
    Yy4NChtbMTszNW1hdXIvG1swbRtbMW1wbGF5dHR5cmVjIBtbMTszMm0xLjAtMxtbMG0gKDYpDQog
    ICAgYSBwbGF5ZXIgZm9yIHJlY29yZGVkIG5ldGhhY2sgZ2FtZXMgcHJvZHVjZWQgYnkgZGdhbWVs
    YXVuY2gNChtbMTszNW1hdXIvG1swbRtbMW10dHlnaWYgG1sxOzMybTEuMC44LTIbWzBtICg2KQ0K
    ICAgIEEgdG9vbCB0aGF0IGNvbnZlcnRzIGEgdHR5cmVjIGZpbGUgaW50byBnaWYgZmlsZXMuDQob
    WzE7MzVtYXVyLxtbMG0bWzFtaXBidCAbWzE7MzJtMjAxNDEwMjYuMjE5NzQzMi0xG1swbSAoNCkN
    CiAgICBBIGhpZ2gtdGVjaCB0dHlyZWMgcGxheWVyDQobWzE7MzVtYXVyLxtbMG0bWzFtdHR5cmVj
    LWdpdCAbWzE7MzJtMjAxMzA5MTgtMRtbMG0gKDQpDQogICAgQSB0dHkgcmVjb3JkZXIgYW5kIHBs
    YXllciAtIHRoaXMgaXMgbm90IHRoZSBvZmZpY2lhbCB1cHN0cmVhbSB2ZXJzaW9uDQobWzE7MzVt
    YXVyLxtbMG0bWzFtc2VxMmdpZiAbWzE7MzJtMC4xMC40LTEbWzBtICgxKQ0KICAgIENvbnZlcnQg
    YSB0dHlyZWMgcmVjb3JkIGludG8gYSBnaWYgYW5pbWF0aW9uIGRpcmVjdGx5DQobWzE7MzVtYXVy
    LxtbMG0bWzFtc2VxMmdpZi1naXQgG1sxOzMxbTAuMTAuMy4xODIuMjUzZGFjYi0xG1swbSAoMCkN
    CiAgICBDb252ZXJ0IGEgdHR5cmVjIHJlY29yZCBpbnRvIGEgZ2lmIGFuaW1hdGlvbiBkaXJlY3Rs
    eQ0KBwAAAOsGCACYAAAAG1sxbRtbN20lG1syN20bWzFtG1ttICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgDSANG10yO2NocmlzQGR1b25leDogL3RtcAcHAAAA
    x7wIADAAAAANG1ttG1syN20bWzI0bRtbSg0KG1swMTszMm0bWzQ1bS90bXAbWzAwbSQgG1tLGz0I
    AAAAnV8IAAMAAAANDQo="></tty-player>

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>

Errors

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>