icholy/ttygif

Recording drops last two frames

Closed this issue · 8 comments

The generated gif effectively drops the last two displayed frames. Looking at the command-line arguments given to convert(1), the last frame (present in the tmp directory full of xwd files) is not mentioned, and (assuming the gif is played in a loop) the second-to-last frame is shown for zero duration because there isn't a -delay after it.

(I plan to make a pull-request to fix this later today, since I came across it while trying to generate a gif and it's easier to fix than to work around.)

It also drops the first frame. If you generate a recording from a script like:

#!/bin/bash
echo First
sleep 1
echo Second

The first frame of the resulting gif will contain both lines.

Cause of skipping the first frame seems to be an off-by-one in handling options.skip_threshold, which defaults to 0, presumably to mean "don't skip anything" but actually meaning "skip the first frame". Despite being in the options structure, skip_threshold and skip_limit do not appear to have command-line arguments or environment variables to control them.

skip_threshold = 0 means skip frames with a delay <= 0.
skip_limit = 5, means don't skip more than 5 frames in a row.

What's your use case exactly? Is this causing issues in any real-world scenarios?

I'm trying to generate explanatory gifs about how terminals work, using a shell script with echo and sleep to define what's displayed.

I could use an example & steps to reproduce.

Here's a shell script which generates some output, and a ttyrec recording of it. There's bits at the start and end to clearly distinguish frames, and a bit in the middle which tests for off-by-ones in timing. (The bit in the middle is not buggy in the current ttyrec, but tests a bug that I accidentally introduced when trying to fix the start/end issues.)

test-ttygif.sh.txt
test-ttygif.ttyrec.txt

#!/bin/bash

CLEAR_LINE=$"\x1b[1K\x1b[99D"

echo -n 'This is the first frame'
sleep 3
echo -e '\nAfter 3 seconds, this second line appears\n'
sleep 1

echo "Now we'll test for glitches in steady-state timing. The line below will blink,"
echo "and should be fully visible 9/10ths of the time. It will blink 10 times total."

for i in {1..10}; do
        echo -e -n "${CLEAR_LINE}=============="
        sleep 0.9
        echo -e -n "${CLEAR_LINE}              "
        sleep 0.1
done

echo -e "\nFinished blinking."
sleep 1

echo -e "\n\nNow we'll test what happens at the end."
echo -n "This is the second-to-last frame. It should be here for 3 seconds."
sleep 3
echo -e "\nAnd this is the last frame. How long it's visible is not well-defined but it shouldn't be instantaneous."
sleep 3