Skip to main content
Go to Editor

Wiki

This guide will help you get started quickly with the JSON Optimizer. Load Project: Use the InputNode to load your .json , .atlas , and .png files. Choose a pre

animationbeginnerchartsconceptsconnectionscontrolsdataexamplesexportfpsguidelosslesslossymemorymetricsoptimizationperformancepipelinesplaybackpluspremiumpricingrecorderrecordingresultssocketsstatisticssubscriptiontabletimelinetypesuivideoviewerworkflowyoutube

Getting Started: Basic Workflow

beginnerworkflowguide

This guide will help you get started quickly with the JSON Optimizer. Load Project: Use the InputNode to load your .json , .atlas , and .png files. Choose a preset (Plus mode): In Plus mode, use the right panel to sel...

Read article

Socket Types & Data Flow

socketstypesdataconnections

This article explains the data types used by sockets in the node graph and what can be connected where. Socket types Spine Payload — runtime-friendly representation of the Spine project used by most processing nodes....

Read article

Subscription Plans & Premium Features

subscriptionpremiumpluspricing

re-polish offers two subscription tiers to fit different needs. Free Plan ✓ Basic Node Graph ✓ JSON Viewer ✓ Timeline with multiple tracks and customizable animation mixing ✓ Limited Optimizations ✓ Spine versions: 4....

Read article

Core Concepts: Lossy vs. Lossless

conceptslossylosslessbeginner

All optimization methods are divided into two types: Lossless: These methods only remove redundant data... Examples: SplineOptimizationNode , CleanupNode . Lossy: These methods simplify animation curves... Examples: R...

Read article

How to Measure Effectiveness

guidemetricsstatistics

To understand how effective your optimization is, pay attention to the following metrics: File Size: The final size of the .json file is the main goal of optimization. Keyframe Count: In the "Statistics" tab, you will...

Read article

Viewer: Controls Panel

viewercontrolsui

The Viewer tab overlays a Controls panel on top of the canvas. It’s split into three groups: Animation Controls Animation — selects which Spine animation is playing. Skin — selects which Skin is applied. Speed — playb...

Read article

Viewer: Performance Panel

performancefpsmemoryui

The Performance panel shows real-time runtime metrics for the currently playing skeleton(s). Real-time FPS — frames per second measured by the monitor. Frame Time — time per frame in milliseconds (lower is better). FP...

Read article

Viewer: Timeline

viewertimelineanimationplaybackguide

The Timeline panel is a dockable animation sequencer at the bottom of the Viewer. It lets you arrange animation clips on multiple tracks, control playback, and preview transitions. Tracks & Clips Up to 4 animation...

Read article

Viewer: Recorder

viewerrecorderrecordingexportvideoguide

The Recorder captures Spine animations from the viewer as video, animated images, or image sequences. Recording Modes ⚡ Quick Record — real-time capture using MediaRecorder + captureStream() . Produces WebM output onl...

Read article

Results Tab

resultstableoptimization

The Results tab shows detailed optimization output. Results table — a row-per-change view of JSON optimization results (e.g. which animation/bone/property/keyframe was modified or removed). Sprite/Atlas comparison — w...

Read article

Statistics Tab

statisticschartsmetrics

The Statistics tab summarizes optimization results as charts and aggregated metrics. Optimization Chart — visualizes optimization impact over the dataset (when JSON optimizations produced changes). Metrics Table — key...

Read article

Pipeline Examples (Video)

videoexamplespipelinesyoutube

Below are complete, real-world pipelines from the official YouTube playlist. Open the full playlist Examples Spine2D Experiments 1: Curve Optimization with RDP Algorithm — baseline Spine 2D optimization demo: the Rame...

Read article

Nodes

Input

Imports Spine project files, JSON-only inputs, demo assets, and ZIP packages into the graph.

Purpose: This is the main entry point for most workflows. It reads JSON, atlas, and textures and normalizes them into internal data that downstream nodes can process.

Supported modes:
1. Full project: JSON + atlas + textures
2. JSON-only: process skeleton/animation data without an atlas
3. ZIP package: a packaged zip containing a complete project
4. Demo assets: built-in sample data for quick testing

