Giter Club home page Giter Club logo

asciicast2gif's Introduction

This project is no longer maintained.

In the end the approach it took didn't work well in many cases and it was hard to optimize further. Therefore I won't be putting any more work into it.

See its successor instead: https://github.com/asciinema/agg


asciicast2gif

asciicast2gif is a tool for generating GIF animations from asciicast files recorded by asciinema.

How it works

Here's how the asciicast->GIF conversion is implemented.

asciicast2gif shell script parses command line arguments and executes Node.js script (main.js). main.js loads asciicast (either from remote URL or local filesystem), generates text representation of the screen for each frame using asciinema-player's virtual terminal emulator, and sends it to PhantomJS-based renderer script (renderer.js), which saves PNG screenshots to a temporary directory. Finally, main.js calls ImageMagick's convert on these PNG images to construct GIF animation, also piping it to gifsicle to get the final, optimized GIF file.

Note, asciicast2gif doesn't capture screenshots at a fixed frame-rate (e.g. 30 FPS) like alternative tools. Instead, it generates PNG files for each screen update, and specifies delay for every image individually (convert -delay <delay-a> 0.png -delay <delay-b> 1.png -delay <delay-c> 2.png ...). When the screen is idle there're no screenshots generated. This saves disk space and makes it less work for both convert and gifsicle, while resulting in smaller GIF file.

Installation

You can install asciicast2gif with npm, use it via Docker image, or build it from source.

npm package

To install asciicast2gif using npm run:

npm install --global asciicast2gif

Following runtime dependencies need to be also installed:

Docker image

You can use asciicast2gif through official asciicast2gif Docker image (automated build on Docker Hub from this repository).

Pull the image:

docker pull asciinema/asciicast2gif

Use it like this:

docker run --rm -v $PWD:/data asciinema/asciicast2gif [options and arguments...]

You need to mount some local directory at /data so input and output files can be accessed by the container. Mounting current working directory ($PWD) makes most sense in majority of cases.

For example, generating GIF from local file, with double speed and Solarized theme:

docker run --rm -v $PWD:/data asciinema/asciicast2gif -s 2 -t solarized-dark demo.json demo.gif

Running the above, long command can get old very quickly. Creating a shell alias may be a good idea:

alias asciicast2gif='docker run --rm -v $PWD:/data asciinema/asciicast2gif'

Look at general usage instructions below for all command line arguments, options etc.

Note: if you want to override gifsicle options (via GIFSICLE_OPTS env var) when using Docker image you need to pass it via Docker's -e option.

Building from source

Clone the repository:

git clone --recursive https://github.com/asciinema/asciicast2gif.git
cd asciicast2gif

All further commands are assumed to be called from within the checked out directory.

Install build time dependencies

Both Node.js script (main.js) and page script used by renderer's HTML page (page/page.js) need to be build from ClojureScript source code.

You need Java 8 JDK and Leiningen.

Install runtime dependencies

Following runtime dependencies need to be installed:

Install Node.js wrapper for PhantomJS:

npm install

If you don't have PhantomJS available in $PATH at this point it will be automatically downloaded during phantomjs-prebuilt package installation.

Build

To build the scripts run:

lein cljsbuild once main && lein cljsbuild once page 

Usage

asciicast2gif [-t theme] [-s speed] [-S scale] [-w cols] [-h rows] <input-json-path-or-url> <output-gif-path>

Following options are supported:

-t <theme>        color theme, one of: asciinema, tango, solarized-dark, solarized-light, monokai (default: asciinema)
-s <speed>        animation speed (default: 1)
-S <scale>        image scale / pixel density (default: 2)
-w <columns>      clip terminal to specified number of columns (width)
-h <rows>         clip terminal to specified number of rows (height)

Example of generating GIF from asciicast URL, with default options (normal speed, double pixel density, asciinema theme):

asciicast2gif https://asciinema.org/a/118274.json demo.gif

example gif 1

Example of generating GIF from local asciicast file, with Solarized Dark theme, double speed (-s 2), single pixel density (-S 1):

asciicast2gif -t solarized-dark -s 2 -S 1 118274.json demo.gif

example gif 2

Setting custom gifsicle options

You can override default options passed to giflossy/gifsicle by setting GIFSICLE_OPTS environment variable.

Default options when giflossy is installed are:

-k 64 -O2 -Okeep-empty --lossy=80

Default options when gifsicle is installed are:

-k 64 -O2 -Okeep-empty

For example to generate 16 color gif, with level 3 optimizations, set it like this:

GIFSICLE_OPTS="-k 16 -O3"

Debugging

You can set DEBUG=1 environment variable to make the output of the conversion process more verbose.

Tweaking conversion process

You can pass extra arguments to Node.js script invocation via NODE_OPTS environment variable.

Limiting node process memory usage

Limit Node's heap size to 512 MB:

NODE_OPTS="--max-old-space-size=512" asciicast2gif ...

Alternatives

There are following alternative tools solving this problem:

License

Copyright ยฉ 2017 Marcin Kulik.

asciicast2gif's People

Contributors

anishkny avatar cjhackerz avatar ku1ik avatar publicarray avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asciicast2gif's Issues

Install with npm failing

When I try to install with npm I get some warning messages. I'm not sure which of these is critical, if any, but I cannot execute asciicast2gif after the install.

See the following terminal recording because of course. :-)

asciicast

Set proper Accept header when fetching asciicast via HTTP(S)

http-get function should be explicitly setting Accept: application/json header.

Once this is done, we can make asciinema web app respond properly with JSON when requesting https://asciinema.org/a/<recording-id> (without .json ext). This would make generating GIFs from already uploaded recordings even easier.

Node crashes in docker container

I may be overly hopeful for a 6 minutes of cast to a gif, but this is what I'm getting

docker run --rm -v $PWD:/data asciinema/asciicast2gif -s 1.0 -t solarized-dark demo.cast demo.gif
==> Loading demo.cast...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...

