JSON Killer
5MB JSON reduction for Scratch games.
An .sb3 is a zip. Costumes and sounds take up the majority of space, but the
project.json needs to track them which quickly adds up.
This strips out the redundant or bulky tracking without changing behavior (hopefully). So now you'll have more space if the
project.json exceeds the 5MiB limit!! Please save backups though, this is highly experimental.
This all runs in-browser, nothing is uploaded!
This doesn't kill JSON.
2× is the default. scratch-vm
overwrites bitmapResolution with 2 as it loads and then
shows every costume at half its pixel size, so nothing bigger works.
Draws each costume bigger and averages it back down. Creates slightly cleaner edges on fine detail.
This doesn't kill JSON.
This only reduces if the file would be smaller afterwards.
Method
- Drops
"topLevel":false,"shadow":false,"next":null. Every scratch-vm reader is a truthy test or null safe. - Drops empty
"inputs":{}and"fields":{}. The deserializer walks both withfor..in. - Drops the trailing null id from field arrays, read behind
if (fieldId). - Drops costume
md5extwhen it equalsassetId + "." + dataFormat, which scratch-vm rebuilds. Soundmd5extstays since it has no fallback. - Drops
bitmapResolutionfrom svg costumes that carry the default 1. Nothing on the vector path reads it:loadVector_ignores it, and editing the costume hasupdateSvgwrite it back as 1. - Rounds rotation centre floats to 3dp, trimming noise like
299.50337500000004. - Deletes orphaned blocks: residue that no top level script reaches and that is attached to nothing which survives. A block still naming a live parent is a detached script rather than residue, so it is kept and reported instead.
- Checks the delete pass by attachment, not by reachability. Reachability is what chooses the blocks to drop, so asking it afterwards whether the choice was right only ever returns its own answer.
- Reports links that disagree in both directions, where a block points at something another block owns.
- Reports dropdowns naming a costume, backdrop, sound or sprite that is gone. Red hides or duplicates code and is yours to fix, yellow runs and does nothing and can be deleted, green is covered up and can be repaired. Residue the sweep removes anyway is not reported.
- Leaves a name that parses as a number alone. Scratch falls back to using it as an index, so such a block still does something.
- Reports inputs naming a block the file does not contain. In the first slot that is a blank hole in a script and the value is gone for good; underneath a plugged in reporter it reads as nothing and the dangling id is simply dropped.
- Offers to remove a duplicated custom block definition: a copy whose own pointers aim at another script’s blocks, along with the code hanging under it.
- Keeps
"parent":null.getTopLevelScriptloops onwhile (block.parent !== null).
Rasterizing
Doesn't decrease JSON. It redraws svg costumes as png.
- A costume is sized the way scratch-vm sizes it: the bounding box of what is actually drawn, grown by half of the widest stroke in the file. The png covers exactly that box, so the drawing keeps its size and its place.
- Anything over 480 × 360 is left as svg. Those costumes are listed by
their name in the
project.jsonafter a run.
Sounds
Doesn't decrease JSON. Every sound is decoded, mixed down to one channel and re-encoded as mp3.
dataFormat becomes mp3, which is in the list
scratch-parser accepts.
- Scratch's library sounds are 22 kHz adpcm at about 88 kbps, so at the default 128 most default assets won't be shrunk.
Support
Donate at ko-fi.com/krazvalt if you wanna support me!!