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
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
<tty-player autoplay loop src="data:application/x-ttyrec;base64,
<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:
- Images aren’t actually supported at present; just as the poster is typically a frame of the video, images seem less likely to be desirable/useful here. Still, image support will probably come eventually. (In fact, for certain reasons any poster text may well be rasterised.)
- You can specify as the poster a frame from the recording itself by using the
npt: URL scheme. As it uses NPT, values like
1:03:45.678 will all work.
- You can specify arbitrary plain text (control sequences will be evaluated) with
data: URIs of the
text/plain type. (This is demonstrated in the Star Wars example.)
<tty-player controls src=vim.ttyrec poster=npt:16.54></tty-player>
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
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
<tty-player> implements all of the
HTMLMediaElement interface, but it doesn’t implement all of
HTMLVideoElement (specifically, it does not implement
videoHeight). Oh, and its
"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:
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
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
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 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.
<tty-player> can have
preload=none, which will cause it to hold off on downloading the script until it needs to.
Do not combine
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>