Main inputs:
- **project_in**: packaged project input for upstream handoff or re-entry into the graph

Main outputs:
- **payload_out**: normalized data for optimization nodes
- **original_json_out**: source JSON for comparison or reconstruction
- **atlas_project_out**: parsed atlas project when textures are provided

Video To Png Sequence

Convert a video clip into a PNG frame sequence for Spine workflows.

This free input tool in the Input menu is intended for production workflows. It supports chroma key for green screens and unpremultiply-style matte cleanup for black backgrounds. Outputs are sent through payload_out and atlas_out.

Picture Input

Adds standalone PNG/JPEG images to the viewport so you can build cleaner previews and presentation shots.

Purpose: Use this node to place images directly into the viewport as presentation layers or visual helpers. It is useful when you want to decorate a scene, add supporting graphics, and make project previews look more polished before recording videos or demos.

Workflow: Load one image, then use the viewport tools to scale it, move it, and adjust its z-index so it sits correctly inside your composition. This makes it convenient for building attractive showcase shots without touching the main Spine project data.

This node is standalone and does not expose graph sockets.

Version: Spine JSON version format for the generated stub skeleton.
Blending: Blend mode for the generated attachment (normal, additive, multiply, screen).

Psd To Skeletons

Loads layered PSD/PSB files and generates linked Spine skeletons that preserve the Photoshop scene layout for fast preview assembly.

Purpose: Use this node when a scene was already blocked out in Photoshop and you want that layer stack to become a set of linked Spine skeletons in the viewer. Each visible PSD layer becomes its own picture-style skeleton positioned from the PSD coordinates, which makes it easier to build accurate previews and place scene objects without rebuilding the composition by hand.

Viewer workflow: After generation you can still change draw order in the viewer and move other skeletons around the imported PSD layer stack, which lets you place additional Spine characters or props between Photoshop layers.

Availability: Free node. This node is standalone and does not expose graph sockets.

Version: Spine JSON version format used for the generated layer skeletons.
Blending: Blend mode used for generated attachments when creating the linked skeleton set.
Load PSD: Open the PSD/PSB picker and generate linked layer skeletons from the selected file.
File Info: Read-only summary of the currently loaded PSD/PSB file.
Layer Count: Read-only count of visible layers that will be converted into linked skeletons.
Preflight: Read-only report about layer-name issues detected before generation.

Project Input

Loads a Spine project folder or archive into the graph and exposes a ProjectPayload through the project_out socket for downstream project-aware nodes.

Purpose: Entry point for project-based workflows. Scans a Spine project folder or archive, builds a ProjectPayload, and keeps cached metadata ready for downstream nodes such as Project Viewer, filters, Static Bake, and Deduplicator.

Controls:
- **Load Folder**: Opens the system folder picker via the File System Access API, scans the selected directory, updates the summary, caches metadata, and starts a file watcher so later changes can be rescanned.
- **Browse (Fallback)**: Uses a hidden **webkitdirectory** input for browsers without **showDirectoryPicker()**. It loads the project, but without a persistent directory handle, so live watching and reliable rescans are not available.
- **Load Archive**: Loads a **.zip** or **.spine** archive as a virtual project tree. Archive-backed projects do not keep a directory handle, so **Rescan** is unavailable by design.
- **Rescan**: Re-scans the previously loaded folder when a directory handle is available. It re-checks read permission before scanning. Projects loaded through fallback browse or archive mode usually report that no directory is loaded.
- **Clear Project**: Stops file watching, clears the current payload, summary, execution cache, and cached payload metadata.
- **Reset to Defaults**: Resets generic node controls only. It does **not** unload the current project and is not a replacement for **Clear Project**.
- **Drop folder or .zip here**: Drag-and-drop entry point that accepts folders and archives and routes them through the same loading pipeline.

Outputs:
- **project_out**: ProjectPayload with the scanned tree, flat file list, size totals, and type breakdown for downstream project-aware nodes.
- **stats**: DEV-only diagnostics output.

Output

Collects the final results and lets you download optimized data as separate files, grouped file sets, or archives.

