WP Manifestindependent plugin directory
manifest / media / frame-sequence-generator

Frame Sequence Generator

Image frame sequence generator for wordpress. Useful to build seamless scroll animations.

by i-jim666 · github.com/i-jim666/frame-sequence-generator · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/i-jim666/frame-sequence-generator/archive/refs/heads/main.zip

Readme

Frame Sequence Generator

A WordPress plugin that turns a Lottie animation, a video, or a ZIP of images into a numbered frame sequence inside the uploads folder, and hands back the two values a scroll-scrubbed canvas block needs: the first frame URL and the frame count.

Scroll sequences are drawn on a canvas from a folder of numbered images. Producing that folder normally means converting the animation by hand and uploading the result over SFTP. This plugin does it from Media → Frame Sequences.

wp-content/uploads/frame-sequences/my-animation/
├── frame-000.webp
├── frame-001.webp
├── …
└── sequence.json      ← what it was made from

Frames are numbered from zero (frame-000, frame-001, …), zero-padded to at least three digits — the pattern the front end walks.

Requirements

WordPress 5.6+
PHP 7.0+
Capability upload_files (editors and up)
ZIP input PHP zip extension
Video / animated GIF input ffmpeg on the server (optional)
Resizing / format conversion GD or Imagick (optional)

Nothing beyond WordPress itself is required for the main path — Lottie files with embedded frames are copied out byte-for-byte using plain PHP.

Installation

cd wp-content/plugins
git clone git@github.com:i-jim666/frame-sequence-generator.git

Activate Frame Sequence Generator in Plugins, then open Media → Frame Sequences.

Usage

  1. Drop a file onto the upload area.
  2. The file is analysed and sensible defaults are proposed (aiming for ~120 frames).
  3. Adjust the name, frame count, format and maximum width if needed, and generate.
  4. Copy the first frame URL and frame count into the block's Frame sequence fields.

Supported input

Input Extensions Notes
Lottie / Bodymovin .json, .lottie Embedded raster frames are copied out with no re-compression. Playback order comes from the layer list, not asset order.
Image sequence .zip Numbered PNG/JPEG/WebP, sorted the way a human counts (frame2 before frame10).
Video / animated .mp4 .m4v .mov .webm .mkv .gif .webp .apng Requires ffmpeg.

A .zip is inspected on arrival: if it contains an animation JSON it is treated as a dotLottie archive, otherwise as a folder of images.

A genuine vector Lottie has no frames to extract and PHP cannot rasterise it. The plugin detects this and says so, rather than failing obscurely — export an image sequence or an MP4 from After Effects and upload that instead.

Options

  • Frames to keep — source frames are sampled at a fixed step. The default targets about 120 frames, which scrubs smoothly without a punishing download.
  • Format — only formats this server can actually write are offered. Keep original never re-compresses and is always available.
  • Maximum width — scales frames down when the source is larger than needed.

Managing sequences

Every generated sequence is listed under Your sequences with a Delete button. Before deleting, the plugin searches post_content and postmeta for pages still referencing that folder and warns you by name.

Scan uploads folder finds sequences placed by hand before the plugin was installed, so those can be copied or removed here too.

How it works

Streaming Lottie parsing

A 480-frame Lottie export runs to tens of megabytes; json_decode()ing it whole would exhaust a shared host's memory limit. Instead the file is read in a windowed pass that records the byte offset and length of each base64 payload, while everything between the payloads is stitched into a small "skeleton" — the same JSON with each blob replaced by a marker — which is cheap to parse and yields the real playback order from the layer list. A 52 MB animation uses roughly 2 MB of memory this way, against 100 MB+ for a full decode.

Frame format is sniffed from the bytes rather than trusted from the declared MIME type; these exports routinely label WebP payloads as image/png.

Batched writes

Frames are written in small batches with a 12-second wall-clock guard per request, so a 500-frame sequence never depends on one long request surviving the host's timeout. The browser drives the loop and shows progress. Passthrough copies run 40 frames per batch; re-encoding runs 8. Video extraction is the exception: ffmpeg writes the frames itself in one background process that the UI polls.

Jobs

Uploads live in uploads/frame-sequences/.jobs/<id>/, protected by .htaccess and an index.php. A job belongs to the user who started it, and a daily cron sweep (fsg_cleanup_jobs) discards anything older than 24 hours that was never finished.

Deletion safety

  • Paths from the client are resolved against the uploads root and re-checked there — never trusted as given.
  • Deletion refuses anything outside wp-content/uploads, and refuses the uploads root.
  • Only the frames describe() actually identified are removed. Anything else in the folder survives and is reported back.
  • Outside the plugin's own folder, a directory must look like a sequence — at least 8 frames, an unbroken run of numbers, and ≥80% of the folder's images belonging to that run — before it can be touched at all. uploads/2026/08 fails that decisively.

Layout

frame-sequence-generator.php     Bootstrap: constants, requires, cron wiring
includes/
  class-fsg-env.php              What this server can do (GD, Imagick, ffmpeg, zip)
  class-fsg-library.php          Sequence discovery, description, usage search, deletion
  class-fsg-job.php              Job lifecycle and the per-frame index
  class-fsg-image.php            Sniffing, dimensions, resize/convert
  class-fsg-source-lottie.php    Streaming Lottie/dotLottie parser
  class-fsg-source-files.php     ZIP extraction and natural-sorted image lists
  class-fsg-source-video.php     ffmpeg probe and extraction
  class-fsg-ajax.php             Endpoints
  class-fsg-admin.php            Media → Frame Sequences screen
assets/
  admin.css
  admin.js

AJAX endpoints

All are admin-ajax.php actions prefixed fsg_, guarded by the upload_files capability and an fsg nonce.

Action Purpose
fsg_upload Receive and analyse a source file, create a job
fsg_start Apply options, prepare the output folder
fsg_batch Write the next batch of frames
fsg_progress Poll ffmpeg extraction
fsg_finish Write sequence.json, destroy the job
fsg_cancel Discard a job
fsg_list List sequences (optionally scanning uploads)
fsg_usage Find content referencing a sequence
fsg_delete Delete a sequence
fsg_redetect Re-probe for ffmpeg

Configuration

Constants, all optional, definable in wp-config.php before the plugin loads:

// Folder inside wp-content/uploads that holds every sequence.
define( 'FSG_FOLDER', 'frame-sequences' );

// Capability required to generate and delete sequences.
define( 'FSG_CAP', 'upload_files' );

// Skip ffmpeg auto-detection and use this binary.
define( 'FSG_FFMPEG_BIN', '/usr/local/bin/ffmpeg' );

Troubleshooting

ffmpeg is installed but not detected. The web server's PATH is usually narrower than a login shell's. The plugin probes ffmpeg, /usr/bin, /usr/local/bin, /opt/homebrew/bin, /opt/local/bin and /snap/bin, and caches the answer for a day. Use Check again for ffmpeg under What this server can do, or set FSG_FFMPEG_BIN.

"That file is larger than this server accepts." The upload never reached PHP. Raise upload_max_filesize and post_max_size, or upload a smaller export.

The sequences folder is locked. wp-content/uploads/frame-sequences must be writable by the web server user.

No WebP option. This server has no WebP encoder. Frames that are already WebP still come through untouched via Keep original.

License

GPL-2.0-or-later.

Read the full README on GitHub →