asciinema / asciicast2gif

Generate GIF animations from asciicasts (asciinema recordings)
MIT License
1.2k stars 83 forks source link

Node crashes in docker container #53

Closed hlolli closed 2 years ago

hlolli commented 5 years ago

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
hlolli commented 5 years ago

I was able to escape the heap limit with -e NODE_OPTIONS='--max_old_space_size=4096' in the docker command, that led me step closer

docker run --rm -v $PWD:/data -e NODE_OPTIONS='--max_old_space_size=4096' asciinema/asciicast2gif -s 1.0 -t solarized-dark demo.cast demo.gif 
==> Loading demo.cast...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining 4338 screenshots into GIF file...
/app/main.js:697
Qe)}function ep(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,Yo(a[6]),b;throw c;}}function fp(a,b,c){c=Zo(c,dp(function(c){a[2]=c;a[1]=b;return ep(a)}));return r(c)?(a[2]=Nb(c),a[1]=b,dj):null}function gp(a,b){a=a[6];null!=b&&a.Dc(null,b,dp(function(){return function(){return null}}(a)));Yo(a);return a}
                                                                                                   ^

Error: spawnSync /bin/sh E2BIG
    at exports._errnoException (util.js:1020:11)
    at spawnSync (child_process.js:451:20)
    at Object.execSync (child_process.js:507:13)
    at Dp (/app/main.js:708:246)
    at /app/main.js:713:178
    at Function.b (/app/main.js:709:287)
    at ep (/app/main.js:697:48)
    at /app/main.js:697:193
    at /app/main.js:689:264
    at Immediate.Po (/app/main.js:685:331)
ku1ik commented 5 years ago

Is it possible that you link to example .cast file that helps to reproduce this?

hlolli commented 5 years ago

https://s3.amazonaws.com/hlolli/demo.cast

ku1ik commented 2 years ago

Wow, this asciicast file is 80 MB, I'd say it's on a heavy side :)

I don't think asciicast2gif will manage. There's just too many frames and the current implementation requires all of it to fit into memory (image concat done by imagemagick's convert).

However I just released asciicast2gif's successor - https://github.com/asciinema/agg . It's meant to handle any asciicast you throw at it very fast with minimal memory usage. You should try it out (asciicast2gif is no longer maintained).

I generated gif from your demo with agg, took 1 minute:

marcin@puter ~/tmp> agg -v --fps-cap=15 --speed=3 issue-53.{cast,gif}
[2022-08-14T14:33:10Z INFO  agg] terminal size: 174x38
[2022-08-14T14:33:10Z INFO  agg] selected font family: JetBrains Mono
[2022-08-14T14:33:10Z INFO  agg] selected theme: dracula
[2022-08-14T14:33:10Z INFO  agg] gif dimensions: 1478x764
1412 / 1412 [=========================================================] 100.00 % 23.61/s
[2022-08-14T14:34:09Z INFO  agg] rendering finished in 59.800545s

The generated gif file was huge - 212 MB. So I ran it through gifsicle:

marcin@puter ~/tmp> gifsicle --lossy=80 -k 64 -O3 -Okeep-empty issue-53.gif -o issue-53-opt.gif
gifsicle: warning: huge GIF, conserving memory (processing may take a while)

This one took 10 minutes or so (didn't count), and produced 117 MB gif.

Either way, this type of animation is an extreme case asciinema will never be a good fit for.