Purpose: Acts as the export hub for optimized JSON, atlas data, textures, and sprites. It can assemble results from a single JSON/atlas/textures set, from multiple file sets, or from sprites only when you want image output without rebuilding a full Spine project.

Export options:
- Download files individually or as a single archive
- Download packed results or an archive with unpacked files
- Export JSON in compact form or in a readable pretty-printed form
- Export complete Spine project data or only sprite/image results

Chaining workflow: OutputNode does not have to be the absolute end of the graph. You can pass its outputs into another pipeline stage and run the same files through additional optimization passes. In practice, key and curve optimization was tested for up to 3 consecutive iterations.

Canonical socket keys:
- Inputs: **payload**, **original_json**, **atlas_project**, **payloads**, **atlas_projects**, **original_jsons**, **sprite_batch_in**
- Outputs: **reconstructed_json_out**, **original_json_passthrough_out**, **payload_out**, **changes**, **atlas_assets**

RDP

Simplifies animation curves using the Ramer-Douglas-Peucker (RDP) algorithm.

Purpose: Reduces the number of keyframes in linear or near-linear animation segments by removing points that lie on a straight line between two others.

Golden Rule: Disabled by default. It protects curves with significant shape (area/curvature) from being flattened to linear. Disable it only for more aggressive compression after visual review.

Socket keys: payload_in, payload_out, changes

Epsilon: Maximum deviation from original curve. Higher values remove more keyframes but may lose curve detail.
Steep: Curvature sensitivity threshold. Protects complex curves from being flattened to linear.
Round Mode: Rounding mode for optimized values: none (keep original), tenths (1 decimal), units (integers).
S Run Length: Minimum number of consecutive standard Spine S-curves required before template-based flattening activates. Set to 0 to disable this feature.
S Deviation: Allowed normalized deviation from the standard Spine S-curve template in permille (0-300). Lower values require a closer match; higher values flatten more near-template runs.

Spline

Fits smooth spline curves to animation keyframes, reducing unnecessary intermediate points.

Purpose: Smooth curve fitting while maintaining visual quality.

Socket keys: payload_in, payload_out, changes

Max Error: Maximum allowed approximation error for spline fitting. Lower = tighter fit to original data.
Min Group Size: Minimum number of consecutive linear keyframes required to form a removable group.

Refit

Approximates dense keyframe sequences with fewer Bezier curves to reduce size.

Purpose: Fits fewer curves while staying within a tolerance.

Socket keys: payload_in, payload_out, changes

Error Tolerance: Maximum allowed deviation between original curve and fitted Bezier. Lower = more accurate.
Max Iterations: Number of optimization iterations for curve fitting. More iterations = better fit but slower.

Quantizer

Reduces precision of numeric values in keyframes and curves.

Purpose: Simple but effective way to reduce file size by rounding numbers to a specified number of decimal places.

Usage: Can be applied to almost any animation data. Becomes more effective with higher keyframe counts.

Caution: Too aggressive quantization (low precision) can cause jitter or visual artifacts in animations.

Socket keys: payload_in, payload_out, changes

Cleanup

Performs various cleanup tasks to remove redundant or unnecessary animation data.

Purpose: Specialized tool for removing specific types of redundant data that other optimizers might miss.

Usage: Connect your payload to 'payload_in' and take the result from 'payload_out'. If you want a per-change report, also use 'changes'.

Socket keys:
- Inputs: payload_in
- Outputs: payload_out, changes

Currently supported cleanups:
1. **Remove Unused Color/Alpha Tracks**: Removes color/alpha timelines for slots that are never visible during the animation.
2. **Remove Redundant IK Rotations**: Removes rotation keyframes from bones that are fully controlled by an IK constraint with 100% mix.
3. **Remove Path Constraint Keys**: Removes rotate/translate keyframes from bones fully controlled by a path constraint (mix values at 100%).
4. **Sanitize Non-English Characters**: Replaces non-English characters in names/identifiers to avoid issues in downstream tools.

Remove Unused Color Tracks: Remove color/alpha timelines for slots that are never visible during animation.
Remove Redundant IKRotation: Remove rotation keyframes from bones fully controlled by IK constraint at 100% mix.
Remove Redundant Path Constraint Keys: Remove rotate/translate keys from bones fully driven by a path constraint.

