animated-loop is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Generate a short seamless video loop: splash background, animated logo backdrop, idle title screen.
When your agent uses it
- Generating a short looping video clip — splash screen background, animated logo backdrop, idle title-screen footage, looping environment ambience
- An idle backdrop behind the UI needs subtle motion without a real-time animated scene
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
A loop is the only video format that has to not have a beginning or end. The viewer sees it on the title screen for 30 seconds; if the seam between loop iterations is visible, the whole thing reads as broken. This skill exists to force the constraints that make seams invisible: take the shortest duration available, keep the motion ambient (no narrative, no big camera moves), use the fast model (ltx), and prompt for a composition where the first and last frames are functionally identical.
Duration is not a dial here. On ltx and kling, assets.generate_video renders only duration: 5 or duration: 10; every other value renders 5. So “drop to 3s to hide the seam” is not an option — 5s is the floor, and the seam has to be won in the prompt and the reference frame instead.
If the user wants a 5s punchy marketing shot, that’s trailer-shot. If they want a 10s narrative cutscene, that’s cinematic-cutscene. This skill is the one for video that has to disappear — atmosphere behind a logo, mood behind a menu, ambience behind a splash card.
When to use
- “Looping background for the title screen.”
- “Animated backdrop behind the logo on the splash.”
- “Menu background — torchlit dungeon, just flicker and motes.”
- “Looping ambient video for the pause screen.”
- “Splash loop — fog over a forest.”
- “Need a video that loops behind the level select.”
When NOT to use
- Marketing shot for a trailer (5-10s with punch) —
trailer-shot. - Narrative cutscene with a beginning and end —
cinematic-cutscene. - Static splash image — generate with
concept-artand use aTextureRect. A still is cheaper, lighter, and never seams. - UI element animation (icons, button states) — those are GDScript
Tweenor sprite sheets, not video. - A 10-second shot you want to “loop”. That seam will be visible. Either accept a hard cut every 10s (ugly) or generate a 5s clip designed to loop.
Steps
1. Confirm the loop will be visible for a long time
Quick check — this loop will play on a screen the user might stare at for 30+ seconds. That means the loop point must be invisible. I’ll take the 5s minimum and prompt for ambient motion (drift, flicker, shimmer) rather than a narrative beat. OK?If the user wants narrative motion (a character walking, a door opening), this is the wrong skill — route to
cinematic-cutscene.
2. Pick the model — ltx first, always
For loops, ltx is almost always right. It takes ~30s, and short ambient motion is what it handles best. The premium models cost more credits and do not loop better.
This skill always passes imageUrl (step 3), which puts every call on the image-to-video route. kling-turbo and veo3 are text-to-video only; pairing either with an imageUrl is a 400 invalid_model, not a silent downgrade.
3. Lock the look with a reference still
The reference still doubles as the target loop frame. Generate it deliberately — the video model’s first and last frames will gravitate toward the reference, which is exactly what you want for a closing seam.aspectRatio to the screen the loop fills (16:9, or 9:16 for a vertical mobile splash).
On the image-to-video route aspectRatio is not applied at all — the clip inherits the reference image’s framing. So a vertical mobile splash needs a 9:16 reference image, and setting aspectRatio: "9:16" on the video call does nothing.
4. Prompt for loopable motion only
Loopable motion is continuous, ambient, directionless, or oscillating. Avoid anything with a beginning or end (a character entering, a sword swinging, a door closing). Loopable verbs:drift, flicker, swirl, shimmer, sway, pulse, glow, rise, fall, wave, breathe, ripple.
Non-loopable verbs (avoid): walks, enters, appears, emerges, transforms, attacks, falls down, opens, closes.
negativePrompt rules out narrative drift. Images have no negative prompt: put negations in the image prompt text.
aspectRatio is omitted deliberately: it is applied on the text-to-video path only, and this call passes imageUrl.
The call answers at once with { status: "running", job: { id } } and no URL. Call jobs.wait({ jobId: "<job.id>", timeoutSeconds: 50 }) until finished is true; only a done job’s result holds the clip.
5. Inspect the seam
Watch the result and the seam (the cut between the last and first frame on replay). If the seam is visible:- Most common cause: something moved across the frame and didn’t return (a particle drifted off-screen, a cloud moved). Regenerate with
slow continuous, returning motion, oscillatingin the prompt. - Second cause: lighting drifted. Regenerate with
constant lighting, no time of day change. - Third cause: the motion is simply too fast to close in the time available. You cannot shorten the clip — 5s is the minimum the API offers — so slow the motion in the prompt instead (
very slow,barely perceptible drift).
VideoStreamPlayer nodes and crossfade between them via a Tween. This is a fallback, not the goal.
6. Import and wire as a looping VideoStreamPlayer
Transcode to Ogg Theora first. The generated clip is an.mp4, and Summer Engine cannot load .mp4. .ogv is the only video container in the build — there is no bundled WebM or MP4 plugin, and nothing transcodes on your behalf. Measured against the shipped binary (4.6.1):
summer_import_from_url downloads the bytes, runs the engine’s import pipeline, and fails the import if the file never becomes a loadable resource — so importing the .mp4 does not quietly half-work, it is rejected and rolled back. Convert first:
scenePath is the exact scene to change:
VideoStreamPlayer in the tree.
7. Mute the audio track
Loops should never have a baked audio track that loops with them — the audio seam will be even more obvious than the visual one. The video models don’t generate audio anyway, but if you ever import a clip that has audio, mute it:music-track.
Reference card — prompts that work
Pattern:<subject> + <ambient loopable motion> + <constant lighting> + "looping, seamless" + <stylistic anchor>. Keep under 40 words. Always pair with imageUrl.
Bad prompts and why
Anti-patterns
- Asking the model for a 10s loop. Past ~6s, identity drifts and the seam shows.
duration=5is both the floor and the right answer; 10 is the only other value the API accepts. - Treating
assets.generate_videoas finished. It answers{ status: "running", job }and no URL. Wait withjobs.waitbefore claiming a clip exists. - Using
klingfor a loop.ltxis almost always right; short ambient motion is what it does best. - Prompting narrative motion. “Hero draws sword” doesn’t loop. Use ambient verbs.
- Forgetting
loop=trueon theVideoStreamPlayer. The clip will play once and freeze on the last frame. - Forgetting to mute baked audio. If audio is on, the loop point becomes audible even if it’s invisible.
- Expecting
aspectRatioto reframe an image-to-video call. It is applied on the text-to-video path only. A portrait splash needs a portrait reference image — the argument does nothing here. - Importing the
.mp4as-is..ogvis the only video container the engine can load; there is no bundled WebM or MP4 plugin. An un-transcoded import fails and is rolled back.
Edge cases
- Splash loop must be tiny in build size. Loops compress aggressively because of low motion. Target ≤2MB by exporting at 720p, low bitrate, in DaVinci. Studio’s import doesn’t re-encode by default.
- Mobile portrait splash. The reference image must be portrait —
aspectRatiois ignored on the image-to-video path, and MCP image generation is square-only, so make the reference in the Summer dashboard or crop it. Anchors preset 15 still works. - Loop must sync to a music beat. The video model doesn’t know your BPM. Generate at the duration matching one bar at the menu music tempo (e.g. 120 BPM × 4 beats = 2s, or 8 beats = 4s) and confirm visually.
- Loop is behind translucent UI. Generate with extra contrast headroom — the model tends toward mid-grey, and translucent UI on mid-grey reads muddy. Push for
high contrast cinematicin the prompt. - Loop seam still visible after 3 regens. Set up two
VideoStreamPlayersiblings and crossfade between them with aTweenon a 0.5s overlap. Costs an extra GPU decode but hides the seam.
Without Summer Engine
In a session without Summer Engine tools (the assets profile; thesummer-assets skill has the whole loop), do steps 1-5 and stop when the seam passes. Skip steps 6-7 (the VideoStreamPlayer and its audio). Save the file where the person asked with out (the summer-assets skill says how), and tell them the path and format. The file is MP4; tell the person to play it looped and muted.
Fallback (no MCP)
If the MCP server isn’t running, route the user to the Summer dashboard:- Image tab → generate the reference still (the loop’s “neutral frame”).
- Video tab → image-to-video with
ltx, duration 5s, aspect ratio per target. - Prompt with the loopable-motion vocabulary above and
"looping, seamless". - Download the result, transcode to
.ogvif needed, place underassets/video/loops/.
Handoff
Once the loop is wired:Looptitle_screen_bgis wired toTitleScreen/BackgroundLoopwith autoplay + loop. Next:
- Score the menu with
music-track— a quiet ambient bed scored to the loop’s mood.- For the logo and menu UI on top, hand off to
ui-graphics.- If the user wants a punchy 5s shot for the trailer using the same look, hand off to
trailer-shot(reuse the reference image).- If the user wants a narrative intro that plays before the title loops, hand off to
cinematic-cutscene.
See also
trailer-shot— punchy marketing footage.cinematic-cutscene— narrative cutscenes with dialogue.music-track— score the menu.ui-graphics— logo, menu buttons, HUD that sits over the loop.concept-art— produce the reference still that anchors the loop.summer_docs_readidreference/mcp-tools-reference— how to callassets.generate_video;summer_searchreturns its exact input.
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
Related skills
asset-strategy: Route any ‘I need a [thing]’ asset request to the right skill: 2D, 3D, audio, video, VFX or animation.
Source:
library/skills/animated-loop/SKILL.md, rendered from summer-engine@4.3.0 on npm.