<--- Last few GCs --->

  104433 ms: Mark-sweep 1372.0 (1434.0) -> 1372.0 (1434.0) MB, 678.8 / 0.0 ms [allocation failure] [GC in old space requested].
  105111 ms: Mark-sweep 1372.0 (1434.0) -> 1373.0 (1404.0) MB, 677.6 / 0.0 ms [last resort gc].
  105784 ms: Mark-sweep 1373.0 (1404.0) -> 1374.0 (1404.0) MB, 673.1 / 0.0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x9f9db0cf781 <JS Object>
    1: Dm [/app/main.js:~626] [pc=0x34f3123b23b6] (this=0x6c6287c409 <JS Global Object>,a=0x24fd68bcc6b9 <a sl with map 0x9ecc840fbf9>,b=59)
    2: Em [/app/main.js:~627] [pc=0x34f3123cb54f] (this=0x6c6287c409 <JS Global Object>,a=0x24fd68bcc6b9 <a sl with map 0x9ecc840fbf9>,b=59)
    3: /* anonymous */ [/app/main.js:325] [pc=0x34f31258f74e] (this=0x6c6287c409 <JS Global Object>)
    4: Qf [/app...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [node]
 2: 0x7d007c [node]
 3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [node]
 5: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [node]
 6: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [node]
 7: 0x34f3120079a7
/app/asciicast2gif: line 118:    16 Aborted                 (core dumped) node $NODE_OPTS "${asciicast2gif_dir}/main.js" "${1}" "${2}" "${tmp_dir}" $theme $speed $scale

"no space left on device" when running in Docker

Following the Docker example in the readme I get this "no space left" error, when my disk has > 200GB remaining:

[ ~/Downloads ] docker run --rm -v $PWD:/data asciinema/asciicast2gif -t solarized-dark 134369.json demo.gif
==> Loading 134369.json...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining screenshots into GIF file...

convert: unable to write pixel cache `/tmp/magick-26AFqOawtyXtYw': No space left on device @ error/cache.c/WritePixelCachePixels/5492.
==> Done.

The asciicast itself is 35 seconds long. Here is the content of my JSON file, for reference.

Check if runtime deps are installed

a2gif shell script should first check whether node, phantomjs, convert and gifsicle are in $PATH and exit with error if that's not the case.

Can't handle Emoji - squares or empty strings are printed

Hi there

First of all, this is AMAZING! Thank you! I have lots of asciinema and I really wanted to get the animations for Github pages!!!

Problem with emojis

So, I have some terminal CLIs with Emojis and they don't get rendered...

Asciinema

screen shot 2018-11-09 at 3 59 27 am

Gif version

screen shot 2018-11-09 at 3 59 51 am

Syntax Error?

I have a test gif I am trying to convert to a gif and keep getting this syntax error:

[]$ > ./asciicast2gif https://asciinema.org/a/0KXjcaOGZjHdR9b9Q7pJAFQ7P ~/Desktop/test.gif

==> Loading https://asciinema.org/a/0KXjcaOGZjHdR9b9Q7pJAFQ7P...
/Users/DJM/Misc/asciicast2gif/main.js:568
return new Km(a,wf)}function Mm(a){try{var b=a[0];return b.h?b.h(a):b.call(null,a)}catch(e){if(e instanceof Object)throw b=e,a[6].Qc(),b;throw e;}}function Nm(a,b,e){e=Gm(e,Lm(function(e){a[2]=e;a[1]=b;return Mm(a)}));return k(e)?(a[2]=pc(e),a[1]=b,ck):null}function Om(a,b,e){b=b.ld(0,e,Lm(function(b){a[2]=b;a[1]=3;return Mm(a)}));return k(b)?(a[2]=pc(b),a[1]=3,ck):null}function Pm(a,b){var e=a[6];null!=b&&e.ld(0,b,Lm(function(){return function(){return null}}(e)));e.Qc();return e}
                                                                                                                   ^

SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at Ts (/Users/DJM/Misc/asciicast2gif/main.js:1026:410)
    at Function.g [as h] (/Users/DJM/Misc/asciicast2gif/main.js:288:239)
    at /Users/DJM/Misc/asciicast2gif/main.js:572:157
    at Function.e [as c] (/Users/DJM/Misc/asciicast2gif/main.js:310:90)

Any idea what is causing this?

Corrupt / Degraded gif Output

Hi,

I recently started using asciicast2gif and have successfully used it a number of times. I use the Docker image

However, while processing a somewhat long demo, the results were less than optimal and the screen output looks wrong

Here is the command:

docker run --rm -v $PWD:/data asciinema/asciicast2gif demo.cast.1 demo.cast.1.gif                                     ==> Loading demo.cast.1...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining 607 screenshots into GIF file...
gifsicle: warning: huge GIF, conserving memory (processing may take a while)
==> Done.

What it looks like via asciinema - asciinema_play.png
asciinema_play

What the generated gif looks like - asciicast2gif.jpg
asciicast2gif

I haven't run into this problem in shorter casts. Any ideas? Thanks.

PhantomJS has been archived

ariya/phantomjs#15344

Perhaps one of these could be used instead:
https://github.com/GoogleChrome/puppeteer
https://github.com/joelgriffith/browserless

When I try to install asciicast2gif locally (though a convoluted way to build a system package), the following occurs:

~ > asciicast2gif https://asciinema.org/a/118274.json demo.gif                                                                                                                                                                 (workstation|โœ”)
==> Loading https://asciinema.org/a/118274.json...
==> Spawning PhantomJS renderer...
/usr/lib/node_modules/asciicast2gif/main.js:696
return new Zo(a,Qe)}function ap(a){try{var b=a[0];return b.h?b.h(a):b.call(null,a)}catch(c){if(c instanceof Object)throw b=c,Uo(a[6]),b;throw c;}}function bp(a,b,c){c=Vo(c,$o(function(c){a[2]=c;a[1]=b;return ap(a)}));return r(c)?(a[2]=Ob(c),a[1]=b,bj):null}function cp(a,b){a=a[6];null!=b&&a.Dc(null,b,$o(function(){return function(){return null}}(a)));Uo(a);return a}                                                                                                             
                                                                                                                   ^

TypeError [ERR_INVALID_ARG_TYPE]: The "file" argument must be of type string. Received type object
    at normalizeSpawnArguments (child_process.js:397:11)
    at spawn (child_process.js:522:38)
    at Function.exports.exec (/usr/lib/node_modules/asciicast2gif/node_modules/phantomjs-prebuilt/lib/phantomjs.js:72:10)                                                                                                                     
    at Le (/usr/lib/node_modules/asciicast2gif/main.js:262:219)
    at Ke (/usr/lib/node_modules/asciicast2gif/main.js:261:410)
    at Je (/usr/lib/node_modules/asciicast2gif/main.js:261:320)
    at Ie (/usr/lib/node_modules/asciicast2gif/main.js:261:238)
    at Me (/usr/lib/node_modules/asciicast2gif/main.js:266:230)
    at tp (/usr/lib/node_modules/asciicast2gif/main.js:704:224)
    at /usr/lib/node_modules/asciicast2gif/main.js:710:373

When I tried building PhantomJS locally, the build failed.

It does work fine via Docker.

file could not be opened error

I built from source, and tried running from both a remote asciinema url as well as a downloaded json file. The script fully completes with no errors, but when the gif is generated, I can't open it.

[09:12AM] asciicast2gif (master)$ asciicast2gif ~/Desktop/147415.json ~/Desktop/demo.gif
==> Loading /Users/jeremywoertink/Desktop/147415.json...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining screenshots into GIF file...
==> Done.

screen shot 2017-11-14 at 9 24 47 am

npm 4.6.1
lein Leiningen 2.8.1 on Java 1.8.0_144 Java HotSpot(TM) 64-Bit Server VM
macOS 10.13.1

Dark box artifact around text

Regardless of what gifsicle settings I put (even --lossy=0), I get a darker box around updated text that I don't see in any of the demo GIFs on the README.

[thank you]

Just wanted to say this is awesome and brilliant!! I'm so glad to have found it! <3

It doesn't work

On Ubuntu 18.04 LTS with all previously installed additional packages I still can't get the result I expect.
Here is the output I have every time (in attachment)
screenshot from 2018-10-16 14-23-48

gifsicle:<stdin>: empty file

Conversion has failed. Deployed asciicast2gif from docker:

# docker run --rm -v $PWD:/data asciinema/asciicast2gif -t solarized-dark ibbdis.json ibbdis.gif
==> Loading ibbdis.json...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining screenshots into GIF file...
gifsicle:<stdin>: empty file
Killed
/app/main.js:2284
cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped=function(a){try{return cljs.core.async.impl.ioc_helpers.run_state_machine(a)}catch(b){throw b instanceof Object&&cljs.core.async.impl.ioc_helpers.aget_object(a,cljs.core.async.impl.ioc_helpers.USER_START_IDX).cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1(null),b;}};
                                                                                                                                                 ^

Error: Command failed: convert -loop 0 -delay 10 /tmp/tmp.p4NraOi9Sf/0.png -delay 60 /tmp/tmp.p4NraOi9Sf/1.png -delay 6 /tmp/tmp.p4NraOi9Sf/2.png -delay 13 /tmp/tmp.p4NraOi9Sf/3.png -delay 26 /tmp/tmp.p4NraOi9Sf/4.png -delay 9 /tmp/tmp.p4NraOi9Sf/5.png -delay 10 /tmp/tmp.p4NraOi9Sf/6.png -delay 6 /tmp/tmp.p4NraOi9Sf/7.png -delay 59 /tmp/tmp.p4NraOi9Sf/8.png -delay 76 /tmp/tmp.p4NraOi9Sf/9.png -delay 13 /tmp/tmp.p4NraOi9Sf/10.png -delay 10 /tmp/tmp.p4NraOi9Sf/11.png -delay 13 /tmp/tmp.p4NraOi9Sf/12.png -delay 6 /tmp/tmp.p4NraOi9Sf/13.png -delay 23 /tmp/tmp.p4NraOi9Sf/14.png -delay 19 /tmp/tmp.p4NraOi9Sf/15.png -delay 16 /tmp/tmp.p4NraOi9Sf/16.png -delay 6 /tmp/tmp.p4NraOi9Sf/17.png -delay 73 /tmp/tmp.p4NraOi9Sf/18.png -delay 33 /tmp/tmp.p4NraOi9Sf/19.png -delay 9 /tmp/tmp.p4NraOi9Sf/20.png -delay 23 /tmp/tmp.p4NraOi9Sf/21.png -delay 16 /tmp/tmp.p4NraOi9Sf/22.png -delay 13 /tmp/tmp.p4NraOi9Sf/23.png -delay 23 /tmp/tmp.p4NraOi9Sf/24.png -delay 26 /tmp/tmp.p4NraOi9Sf/25.png -delay 6 /tmp/tmp.p4NraOi9Sf/26.png -delay 6 /tmp/tmp.p4NraOi9Sf/27.png -delay 16 /tmp/tmp.p4NraOi9Sf/28.png -delay 16 /tmp/tmp.p4NraOi9Sf/29.png -delay 33 /tmp/tmp.p4NraOi9Sf/30.png -delay 30 /tmp/tmp.p4NraOi9Sf/31.png -delay 19 /tmp/tmp.p4NraOi9Sf/32.png -delay 50 /tmp/tmp.p4NraOi9Sf/33.png -delay 46 /tmp/tmp.p4NraOi9Sf/34.png -delay 50 /tmp/tmp.p4NraOi9Sf/35.png -delay 46 /tmp/tmp.p4NraOi9Sf/36.png -delay 66 /tmp/tmp.p4NraOi9Sf/37.png -delay 53 /tmp/tmp.p4NraOi9Sf/38.png -delay 53 /tmp/tmp.p4NraOi9Sf/39.png -delay 59 /tmp/tmp.p4NraOi9Sf/40.png -delay 50 /tmp/tmp.p4NraOi9Sf/41.png -delay 36 /tmp/tmp.p4NraOi9Sf/42.png -delay 19 /tmp/tmp.p4NraOi9Sf/43.png -delay 53 /tmp/tmp.p4NraOi9Sf/44.png -delay 40 /tmp/tmp.p4NraOi9Sf/45.png -delay 16 /tmp/tmp.p4NraOi9Sf/46.png -delay 19 /tmp/tmp.p4NraOi9Sf/47.png -delay 36 /tmp/tmp.p4NraOi9Sf/48.png -delay 33 /tmp/tmp.p4NraOi9Sf/49.png -delay 46 /tmp/tmp.p4NraOi9Sf/50.png -delay 13 /tmp/tmp.p4NraOi9Sf/51.png -delay 13 /tmp/tmp.p4NraOi9Sf/52.png -delay 53 /tmp/tmp.p4NraOi9Sf/53.png -delay 6 /tmp/tmp.p4NraOi9Sf/54.png -delay 80 /tmp/tmp.p4NraOi9Sf/55.png -delay 150 /tmp/tmp.p4NraOi9Sf/56.png -delay 193 /tmp/tmp.p4NraOi9Sf/57.png -delay 106 /tmp/tmp.p4NraOi9Sf/58.png -delay 43 /tmp/tmp.p4NraOi9Sf/59.png -delay 319 /tmp/tmp.p4NraOi9Sf/60.png -delay 3 /tmp/tmp.p4NraOi9Sf/61.png -delay 3 /tmp/tmp.p4NraOi9Sf/62.png -delay 96 /tmp/tmp.p4NraOi9Sf/63.png -delay 193 /tmp/tmp.p4NraOi9Sf/64.png -delay 276 /tmp/tmp.p4NraOi9Sf/65.png -delay 86 /tmp/tmp.p4NraOi9Sf/66.png -delay 66 /tmp/tmp.p4NraOi9Sf/67.png -delay 63 /tmp/tmp.p4NraOi9Sf/68.png -delay 63 /tmp/tmp.p4NraOi9Sf/69.png -delay 60 /tmp/tmp.p4NraOi9Sf/70.png -delay 76 /tmp/tmp.p4NraOi9Sf/71.png -delay 60 /tmp/tmp.p4NraOi9Sf/72.png -delay 66 /tmp/tmp.p4NraOi9Sf/73.png -delay 60 /tmp/tmp.p4NraOi9Sf/74.png -delay 60 /tmp/tmp.p4NraOi9Sf/75.png -delay 3 /tmp/tmp.p4NraOi9Sf/76.png -delay 126 /tmp/tmp.p4NraOi9Sf/77.png -delay 110 /tmp/tmp.p4NraOi9Sf/78.png -delay 200 /tmp/tmp.p4NraOi9Sf/79.png -delay 146 /tmp/tmp.p4NraOi9Sf/80.png -delay 193 /tmp/tmp.p4NraOi9Sf/81.png -delay 1556 /tmp/tmp.p4NraOi9Sf/82.png -delay 63 /tmp/tmp.p4NraOi9Sf/83.png -delay 123 /tmp/tmp.p4NraOi9Sf/84.png -delay 3 /tmp/tmp.p4NraOi9Sf/85.png -delay 93 /tmp/tmp.p4NraOi9Sf/86.png -delay 96 /tmp/tmp.p4NraOi9Sf/87.png -delay 93 /tmp/tmp.p4NraOi9Sf/88.png -delay 133 /tmp/tmp.p4NraOi9Sf/89.png -delay 5030 /tmp/tmp.p4NraOi9Sf/90.png -delay 3 /tmp/tmp.p4NraOi9Sf/91.png -delay 223 /tmp/tmp.p4NraOi9Sf/92.png -delay 293 /tmp/tmp.p4NraOi9Sf/93.png -delay 223 /tmp/tmp.p4NraOi9Sf/94.png -delay 3 /tmp/tmp.p4NraOi9Sf/95.png -delay 3 /tmp/tmp.p4NraOi9Sf/96.png -delay 3 /tmp/tmp.p4NraOi9Sf/97.png -delay 140 /tmp/tmp.p4NraOi9Sf/98.png -delay 156 /tmp/tmp.p4NraOi9Sf/99.png -delay 836 /tmp/tmp.p4NraOi9Sf/100.png -delay 216 /tmp/tmp.p4NraOi9Sf/101.png -delay 3 /tmp/tmp.p4NraOi9Sf/102.png -delay 3 /tmp/tmp.p4NraOi9Sf/103.png -delay 230 /tmp/tmp.p4NraOi9Sf/104.png -delay 213 /tmp/tmp.p4NraOi9Sf/105.png -delay 106 /tmp/tmp.p4NraOi9Sf/106.png -delay 96 /tmp/tmp.p4NraOi9Sf/107.png -delay 73 /tmp/tmp.p4NraOi9Sf/108.png -delay 4796 /tmp/tmp.p4NraOi9Sf/109.png -delay 233 /tmp/tmp.p4NraOi9Sf/110.png -delay 436 /tmp/tmp.p4NraOi9Sf/111.png -delay 26526 /tmp/tmp.p4NraOi9Sf/112.png -delay 69 /tmp/tmp.p4NraOi9Sf/113.png -delay 60 /tmp/tmp.p4NraOi9Sf/114.png -delay 63 /tmp/tmp.p4NraOi9Sf/115.png -delay 66 /tmp/tmp.p4NraOi9Sf/116.png -delay 63 /tmp/tmp.p4NraOi9Sf/117.png -delay 3 /tmp/tmp.p4NraOi9Sf/118.png -delay 133 /tmp/tmp.p4NraOi9Sf/119.png -delay 96 /tmp/tmp.p4NraOi9Sf/120.png -delay 73 /tmp/tmp.p4NraOi9Sf/121.png -delay 73 /tmp/tmp.p4NraOi9Sf/122.png -delay 216 /tmp/tmp.p4NraOi9Sf/123.png -delay 63 /tmp/tmp.p4NraOi9Sf/124.png -delay 126 /tmp/tmp.p4NraOi9Sf/125.png -delay 3 /tmp/tmp.p4NraOi9Sf/126.png -delay 3 /tmp/tmp.p4NraOi9Sf/127.png -delay 3 /tmp/tmp.p4NraOi9Sf/128.png -delay 3 /tmp/tmp.p4NraOi9Sf/129.png -delay 3 /tmp/tmp.p4NraOi9Sf/130.png -delay 3 /tmp/tmp.p4NraOi9Sf/131.png -delay 233 /tmp/tmp.p4NraOi9Sf/132.png -delay 230 /tmp/tmp.p4NraOi9Sf/133.png -delay 3 /tmp/tmp.p4NraOi9Sf/134.png -delay 3 /tmp/tmp.p4NraOi9Sf/135.png -delay 3 /tmp/tmp.p4NraOi9Sf/136.png -delay 3 /tmp/tmp.p4NraOi9Sf/137.png -delay 69 /tmp/tmp.p4NraOi9Sf/138.png -delay 3 /tmp/tmp.p4NraOi9Sf/139.png -delay 63 /tmp/tmp.p4NraOi9Sf/140.png -delay 200 /tmp/tmp.p4NraOi9Sf/141.png -delay 3 /tmp/tmp.p4NraOi9Sf/142.png -delay 3 /tmp/tmp.p4NraOi9Sf/143.png -delay 73 /tmp/tmp.p4NraOi9Sf/144.png -delay 216 /tmp/tmp.p4NraOi9Sf/145.png -delay 73 /tmp/tmp.p4NraOi9Sf/146.png -delay 156 /tmp/tmp.p4NraOi9Sf/147.png -delay 3046 /tmp/tmp.p4NraOi9Sf/148.png -delay 3 /tmp/tmp.p4NraOi9Sf/149.png -delay 123 /tmp/tmp.p4NraOi9Sf/150.png -delay 76 /tmp/tmp.p4NraOi9Sf/151.png -delay 73 /tmp/tmp.p4NraOi9Sf/152.png -delay 246 /tmp/tmp.p4NraOi9Sf/153.png -delay 800 /tmp/tmp.p4NraOi9Sf/154.png -delay 79 /tmp/tmp.p4NraOi9Sf/155.png -delay 80 /tmp/tmp.p4NraOi9Sf/156.png -delay 3 /tmp/tmp.p4NraOi9Sf/157.png -delay 100 /tmp/tmp.p4NraOi9Sf/158.png -layers Optimize gif:- | gifsicle -k 32 -O2 -Okeep-empty -o ibbdis.gif -
gifsicle:<stdin>: empty file
Killed

    at checkExecSyncError (child_process.js:481:13)
    at Object.execSync (child_process.js:521:13)
    at Object.asciinema.gif.main.shell (/app/main.js:5245:143)
    at Object.asciinema.gif.main.gen_gif (/app/main.js:5252:371)
    at /app/main.js:5261:136
    at d (/app/main.js:5255:185)
    at b (/app/main.js:5256:17)
    at Object.cljs.core.async.impl.ioc_helpers.run_state_machine (/app/main.js:2283:287)
    at Object.cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped (/app/main.js:2284:116)
    at /app/main.js:2285:321
#

Clamp frame-rate at 30 fps

While this tool doesn't use constant frame-rate (delay for each frame is specified individually), it's worth investigating if skipping over frames with very small delay can decrease file size without degrading animation smoothness in noticeable way.

We can experiment with 30 fps clamp. asciinema-player has asciinema.player.frames/at-hz function which quantizes frame times so they sit on multiples of 1/30s, and can be used on frames before passing them to renderer (gen-image-frames).

How to change font of asciicast2gif

Hi all around! I love asciinema and this script is just great!

I created an asciinema recording in my terminal. the terminal uses the font Meslo for powerline. Recording works nicely, playing it works nicely. The gif can be created using this tool, but unfortunately with the gif, a non-monospaced font is used instead of Meslo (Looks like default sans serif). As you can image this looks quite messy in a terminal.

I did not understand which part of the process picks the font when creating the gif-image. Where do I have to change the font to a monospaced one?

Cheers,
Sandra

taking a long time...

I run this command:

i run this in alias :

asciicast2gif='docker run --rm -v $PWD:/data asciinema/asciicast2gif'
then i ran the following command:

asciicast2gif demosprint.cast demosprint.gif

==> Loading demosprint.cast...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining 1131 screenshots into GIF file...

And now is seem to be stuck there forever. A long normaly should this take ?

thx

Unicode not rendered

I have a demo where a tree is rendered with unicode, the tree is not visible in the generated gif.

Support server URLs without appended file extension

Hi, I'm trying to run asciicast2gif against a recording I just posted online, but I'm getting the following output:

==> Loading https://asciinema.org/a/AsPWpL1qCvInbNAAVBfbDfRhy...
only asciicast v1 and v2 formats can be opened
==> Done.

Running locally it doesn't work, as well:

==> Loading /tmp/tmpi1soul1l-ascii.cast...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Couldn't get geometry of requested DOM element
/usr/local/lib/node/lib/node_modules/asciicast2gif/main.js:696
[ ... ]

Any pointers? Thanks!

Converted GIF color mismatch

I generated a GIF using the command docker run --rm -v $PWD:/data asciinema/asciicast2gif -s 2 -t solarized-dark recording.json recording.gif

The GIF does not match the colours recorded from asciinema rec. The original can be found here.

Is this due to an 8 bit colour limitation? Either way, my shell prompt has green in it, whereas the SUCCESS messages are grey.

Fails to build ClojureScript code

When running lein cljsbuild once main I get the following error. Using the Docker image is failing too because of #21 ๐Ÿ˜ข

Compiling ClojureScript...
Compiling "main.js" from ["src"]...
Compiling "main.js" failed.
clojure.lang.ExceptionInfo: failed compiling file:/home/raskolnikov/soft/asciicast2gif/src/asciinema/gif/main.cljs {:file #object[java.io.File 0x3d41449a "/home/raskolnikov/soft/asciicast2gif/src/asciinema/gif/main.cljs"]}
	at clojure.core$ex_info.invokeStatic(core.clj:4617)
	at clojure.core$ex_info.invoke(core.clj:4617)
	at cljs.compiler$compile_file$fn__3884.invoke(compiler.cljc:1471)
	at cljs.compiler$compile_file.invokeStatic(compiler.cljc:1436)
	at cljs.compiler$compile_file.invoke(compiler.cljc:1412)
	at cljs.closure$compile_file.invokeStatic(closure.clj:497)
	at cljs.closure$compile_file.invoke(closure.clj:488)
	at cljs.closure$eval5698$fn__5699.invoke(closure.clj:566)
	at cljs.closure$eval5634$fn__5635$G__5623__5642.invoke(closure.clj:450)
	at cljs.closure$compile_sources$iter__5834__5838$fn__5839.invoke(closure.clj:914)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.Cons.next(Cons.java:39)
	at clojure.lang.RT.next(RT.java:688)
	at clojure.core$next__4341.invokeStatic(core.clj:64)
	at clojure.core$dorun.invokeStatic(core.clj:3033)
	at clojure.core$doall.invokeStatic(core.clj:3039)
	at clojure.core$doall.invoke(core.clj:3039)
	at cljs.closure$compile_sources.invokeStatic(closure.clj:908)
	at cljs.closure$compile_sources.invoke(closure.clj:897)
	at cljs.closure$build.invokeStatic(closure.clj:2307)
	at cljs.closure$build.invoke(closure.clj:2236)
	at cljs.build.api$build.invokeStatic(api.clj:202)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljs.build.api$build.invokeStatic(api.clj:192)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljsbuild.compiler$compile_cljs$fn__6943.invoke(compiler.clj:66)
	at cljsbuild.compiler$compile_cljs.invokeStatic(compiler.clj:65)
	at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:54)
	at cljsbuild.compiler$run_compiler.invokeStatic(compiler.clj:165)
	at cljsbuild.compiler$run_compiler.invoke(compiler.clj:126)
	at user$eval7047$iter__7083__7087$fn__7088$fn__7106.invoke(form-init545893261685407571.clj:1)
	at user$eval7047$iter__7083__7087$fn__7088.invoke(form-init545893261685407571.clj:1)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.RT.seq(RT.java:521)
	at clojure.core$seq__4357.invokeStatic(core.clj:137)
	at clojure.core$dorun.invokeStatic(core.clj:3024)
	at clojure.core$doall.invokeStatic(core.clj:3039)
	at clojure.core$doall.invoke(core.clj:3039)
	at user$eval7047.invokeStatic(form-init545893261685407571.clj:1)
	at user$eval7047.invoke(form-init545893261685407571.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:6927)
	at clojure.lang.Compiler.eval(Compiler.java:6917)
	at clojure.lang.Compiler.load(Compiler.java:7379)
	at clojure.lang.Compiler.loadFile(Compiler.java:7317)
	at clojure.main$load_script.invokeStatic(main.clj:275)
	at clojure.main$init_opt.invokeStatic(main.clj:277)
	at clojure.main$init_opt.invoke(main.clj:277)
	at clojure.main$initialize.invokeStatic(main.clj:308)
	at clojure.main$null_opt.invokeStatic(main.clj:342)
	at clojure.main$null_opt.invoke(main.clj:339)
	at clojure.main$main.invokeStatic(main.clj:421)
	at clojure.main$main.doInvoke(main.clj:384)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
Caused by: clojure.lang.ExceptionInfo: No such namespace: asciinema.player.source, could not locate asciinema/player/source.cljs, asciinema/player/source.cljc, or Closure namespace "asciinema.player.source" in file /home/raskolnikov/soft/asciicast2gif/src/asciinema/gif/main.cljs {:tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4617)
	at clojure.core$ex_info.invoke(core.clj:4617)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:657)
	at cljs.analyzer$error.invoke(analyzer.cljc:653)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:655)
	at cljs.analyzer$error.invoke(analyzer.cljc:653)
	at cljs.analyzer$analyze_deps.invokeStatic(analyzer.cljc:1975)
	at cljs.analyzer$analyze_deps.invoke(analyzer.cljc:1951)
	at cljs.analyzer$ns_side_effects.invokeStatic(analyzer.cljc:3238)
	at cljs.analyzer$ns_side_effects.invoke(analyzer.cljc:3233)
	at cljs.analyzer$analyze_STAR_$fn__2767.invoke(analyzer.cljc:3328)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6544)
	at clojure.core$reduce.invoke(core.clj:6527)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3328)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:3318)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3352)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:3335)
	at cljs.compiler$emit_source.invokeStatic(compiler.cljc:1307)
	at cljs.compiler$emit_source.invoke(compiler.cljc:1287)
	at cljs.compiler$compile_file_STAR_$fn__3861.invoke(compiler.cljc:1381)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1206)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1195)
	at cljs.compiler$compile_file_STAR_.invokeStatic(compiler.cljc:1370)
	at cljs.compiler$compile_file_STAR_.invoke(compiler.cljc:1363)
	at cljs.compiler$compile_file$fn__3884.invoke(compiler.cljc:1459)
	... 56 more
Subprocess failed

Conversion fails with `gifsicle:<stdin>: empty file`

Running

$ docker run --memory $(( 1024 * 1024 * 1024 )) --volume /var/tmp/demo:/data --cpus 1 asciinema/asciicast2gif demo.json demo.gif
==> Loading demo.json...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining screenshots into GIF file...
gifsicle:<stdin>: empty file
Killed
/app/main.js:697
return new yp(a,Oe)}function Ap(a){try{var b=a[0];return b.h?b.h(a):b.call(null,a)}catch(c){if(c instanceof Object)throw b=c,tp(a[6]),b;throw c;}}function Bp(a,b,c){c=up(c,zp(function(c){a[2]=c;a[1]=b;return Ap(a)}));return t(c)?(a[2]=Gb(c),a[1]=b,ej):null}function Cp(a,b){var c=a[6];null!=b&&c.Jc(0,b,zp(function(){return function(){return null}}(c)));tp(c);return c}

Error: Command failed: convert -loop 0 -delay 3 /tmp/tmp.RFGokXCDrf/0.png -delay 196 /tmp/tmp.RFGokXCDrf/1.png [...] -delay 100 /tmp/tmp.RFGokXCDrf/2218.png -layers Optimize gif:- | gifsicle -k 32 -O2 -Okeep-empty -o demo.gif -
gifsicle:<stdin>: empty file
Killed

    at checkExecSyncError (child_process.js:472:13)
    at Object.execSync (child_process.js:512:13)
    at /app/main.js:711:275
    at Function.b (/app/main.js:707:233)
    at Ap (/app/main.js:697:64)
    at /app/main.js:697:209
    at /app/main.js:691:10
    at Immediate.kp (/app/main.js:687:320)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)

The same works with a shorter recording.

some characters are not visible

I tried converting a recording to a GIF.

docker run --rm -v $PWD:/data asciinema/asciicast2gif https://asciinema.org/a/193932.json 193932.gif

The original on the website looks fine:
asciicast

But as you can see, the GIF is not:
193932

In a possibly related issue, the thumbnail on the website is fine, but not in the embed.

number of columns is not respected

it seem that asciicast2gif does not respect the custom number of columns required and fallbacks to 80 or similar value when tmux was involved.

I mention that the the same recording behavers normal when played using asciinema, this behaviour being seen only when converting to gif. Use of -c param seems to have no effect.

Both files can be found at https://github.com/pycontribs/rmux/tree/master/docs

The command used to build the gif was asciicast2gif -S 2 -w 160 movie.cast movie.gif and while the total number of columns of the gif is 160 you can see around the half of the animation that when tmux split window starts it is cropped to ~100 columns.

If you try to play the same recording, it will display correctly.

Docker command asciicast2gif not work

I use docker image run this command,output:

ra@17zy:~/Downloads/video$ sudo asciicast2gif https://asciinema.org/a/118274.json demo.gif
==> Loading https://asciinema.org/a/118274.json...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Couldn't get geometry of requested DOM element
/usr/local/lib/node_modules/asciicast2gif/main.js:696
return new Zo(a,Qe)}function ap(a){try{var b=a[0];return b.h?b.h(a):b.call(null,a)}catch(c){if(c instanceof Object)throw b=c,Uo(a[6]),b;throw c;}}function bp(a,b,c){c=Vo(c,$o(function(c){a[2]=c;a[1]=b;return ap(a)}));return r(c)?(a[2]=Ob(c),a[1]=b,bj):null}function cp(a,b){a=a[6];null!=b&&a.Dc(null,b,$o(function(){return function(){return null}}(a)));Uo(a);return a}
                                                                                                                   ^

Error: program exited with code 1
    at ChildProcess.<anonymous> (/usr/local/lib/node_modules/asciicast2gif/main.js:704:399)
    at emitTwo (events.js:126:13)
    at ChildProcess.emit (events.js:214:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)

node: v8.10.0
npm: 3.5.2
system: Linux 17zy 4.15.0-29-generic #31-Ubuntu x86_64 x86_64 GNU/Linux
docker: Docker version 17.06.2-ce, build a04f55b
docker-image: asciinema/asciicast2gif latest 54698cc15d97

Running via Docker image fails: Unexpected token in JSON at positon 0

I downloaded the file and found a regular curly brace at position 0.

[ ~ ] docker run --rm -v $PWD:/data asciinema/asciicast2gif https://asciinema.org/a/bqBwff05mI7Cl9bz7EqLPMKF8.json demo.gif                                                                                                                                   [ master ]
==> Loading https://asciinema.org/a/bqBwff05mI7Cl9bz7EqLPMKF8.json...
/app/main.js:2284
cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped=function(a){try{return cljs.core.async.impl.ioc_helpers.run_state_machine(a)}catch(b){throw b instanceof Object&&cljs.core.async.impl.ioc_helpers.aget_object(a,cljs.core.async.impl.ioc_helpers.USER_START_IDX).cljs$core$async$impl$protocols$Channel$close_BANG_$arity$1(null),b;}};
                                                                                                                                                 ^

SyntaxError: Unexpected token  in JSON at position 0
    at parse (native)
    at asciinema.gif.main.parse_json (/app/main.js:5235:406)
    at Function.e [as cljs$core$IFn$_invoke$arity$1] (/app/main.js:931:362)
    at /app/main.js:2620:464
    at Function.f [as cljs$core$IFn$_invoke$arity$2] (/app/main.js:1065:400)
    at Function.g [as cljs$core$IFn$_invoke$arity$2] (/app/main.js:2276:3)
    at cljs.core.async.impl.channels.ManyToManyChannel.cljs$core$async$impl$protocols$WritePort$put_BANG_$arity$3 (/app/main.js:2257:80)
    at Object.cljs.core.async.impl.protocols.put_BANG_ (/app/main.js:2171:146)
    at Function.cljs.core.async.put_BANG_.cljs$core$IFn$_invoke$arity$2 (/app/main.js:2359:176)
    at IncomingMessage.<anonymous> (/app/main.js:5238:483)

[ ~ ] docker -v
Docker version 17.06.1-ce, build 874a7374f3

How can I patch the client object to support self-signed SSL Cert protected urls

Inspecting main.cljs, I think that I need to provide an options object to the http client object.

(defn- http-get [url ch]
  (let [proto (-> url (str/split #":") first)
        gunzip (.createGunzip zlib)
        client (nodejs/require proto)]
    (.get client url (fn [res]
[...]

I should be able to generically attach the rejectUnauthorized parameter within an options object with a default value of true. I can't figure out the syntax to accomplish this.

Any hints on the best way to proceed?

Use gifsicle to assemble frames instead of ImageMagick?

Right now we assemble initial GIF file with ImageMagicks's convert and the pass it through gifsicle. convert is doing palette reduction and dithering separately for each frame. Assembling GIF directly in gifsicle may give use better quality (and maybe even smaller file size).

Unfortunately gifsicle can't directly read PNG files so we probably still need to use convert to convert PNG files into single-image GIF files before invoking gifsicle.

Corrupted gif

asciicast2gif is producing gifs that cannot be opened.

I tried with both the standalone version and the docker container.

Any clue how I can troubleshoot this?

Setting row limit causes recording to jump/glitch

I was able to produce a minimal working test case with this asciicast.

This test case simply redirects some garbage from /dev/random into a text file and outputs the octal dump via od (to avoid potentially introducing Unicode bugs). Afterwards, it prints some echo statements.

I then converted this to a gif with the command:

asciicast2gif -w 80 -h 25 https://asciinema.org/a/st5CY0WipJ1S85VkUNjK2HdXb.json cast.gif

The GIF that is then produced by asciicast2gif however, seems to break once the row-limit of 25 is exceeded, and bugs out. It fails to include the echo statements because it seems to get stuck and drop frames. This kind of bug was discovered when I was trying to make my own personal cast:

GIF

I am running this on Ubuntu 16.04, and the dependency of ImageMagick is satisfied. Of giflossy/gifsicle, I am using gifsicle, which I compiled from source from its GitHub repository.

My guess is that I'm doing something wrong, most likely something with my dependencies, but I'm not sure where to start looking.

Height overflow

I have bit longer cast (here), that I tried to convert, but I wanted to limit the height of resulting GIF so I used the -h parameter. Unfortunately the resulted GIF trims the part that overflow the limited window.

I would expect that the tool will imitate terminal window behaviour where when the prompt reaches bottom of the window, it will start "push out" the oldest entries up and from the window view box.

Is there some way to make this happen?

Make stdout output less noisy

The output from procecssing is too noisy now. We can leave some basic informational/progress messages.
Everything over that should be either removed or only displayed when DEBUG=1 env var is set.

`No such namespace: asciinema.player.asciicast`

Hey hey. Trying to build this project. Having an error from lein. On Debian/testing.

$ lein -v
Leiningen 2.8.1 on Java 1.8.0_144 Java HotSpot(TM) 64-Bit Server VM
$ pwd
/home/mfowlewebs/src/asciicast2gif
$ lein cljsbuild once main                             
Compiling ClojureScript...
Compiling ["main.js"] from ["src"]...
Compiling ["main.js"] failed.
clojure.lang.ExceptionInfo: failed compiling file:/home/rektide/projects/archive/asciicast2gif/src/asciinema/gif/main.cljs {:file #object[java.io.File 0x32ea16b7 "/home/rektide/projects/archive/asciicast2gif/src/asciinema/gif/main.cljs"]}
	at clojure.core$ex_info.invokeStatic(core.clj:4739)
	at clojure.core$ex_info.invoke(core.clj:4739)
	at cljs.compiler$compile_file$fn__3702.invoke(compiler.cljc:1562)
	at cljs.compiler$compile_file.invokeStatic(compiler.cljc:1522)
	at cljs.compiler$compile_file.invoke(compiler.cljc:1498)
	at cljs.closure$compile_file.invokeStatic(closure.clj:573)
	at cljs.closure$compile_file.invoke(closure.clj:564)
	at cljs.closure$fn__5124.invokeStatic(closure.clj:653)
	at cljs.closure$fn__5124.invoke(closure.clj:647)
	at cljs.closure$fn__5052$G__5045__5059.invoke(closure.clj:521)
	at cljs.closure$compile_sources$iter__5250__5254$fn__5255.invoke(closure.clj:1011)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.Cons.next(Cons.java:39)
	at clojure.lang.RT.next(RT.java:706)
	at clojure.core$next__5108.invokeStatic(core.clj:64)
	at clojure.core$dorun.invokeStatic(core.clj:3134)
	at clojure.core$doall.invokeStatic(core.clj:3140)
	at clojure.core$doall.invoke(core.clj:3140)
	at cljs.closure$compile_sources.invokeStatic(closure.clj:1007)
	at cljs.closure$compile_sources.invoke(closure.clj:996)
	at cljs.closure$build.invokeStatic(closure.clj:2817)
	at cljs.closure$build.invoke(closure.clj:2718)
	at cljs.build.api$build.invokeStatic(api.clj:208)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljs.build.api$build.invokeStatic(api.clj:195)
	at cljs.build.api$build.invoke(api.clj:189)
	at cljsbuild.compiler$compile_cljs$fn__718.invoke(compiler.clj:61)
	at cljsbuild.compiler$compile_cljs.invokeStatic(compiler.clj:60)
	at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:48)
	at cljsbuild.compiler$run_compiler.invokeStatic(compiler.clj:168)
	at cljsbuild.compiler$run_compiler.invoke(compiler.clj:129)
	at user$eval847$iter__895__899$fn__900$fn__926.invoke(form-init8977336585284452904.clj:1)
	at user$eval847$iter__895__899$fn__900.invoke(form-init8977336585284452904.clj:1)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.RT.seq(RT.java:528)
	at clojure.core$seq__5124.invokeStatic(core.clj:137)
	at clojure.core$dorun.invokeStatic(core.clj:3125)
	at clojure.core$doall.invokeStatic(core.clj:3140)
	at clojure.core$doall.invoke(core.clj:3140)
	at user$eval847.invokeStatic(form-init8977336585284452904.clj:1)
	at user$eval847.invoke(form-init8977336585284452904.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:7062)
	at clojure.lang.Compiler.eval(Compiler.java:7052)
	at clojure.lang.Compiler.load(Compiler.java:7514)
	at clojure.lang.Compiler.loadFile(Compiler.java:7452)
	at clojure.main$load_script.invokeStatic(main.clj:278)
	at clojure.main$init_opt.invokeStatic(main.clj:280)
	at clojure.main$init_opt.invoke(main.clj:280)
	at clojure.main$initialize.invokeStatic(main.clj:311)
	at clojure.main$null_opt.invokeStatic(main.clj:345)
	at clojure.main$null_opt.invoke(main.clj:342)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
Caused by: clojure.lang.ExceptionInfo: No such namespace: asciinema.player.asciicast, could not locate asciinema/player/asciicast.cljs, asciinema/player/asciicast.cljc, or JavaScript source providing "asciinema.player.asciicast" in file /home/rektide/projects/archive/asciicast2gif/src/asciinema/gif/main.cljs {:tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4739)
	at clojure.core$ex_info.invoke(core.clj:4739)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:697)
	at cljs.analyzer$error.invoke(analyzer.cljc:693)
	at cljs.analyzer$error.invokeStatic(analyzer.cljc:695)
	at cljs.analyzer$error.invoke(analyzer.cljc:693)
	at cljs.analyzer$analyze_deps.invokeStatic(analyzer.cljc:2129)
	at cljs.analyzer$analyze_deps.invoke(analyzer.cljc:2103)
	at cljs.analyzer$ns_side_effects.invokeStatic(analyzer.cljc:3476)
	at cljs.analyzer$ns_side_effects.invoke(analyzer.cljc:3471)
	at cljs.analyzer$analyze_STAR_$fn__2510.invoke(analyzer.cljc:3596)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at cljs.analyzer$analyze_STAR_.invokeStatic(analyzer.cljc:3596)
	at cljs.analyzer$analyze_STAR_.invoke(analyzer.cljc:3586)
	at cljs.analyzer$analyze.invokeStatic(analyzer.cljc:3616)
	at cljs.analyzer$analyze.invoke(analyzer.cljc:3598)
	at cljs.compiler$emit_source.invokeStatic(compiler.cljc:1386)
	at cljs.compiler$emit_source.invoke(compiler.cljc:1365)
	at cljs.compiler$compile_file_STAR_$fn__3672.invoke(compiler.cljc:1467)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1285)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1274)
	at cljs.compiler$compile_file_STAR_.invokeStatic(compiler.cljc:1451)
	at cljs.compiler$compile_file_STAR_.invoke(compiler.cljc:1444)
	at cljs.compiler$compile_file$fn__3702.invoke(compiler.cljc:1547)
	... 55 more
Subprocess failed

Does asciicast2gif ignore 'idle_time_limit'?

WARNING: I could be completely wrong here and my javascript is not good so I haven't checked.

The 'idle_time_limit' function of asciinema rec is not working when I use asciicast2gif from the resulting json file. I just went through and retimed my recording manually to work around the problem.

Couldn't get geometry of requested DOM element

asciicast2gif fails to generate .gif files

$ ./asciicast2gif asciicast.json image.gif

==> Loading asciicast-133781.json...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Couldn't get geometry of requested DOM element
/home/xtonousou/.scripts/others/asciicast2gif/main.js:568
return new Km(a,wf)}function Mm(a){try{var b=a[0];return b.h?b.h(a):b.call(null,a)}catch(e){if(e instanceof Object)throw b=e,a[6].Qc(),b;throw e;}}function Nm(a,b,e){e=Gm(e,Lm(function(e){a[2]=e;a[1]=b;return Mm(a)}));return k(e)?(a[2]=pc(e),a[1]=b,ck):null}function Om(a,b,e){b=b.ld(0,e,Lm(function(b){a[2]=b;a[1]=3;return Mm(a)}));return k(b)?(a[2]=pc(b),a[1]=3,ck):null}function Pm(a,b){var e=a[6];null!=b&&e.ld(0,b,Lm(function(){return function(){return null}}(e)));e.Qc();return e}
                                                                                                                   ^

Error: program exited with code 1
    at ChildProcess.<anonymous> (/home/xtonousou/.scripts/others/asciicast2gif/main.js:1028:100)
    at emitTwo (events.js:125:13)
    at ChildProcess.emit (events.js:213:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

The .json file is the one mentioned here

$ uname -a

Linux hyperi0n 4.12.6-1-ARCH #1 SMP PREEMPT Sat Aug 12 09:16:22 CEST 2017 x86_64 GNU/Linux

Use lowest compression when saving PNG to speed up process?

PhantomJS's page.render method support second argument, an options object where it's possible to specify quality:

page.render(imagePath, { quality: 100 });

For PNG quality means compression, and with 100 it generates PNG files the fastest, with least/no compression.

This may speed up PNG generation, as it doesn't compress, but at the same time it may slow it down, as bigger PNG files need to be saved to disk, and disk I/O is slow. Needs benchmarking.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.