Scale

Scales all numeric values in animation keyframes by a specified factor.

Purpose: Uniformly scales animation data, useful for resizing skeleton proportionally or adjusting animation intensity.

Usage: Connect **payload_in** and take the result from **payload_out**.

Socket keys: payload_in, payload_out

Scale Factor: Multiplier applied to skeleton dimensions (e.g. 0.5 = half size, 2.0 = double size).
Scale Bones: Scale bone positions and lengths.
Scale Attachments: Scale attachment dimensions and positions.
Scale Animations: Scale animation translation values.
Scale Constraints: Scale constraint positions and distances.
Scale Path: Scale path attachment vertices.

Schneider

Fits smooth Bezier curves to animation keyframes using the Schneider curve fitting algorithm.

Purpose: Advanced curve fitting that produces natural-looking Bezier curves from dense keyframe sequences.

Availability: **Plus-only node**.

How it works: The Schneider algorithm analyzes keyframe positions and tangents to generate optimal Bezier control points that closely match the original motion.

Parameters:
- **Error Tolerance**: Maximum allowed deviation from original keyframes. Lower = more accurate, higher = smoother curves.
- **Corner Angle**: Threshold angle (degrees) at which to split curve into segments.

Best for:
- Hand-drawn or imported animations with many keyframes
- Converting linear interpolation to smooth Bezier curves
- Reducing keyframe count while maintaining curve quality

Note: More computationally intensive than simpler algorithms like RDP, but produces superior curve quality.

Socket keys: payload_in, payload_out, changes

Min Segment Size: Minimum number of keyframes in a segment before the algorithm attempts curve fitting.

Physics Constraint Bake

Bakes Spine PhysicsConstraint motion into bone rotate/translate keyframes and removes physics timelines.

Purpose: Converts runtime physics simulation into explicit keyframes so animations are deterministic and editable without physics constraints. After bake, physics constraints and physics timelines are removed from the payload.

Availability: **Plus-only node**.

Inputs/Outputs:
- **payload_in** → **payload_out** (baked)
- **changes** (optional change list)

Controls:
- **Sample FPS**: Simulation sampling rate for the bake.
- **Bake Rotation**: Write baked rotation keys.
- **Bake Translation**: Write baked translation keys.
- **Bake Translation (Children)**: Apply translate bake to child bones that rely on physics motion.

Notes:
- Requires original Spine JSON to reconstruct simulation data.
- Use when you want to remove physics constraints but keep the motion.

Attachment Visibility

Optimizes rendering by setting a slot's attachment to null when its alpha is zero.

Purpose: Prevents the game engine from having to process or render invisible attachments.

Usage: Processes **payload_in**, outputs optimized **payload_out**, and optionally reports **changes**.

Socket keys: payload_in, payload_out, changes

Alpha Threshold: Alpha value below which attachments are set to null. Default 0 means only fully invisible slots.
Auto Restore: Automatically restore attachments when alpha rises above threshold.

Payload Merger

Merges multiple processed animation payloads back into a single unified payload.

Purpose: Essential for parallel processing pipelines where different animations or bone groups are optimized separately and need to be recombined.

Inputs:
- **base**: Master payload (skeleton structure)
- **overrides**: One or more payloads whose tracks replace base tracks

Output:
- **merged_out**: Merged payload

Socket keys: base, overrides, merged_out

Warn conflicts: Show warnings when merged payloads contain conflicting animation tracks.

Animation Viewer

Visual tool for inspecting and comparing animation curves before and after optimization.

Purpose: Provides graphical representation of keyframes and curves for selected track.

Usage: Connect **before_in** and **after_in** to overlay original vs optimized. Optionally connect **changes** to highlight impacted tracks.

Socket keys: before_in, after_in, changes

Show changed: When enabled, highlights only animations that were modified by the pipeline.
Animation: Select the animation to preview in the viewport.
Target: Select which skeleton version to view (original vs. optimized).
Property: Select which animation property to visualize (translate, rotate, scale, etc.).

Project Viewer

