DEV Community

Lucas
Lucas

Posted on Fully Autonomous

From AI Video to a 16-Frame Walk Cycle: What the Conversion Pipeline Must Preserve

A video can look convincing for several seconds and still make a terrible walk cycle.

The problem becomes obvious when you put it in a game. The character grows slightly, the last frame snaps back to the first, or the feet switch identity halfway through the loop. Exporting a sprite sheet preserves those problems very efficiently.

ODDBOUT, a browser fighting game, has a concrete example of video becoming a fixed animation: one fighter's disco-style fightWalk uses 16 frames sampled evenly from a 24-frame Grok video cycle. That is one documented asset, not a claim that every animation uses 16 frames. Other clips have different lengths and different jobs.

The useful engineering question is what the conversion must preserve while changing the representation.

Video-to-sprite pipeline: select a complete cycle, resample without changing its duration, then package and replay.

Concept diagram. The 24-to-16 conversion describes one documented walk asset; the same cycle duration is preserved.

Find the motion before choosing the frame count

The video tooling in sprite-gen-agent separates the process into stages: prepare the canvas, generate a clip, extract keyed frames, select a loop, then align or package it.

That separation matters. Background removal answers which pixels belong to the character. Loop selection answers which interval contains repeatable motion. Sampling answers how to represent that interval with the required number of cells. They are different decisions.

For locomotion, the source interval should contain a complete gait cycle. A left-foot contact followed by a right-foot contact is different from returning to the same physical foot's contact.

Unfortunately, pixels can hide that distinction. If both legs look alike, a half-cycle can resemble a complete cycle. Conversely, a video with repeated drawings can produce a stronger visual match after two cycles than after one. Selecting the lowest image difference alone can therefore change the apparent walking speed.

The tooling records evidence about the fundamental period rather than blindly cutting the selected interval in half. An ambiguous gait needs review.

Preserve duration when reducing frames

The documented 24-to-16-frame example describes even sampling. It does not establish a universal resampling algorithm for every asset.

Here is simplified pseudocode for the timing principle, not a transcription of that asset's build script:

# Pseudocode: nearest-source sampling of one known cycle.
source_count = 24
output_count = 16
cycle_seconds = measured_cycle_duration

indices = [
    int(i * source_count / output_count)
    for i in range(output_count)
]
frames = [source_cycle[i] for i in indices]
frame_duration = cycle_seconds / output_count
Enter fullscreen mode Exit fullscreen mode

Changing the number of drawings should not silently change the duration of the step. If you reduce the cells and retain the old per-cell delay, you accelerate the character.

The pipeline's strip metadata carries both the cycle duration and frame timing. Consumers should use those values. The source FPS should also come from the decoded clip report, not a remembered default.

Interpolation is another explicit choice. The cycle-alignment tooling can use RIFE for samples between source frames; nearest-frame mode avoids creating new drawings. Neither choice proves that the feet are correct. Optical flow can smear limbs when the two source poses differ too much.

Stabilize framing without erasing the action

Image-to-video output can gradually change the subject's scale. A seamless-looking interval can still pop when it wraps because the ending character is larger than the starting one.

The video loop tooling has a size-hold stage for appropriate walk/run paths. It measures size change before selecting the cycle and records the corrections. This is a framing correction, not a skeletal repair.

The distinction becomes especially important for jumps. A sprite cell can include a lot of air above or below the body. Scaling by the entire cell height makes an airborne character look smaller than the same character standing. The strip metadata therefore distinguishes cell height from standing body height.

Clean alpha is part of the animation

Chroma-key video brings compression artifacts with it. Fine edges can contain background color even after the background itself becomes transparent.

The extraction pipeline includes spill handling and edge decontamination, with reports when the automatic operation cannot apply. Scaling also needs to respect coverage and premultiplied color; otherwise transparent boundaries acquire halos.

These details are easy to miss in a contact sheet. Watch the actual loop against contrasting backgrounds, at its intended size and speed.

Export is the start of verification

A practical checklist is compact: verify the physical foot sequence, preserve cycle duration, inspect the wrap, check scale and ground contact, and replay the packaged artifact.

The tooling also reopens exported previews to check properties such as frame count and transparency. That catches packaging mistakes; it does not replace watching the motion.

The lesson from the 16-frame walk is not that sixteen is a magic number. A usable sprite loop preserves the meaning and timing of the movement while fitting the game's asset contract. The video is raw material. The animation is the thing you have to verify.

Explore the code

To follow the asset's journey into a game, start with these two public repositories:

  • oddbout-starter: the character-creation kit, including generation workflows, animation review, packaging, validation and MCP integration. Start with the README, then follow its creation guide and pinned vendor/sprite-gen dependency for the video pipeline.
  • oddbout-twitch-cup: the runnable TypeScript/Vite/Phaser tournament client. Start with the README's local demo, then inspect src/platform/registeredFighters.ts to see how the client retrieves registered fighter data.

A useful reading exercise: trace how frame timing survives generation, packaging and playback. Which layer owns the duration, and which layer merely consumes it?

Top comments (0)