Skip to content

Instantly share code, notes, and snippets.

@jkeuper
Forked from tristanwietsma/term2gif.sh
Last active March 3, 2024 02:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkeuper/7c445def41863d2104ecb67b9ef58110 to your computer and use it in GitHub Desktop.
Save jkeuper/7c445def41863d2104ecb67b9ef58110 to your computer and use it in GitHub Desktop.
Record terminal session to GIF
#!/bin/bash
MAX=200 # maximum wait between frames
DELAY=0.2 # speed things up a bit
TIMING=$1
SCRIPT=$2
W=$WINDOWID # Note: not alway present. Terminator not, xterm it is.
rm -rf /tmp/script-replay-gifs/
mkdir /tmp/script-replay-gifs/
t=$(mktemp)
cp $SCRIPT $t
#remove first line
sed -i '1d' $t
#clear screen
clear
#read timing file one by one
curr=0
i=0
while read line
do
#capture time and chars to read
cols=($line)
chars=${cols[1]}
#read from current char the number of chars to read
dd if=$t bs=1 skip=$curr count=$chars 2>/dev/null
#convert to gif frame with a nice frame-number
n=$(printf "%010d" $i)
import -window $WINDOWID /tmp/script-replay-gifs/$n.gif
#and move to next position
curr=$((curr+chars))
i=$((i+1))
done <$TIMING
rm -f $t
#now, set gif with delay per frame
i=1
while read line
do
cols=($line)
timing=${cols[0]}
#get next image
file=$(ls -1 /tmp/script-replay-gifs/ | head -n $i | tail -n 1)
timing=$(echo "$timing*100*$DELAY" | bc -l | awk '{print int($0)}')
timing=$(( $timing < $MAX ? $timing : $MAX ))
command=$command" -delay $timing /tmp/script-replay-gifs/$file"
i=$((i+1))
done < $TIMING
convert $command /tmp/anim-notoptim.gif
convert /tmp/anim-notoptim.gif -coalesce -layers Optimize /tmp/anim.gif
mv /tmp/anim.gif ./anim_$(date +%Y%m%dT%H%M%S).gif
rm -f /tmp/anim-notoptim.gif
rm -rf /tmp/script-replay-gifs/
@dhananjay1438
Copy link

How does it work? Can you elaborate?

@jkeuper
Copy link
Author

jkeuper commented Nov 28, 2019

How does it work? Can you elaborate?
The dd command reads the specific part of the logfile. (All parts are specified by the timing file, i.e. number of characters and duration.)

The import command makes a screenshot of the terminal.

The convert command processes all gif files and applies timings to each frame. And then the output gif is optimized.

That's it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment