RecGif
Bomb Bloke 07 Oct 2015
pastebin get MgMmd2dC recgif
A ComputerCraft screen recorder. Saves your terminal output as an animated GIF.
Requires my GIF API and BBPack, though these should be downloaded automatically if they're missing.
Also requires a Minecraft font file, saved as "ascii.gif". It'll auto-download a low-res one if it's missing, via:
... but, if you don't mind longer encoding times, you can get a high-res one by manually running:
The script will use an alternate font if it detects CC 1.76 or later:
Which can again be replaced by a high-res version, if you wish:
Usage:
If the -i flag is used, then key/mouse_events will be logged at the bottom of the animation.
If -s is used, then the last frame will be skipped, excluding it from the animation. Handy for those cases where you want to avoid a big red "Terminated" message being captured when you hit Ctrl + T.
If -ld: is used, then it must be followed immediately by a number (no spaces). This sets the delay of the last frame in the animation in seconds. The default is two.
If no script is specified, simply starts another CraftOS shell and records that.
Edited by Bomb Bloke, 20 June 2017 - 10:42 AM.
A ComputerCraft screen recorder. Saves your terminal output as an animated GIF.
Requires my GIF API and BBPack, though these should be downloaded automatically if they're missing.
Also requires a Minecraft font file, saved as "ascii.gif". It'll auto-download a low-res one if it's missing, via:
bbpack get Y0eLUPtr
... but, if you don't mind longer encoding times, you can get a high-res one by manually running:
bbpack get QCwtu5sK
The script will use an alternate font if it detects CC 1.76 or later:
bbpack get CnLzL5fg
Which can again be replaced by a high-res version, if you wish:
bbpack get vtKWYMqa
Usage:
recgif [-i] [-s] [-ld:<num>] [scriptToRecord] [scriptArgs ...]
If the -i flag is used, then key/mouse_events will be logged at the bottom of the animation.
If -s is used, then the last frame will be skipped, excluding it from the animation. Handy for those cases where you want to avoid a big red "Terminated" message being captured when you hit Ctrl + T.
If -ld: is used, then it must be followed immediately by a number (no spaces). This sets the delay of the last frame in the animation in seconds. The default is two.
If no script is specified, simply starts another CraftOS shell and records that.
Examples
Version History
Edited by Bomb Bloke, 20 June 2017 - 10:42 AM.
Wojbie 07 Oct 2015
Nice stuff! This will be really useful in creating tutorials and stuff for cc without using recording software. I am so making some recordings with this! One question for you? Is there a reason you went with coorutine.yeld overwrite instead of going coorutine.create and restore like monitor program? I am guessing that messed with timing right?
Edited by wojbie, 07 October 2015 - 01:00 PM.
Edited by wojbie, 07 October 2015 - 01:00 PM.
Bomb Bloke 07 Oct 2015
Nah, just laziness on my part. Doing it properly (either by sandboxing or a custom coroutine manager) could potentially run slightly faster under uncommon scenarios (eg, people actually using multiple multishell tabs), but it'd make for more lengthy code.
Wojbie 07 Oct 2015
EDIT: Or not? I think I got confused for a moment. I need to test it again.
I had case of dumb-dumb there.
On other note I love how you separated recording and rendering of gif. And the way you piece frames of the gif together.
Edited by wojbie, 07 October 2015 - 07:38 PM.
SquidDev 07 Oct 2015
Wow! That is some nice code! Having a read through I guess it would be too difficult to show key presses - something like this (and even mouse clicks)? I guess your rendering system isn't really designed for it, though it would be a pretty awesome feature! Heh, using alpha-blending you could even have it as a semi-transparent overlay.
Wojbie 07 Oct 2015
I got 3 bugs reports:
- If using it to open program and pass arguments to that program they will not be passed due to:
local arg = {...} shell.run(#arg == 0 and "shell" or unpack(arg))
part. Because if you return more than one element into logic stuuf only first one is considered rest is discared. In this case only arg[1] is passed. Quick and dirty fix would be to change it to:
local arg = {...} shell.run(#arg == 0 and "shell" or arg[1],unpack(arg,2))
. - If attempting to record edit program. It errors on encoding in line 219: Attempt to get length of number.
When tested it don&#39;t seem to happen in other programs. - Looks like last frame is held on screen for about 5 sec. Is that on purpose?
- When waiting for [y/n] answer can you ignore all other than y/n? Accidentally wiped few recordings by typing filename there. I hate when i am idiot that detects places to idiot-prof code but yea.
Bomb Bloke 07 Oct 2015
SquidDev, on 07 October 2015 - 03:06 PM, said:
Wow! That is some nice code! Having a read through I guess it would be too difficult to show key presses - something like this (and even mouse clicks)? I guess your rendering system isn't really designed for it, though it would be a pretty awesome feature! Heh, using alpha-blending you could even have it as a semi-transparent overlay.
Not much in the way of alpha available in GIF, but in theory I could do something with the 8bit colour depth. Still, it'd be easier to just add an extra few rows of pixels to the bottom of the image and put the text there. I may take a stab at it.
wojbie, on 07 October 2015 - 07:42 PM, said:
If using it to open program and pass arguments to that program they will not be passed due to:
Thanks, fixed.
wojbie, on 07 October 2015 - 07:42 PM, said:
If attempting to record edit program. It errors on encoding in line 219: Attempt to get length of number.
When tested it don&#39;t seem to happen in other programs.
When tested it don&#39;t seem to happen in other programs.
Whoops, forgot you could term.write() numbers...
I for one tend to avoid that in my code, as monitors still format them differently to the regular terminal. For some reason.
wojbie, on 07 October 2015 - 07:42 PM, said:
Looks like last frame is held on screen for about 5 sec. Is that on purpose?
Yes, that's on purpose (line 74 sets the duration).
wojbie, on 07 October 2015 - 07:42 PM, said:
When waiting for [y/n] answer can you ignore all other than y/n?
Ok.
wojbie, on 07 October 2015 - 07:42 PM, said:
On other note something i was making using your RecGif. Showcase for one of my programs:
Yes, I figured it'd be useful for that sort of thing.
Looks like you might want to have it wrap quotes around the argument suggestions with spaces in them.
Bomb Bloke 10 Oct 2015
SquidDev, on 07 October 2015 - 03:06 PM, said:
Having a read through I guess it would be too difficult to show key presses - something like this (and even mouse clicks)?
Alright, I've added something along those lines - an example animation has been added to the OP. I was considering having the input fade after a while, but I for one type quickly enough that the line tends to run off the screen nearly immediately anyways... I may pretty it up a bit some other day.
I've also dug out a higher resolution font file, which can be optionally downloaded in place of the default low-res one. That was used to create the Bank Vault animation.
Bomb Bloke 10 Oct 2015
Certainly, users need not ask permission or worry about credit. Go for it.
Bomb Bloke 11 Oct 2015
Bomb Bloke 21 Dec 2015
Updated with font support for CC1.76 - you'll need to delete your old font file after updating ComputerCraft (ascii.gif). Updates to my Package and GIF APIs recently may mean you'll also need to delete those before running this new version too (it'll automatically download all required files if they're missing).
Edited by Bomb Bloke, 10 February 2016 - 11:05 PM.
Spoiler
Edited by Bomb Bloke, 10 February 2016 - 11:05 PM.
DvgCraft 15 Feb 2016
Wow! looks nice! But... It doesn't work.
After it has asked to save and where to save, it starts to save and download the nessessary files. But then, it raises an error:
Any ideas?
EDIT: I'm on CC 1.63
Edited by DvgCraft, 15 February 2016 - 05:33 PM.
After it has asked to save and where to save, it starts to save and download the nessessary files. But then, it raises an error:
recgif:190: attempt to index ? (a nil value)Line 190 says:
local set = ascii[y + ybump][x + xbump] == 1which references to the place ascii is assigned: (line 177)
local ascii, counter = GIF.toPaintutils(GIF.flattenGIF(GIF.loadGIF(shell.resolve("ascii.gif")))), 0So I think it has somehing to do with your GIF API.
Any ideas?
EDIT: I'm on CC 1.63
Edited by DvgCraft, 15 February 2016 - 05:33 PM.
Bomb Bloke 16 Feb 2016
Urgh, too many versions of ComputerCraft for me to keep track of these days. The GIF API wasn't causing that particular error, but when I corrected it, the API then DID crash out due a floating point problem... both issues were exclusive to older CC builds, though the first of the two was entirely my fault.
So you'll need to remove both the GIF API file as well as RecGif before updating. Don't forget to reboot your ComputerCraft system to force the new copy of the API to load (if it'd already loaded the old copy since its last restart, then it otherwise won't bother to download and load the new one).
I also noticed a bug where the text cursor sometimes gets stuck in the recording where it shouldn't, but I'll have to dig deeper into that when I've got some time. I also need to re-write Package one of these days (the bit which does most of the work, handling all the image compression); there's bound to be some speed improvements to be made there.
So you'll need to remove both the GIF API file as well as RecGif before updating. Don't forget to reboot your ComputerCraft system to force the new copy of the API to load (if it'd already loaded the old copy since its last restart, then it otherwise won't bother to download and load the new one).
I also noticed a bug where the text cursor sometimes gets stuck in the recording where it shouldn't, but I'll have to dig deeper into that when I've got some time. I also need to re-write Package one of these days (the bit which does most of the work, handling all the image compression); there's bound to be some speed improvements to be made there.