Displays a Spine project from the project_in socket for inspection and preview without mutating the incoming data.

Deduplicator

Deduplicates atlas projects by consuming project_inputs and returning payloads, atlas_projects, original_jsons, and shared_atlas_out for canonicalized downstream workflows.

The Deduplicator node scans all atlas regions for visually identical or near-identical sprites. It merges duplicates by choosing a canonical representative and remapping references. Several thresholds control detection sensitivity for different sprite types (glow, solid, alpha). Optionally constrains the output canonical atlas dimensions. A verification pass ensures the deduplicated result is visually equivalent to the original within the specified RMSE tolerance.

Socket keys: project_inputs, payloads, atlas_projects, original_jsons, shared_atlas_out

Repack mode: How to handle repacking after deduplication: auto, conservative, or aggressive.
Glow threshold: Similarity threshold for glow/bloom sprite hashing. Lower = stricter matching.
Solid threshold: Similarity threshold for solid (opaque) sprite hashing.
Min sprite area: Minimum sprite area in pixels squared. Sprites smaller than this are skipped.
Alpha hash threshold: Similarity threshold for alpha channel comparison.
Verification threshold: Post-dedup verification: max allowed pixel difference between original and deduplicated.
Color rmse threshold: Root mean square error threshold for solid color comparison.
Constrain canonical atlas size: When enabled, limits the canonical atlas to specified max dimensions.
Max canonical atlas width: Maximum width for the canonical atlas page.
Max canonical atlas height: Maximum height for the canonical atlas page.

Animation Filter

Filters animation tracks based on animation name (e.g., 'run', 'idle').

Purpose: Useful for applying different optimization strategies to different animations.

Usage: Filters **payload_in** into **payload_out** for single-payload workflows, or accepts **project_in** and forwards the enriched project through **project_out** so downstream project-aware nodes can discover animations immediately. The node also exposes **animation_list** for UI selection.

Socket keys: payload_in, project_in, payload_out, project_out, animation_list

Asset Filter

Filters atlas assets by name, works in two modes: before unpacker (filters atlas text) or after unpacker (filters sprites).

Purpose: Controls which assets are included in the workflow - either which assets to unpack from atlas, or which unpacked sprites to include in repacking.

Inputs/Outputs:
- Atlas mode: **atlas_in** → **atlas_out**
- Sprites mode: **sprites_in** → **sprites_out**

Socket keys: atlas_in, atlas_out, sprites_in, sprites_out

Bone Filter

Filters bone animation tracks based on bone name.

Purpose: Allows targeting or excluding specific bones from the optimization process.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Skin Filter

Filters animation and asset data based on skin names.

Purpose: Process only specific skins from a multi-skin Spine project.

Usage: Filters **payload_in** into **payload_out** for payload workflows, or accepts **project_in** and returns **project_out** with project metadata enriched by the selected skin subset.

Socket keys: payload_in, project_in, payload_out, project_out

Slot Filter

Filters slot animation tracks based on slot name.

Purpose: Useful for targeting or excluding specific slots that may have special timing or visibility requirements.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Parameter Filter

Filters animation tracks based on their property type (e.g., rotation, scale, color).

Purpose: Allows applying subsequent optimizations only to specific types of animation data.

Usage: Filters **payload_in** into **payload_out**.

Socket keys: payload_in, payload_out

Rotation: Include rotation animation tracks in the output.
Translation: Include translation animation tracks in the output.
Scale: Include scale animation tracks in the output.
Shear: Include shear animation tracks in the output.
Color: Include color/alpha animation tracks in the output.
Attachment: Include attachment switch animation tracks in the output.
Deform: Include mesh deform animation tracks in the output.

Atlas Unpacker

Extracts individual sprites from a Spine texture atlas.

Purpose: Breaks down an atlas file into its component sprites, allowing for individual analysis or repacking.

Usage: Connect **atlas_project** from InputNode to **atlas_project** (or the legacy **atlas_project_in**) on this node. Optionally connect **skeleton_json_in** (from InputNode's **original_json**) to enable mesh-aware cropping (trims sprites to mesh hull bounds instead of rectangular bounds, which can significantly reduce texture memory for mesh attachments).

Outputs:
- **sprites_out**: Standardized sprites array (for viewer/repacker)
- **sprites_data_out**: Extracted sprite images/metadata (structured bundle)
- **atlas_out**: Atlas project passthrough

Socket keys: atlas_project, atlas_project_in, skeleton_json_in, sprites_out, sprites_data_out, atlas_out

Atlas Repacker

Repacks individual sprites into one or more new, optimized texture atlases.

Purpose: Optimizes texture memory and potentially reduces draw calls by creating efficient sprite sheets.

Usage: Accepts sprites either via **sprites_data_in** (structured sprites bundle) or via **sprites_out** (standardized sprites array). If needed for alpha handling / polygon packing, provide the original skeleton via **original_json**. Outputs a packed atlas as **atlas_out**.

Socket keys: sprites_data_in, sprites_out, original_json, atlas_out

Min Page Width: Minimum atlas page width in pixels.
Min Page Height: Minimum atlas page height in pixels.
Max Page Width: Maximum atlas page width in pixels.
Max Page Height: Maximum atlas page height in pixels.
Padding X: Horizontal spacing between packed sprites (pixels).
Padding Y: Vertical spacing between packed sprites (pixels).
Edge Padding: Add padding around the edge of the atlas page.
Duplicate Padding: Duplicate sprite edge pixels into padding area to prevent bleeding.
Alpha Mode: Alpha handling mode for packed sprites (auto, premultiply, strip, etc.).
Alpha Threshold: Alpha values below this are treated as fully transparent during packing.
Strip Whitespace X: Remove transparent columns from sprite edges before packing.
Strip Whitespace Y: Remove transparent rows from sprite edges before packing.
Color Bleed Radius: Number of pixels to extend during color bleed.
Scale: Scale factor applied to all sprites before packing.
Power Of Two: Force atlas dimensions to be powers of two (required by some game engines).
Divisible By4: Force atlas dimensions to be divisible by 4 (useful for video codec compatibility).
Square: Force atlas to be square (width = height).
Allow Rotation: Allow sprites to be rotated 90 degrees for tighter packing.
Packer Type: Bin-packing algorithm: MaxRects or similar.

Atlas Viewer

Lightweight atlas visualization and analysis tool for inspecting atlas structure before unpacking.

Purpose: Provides a fast way to preview atlas pages and regions without performing the heavy unpacking operation. Helps validate atlas structure and identify unused regions.

Usage: Connect a single atlas project to **atlas_project** (or legacy **atlas_in** / **atlas**), or inspect a batch of atlas projects via **atlas_projects**. Optionally connect skeleton JSON to **json** for usage analysis.

Socket keys: atlas_project, atlas_projects, atlas_in, atlas, json

Page Info: Shows the current atlas page number.
Stats: Displays atlas statistics: total regions, merged size, compression ratio.

Atlas Merger

Combines multiple atlas sources into a single unified atlas.

Purpose: Merge multiple atlas projects into one.

Input:
- **atlas_inputs**: Multi-input array of atlas projects

Outputs:
- **atlas_out**: Merged atlas project
- **merged_out**: Legacy merged output
- **merged_atlas_out**: Legacy merged output

Socket keys: atlas_inputs, atlas_out, merged_out, merged_atlas_out

Typical pipeline:
```
InputA → Unpacker → Repacker ─┐
                               ├→ Atlas Merger → Unpacker → Repacker → Output
InputB → Unpacker → Repacker ─┘
```
Before Repacker the data is individual sprites; after Repacker it becomes an atlas project. Atlas Merger combines the atlas projects, then a final Unpacker → Repacker pass repacks everything tightly into a single unified atlas.

Asset Viewer

Displays individual sprites from an unpacked atlas.

Purpose: Visual debugging tool for atlas manipulation.

Usage: Accepts sprites via **sprites_out** (standard) or legacy **sprites_in** / **sprites_data**.

Socket keys: sprites_out, sprites_in, sprites_data

Asset select: Select which attachment or atlas region to inspect.
Pixel stats: Shows pixel-level statistics for the selected asset (dimensions, alpha, colors).