> ## Documentation Index
> Fetch the complete documentation index at: https://docs.summerengine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to make an animated title screen for your game

> Make an animated title screen with AI: key art with room for the logo and menu, a short video loop with no visible seam, a menu music loop that repeats without a gap, a confirm sound, and the scene that plays it all. Exact CLI, API and MCP steps and what it costs.

The title screen is the first thing every player sees, and they often sit on it for a minute: reading the menu, changing settings, waiting for a friend. A still picture looks unfinished. A video that jumps every five seconds looks broken. The music that stops and starts again is worse. This guide makes the four parts of a title screen that feels alive: key art composed for a logo and a menu, a short video loop from it with no visible seam, a music loop that repeats without a gap, and a confirm sound. Then it wires them into one scene.

## The chain

| Step | Model | Why this model | Cost |
| - | - | - | - |
| 1. Key art | [GPT Image 2.5](https://docs.summerengine.com/api/models/image/gpt-image-2-5.md) `image/gpt-image-2.5` | Real light and faithful composition from a long brief, so the calm areas for the logo and the menu end up where you asked. | \$0.053 |
| 2. Video loop | [Luma Ray 3.2](https://docs.summerengine.com/api/models/video/luma-ray-3-2.md) `video/luma-ray-3.2` | Cinematic video built for silent background loops on menus and title screens, with calm, controlled motion from one picture. | \$1.00 |
| 3. Menu music loop | [Music v2](https://docs.summerengine.com/api/models/music/music-v2.md) `music/music-v2` | Level and menu music in the style of your game, with instrumental loops and a steady structure, priced by the second. | \$0.16 |
| 4. Confirm sound | [Sound Effects v2](https://docs.summerengine.com/api/models/sound/sfx-v2.md) `sound/sfx-v2` | Short UI and pickup sounds from a plain description, priced by the second, so a short sound costs almost nothing. | \$0.003 |
| | | **Total** | **\$1.216** |

**\$1.216 for the whole chain**, at each model's list price:

* Key art: \$0.053 (\$0.053 per image)
* Video loop: \$1.00 (\$0.20 per second)
* Menu music loop: \$0.16 (\$0.0025 per second)
* Confirm sound: \$0.003 (\$0.002 per second)

A failed job costs nothing. Before you run anything, price each step exactly and for free: `summer api estimate <model> --input '<json>'`, or `POST /v1/estimate` with the same body as the job. Prices come from [`GET /v1/models`](https://docs.summerengine.com/api/reference/get-models) and change only when the provider's price does.

## Before you start

Sign in once, so your agent or your terminal can run jobs on your Summer account:

```bash theme={null}
npx -y summer-engine@latest login
```

Your browser opens the Summer sign-in. Pick a spend limit for this computer and choose **Allow**. Using a coding agent? Paste this guide's URL and say "make my title screen"; the [quickstart for your agent](https://docs.summerengine.com/api/agents.md) connects it in one command.

Have your logo ready as a transparent PNG. The [logo and vector art](https://docs.summerengine.com/api/guides/logo-and-vector-art.md) guide makes one. Then sketch the screen in one line: where the logo goes, where the menu goes, what in the scene can move.

## Step 1: key art made for a title screen

Title screen key art is not a poster. Half of it will be covered by a logo and a menu, so plan the empty spaces first.

* **Leave calm areas, and say where.** "The upper middle is calm soft sky with little detail, for a logo. The lower left is darker and calm, for menu buttons." Busy detail behind text makes both hard to read.
* **Put the light away from the menu.** The lantern sits in the right third; the menu sits in the darker lower left. White buttons read on dark, quiet ground.
* **Pick things that can move forever.** Fog, flame, fireflies, water, leaves, clouds, grass. These are the motions that loop. A character in a pose that must change, or a door, does not.
* **No text, no logo, no letters.** The logo is a separate layer, so you can change it, translate it and animate it.
* **High contrast.** Video models drift toward grey. Start with deep shadows and a bright light, and there is room to lose a little.

`width` and `height` ask for a picture at least 1920 by 1080, so it holds up full screen. Set `aspectRatio` to the screen the menu fills: `16:9` for desktop and TV. For a phone in portrait, make a second key art at `9:16`: the clip follows the shape of its picture.

```bash CLI theme={null}
npx -y summer-engine@latest api run image/gpt-image-2.5 \
  --input '{"prompt":"Wide painted title screen background for a cozy fantasy adventure game: a quiet forest hollow at dusk, an old mossy stump with a glowing lantern in the right third, soft fog lying low between dark tree trunks, a few fireflies, a small stream in the foreground catching the lantern light. The upper middle of the picture is calm soft sky and fog with little detail, as space for a logo. The lower left is darker and calm, as space for menu buttons. Painterly stylized look, warm orange lantern light against deep blue and green shadows, high contrast. Wide shot at eye level, no characters, no text, no logo, no letters.","aspectRatio":"16:9","width":1920,"height":1080,"title":"Title screen key art"}' \
  --download .
```

```bash curl theme={null}
curl https://www.summerengine.com/v1/jobs \
  -H "Authorization: Bearer $SUMMER_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Prefer: wait=60" \
  -d '{"model":"image/gpt-image-2.5","input":{"prompt":"Wide painted title screen background for a cozy fantasy adventure game: a quiet forest hollow at dusk, an old mossy stump with a glowing lantern in the right third, soft fog lying low between dark tree trunks, a few fireflies, a small stream in the foreground catching the lantern light. The upper middle of the picture is calm soft sky and fog with little detail, as space for a logo. The lower left is darker and calm, as space for menu buttons. Painterly stylized look, warm orange lantern light against deep blue and green shadows, high contrast. Wide shot at eye level, no characters, no text, no logo, no letters.","aspectRatio":"16:9","width":1920,"height":1080,"title":"Title screen key art"}}'
```

```ts TypeScript theme={null}
const res = await fetch("https://www.summerengine.com/v1/jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUMMER_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
    Prefer: "wait=60",
  },
  body: JSON.stringify({
    "model": "image/gpt-image-2.5",
    "input": {
      "prompt": "Wide painted title screen background for a cozy fantasy adventure game: a quiet forest hollow at dusk, an old mossy stump with a glowing lantern in the right third, soft fog lying low between dark tree trunks, a few fireflies, a small stream in the foreground catching the lantern light. The upper middle of the picture is calm soft sky and fog with little detail, as space for a logo. The lower left is darker and calm, as space for menu buttons. Painterly stylized look, warm orange lantern light against deep blue and green shadows, high contrast. Wide shot at eye level, no characters, no text, no logo, no letters.",
      "aspectRatio": "16:9",
      "width": 1920,
      "height": 1080,
      "title": "Title screen key art"
    }
  }),
});
const { job } = await res.json();
console.log(job.state, job.id);
```

```python Python theme={null}
import os, uuid, requests

res = requests.post(
    "https://www.summerengine.com/v1/jobs",
    headers={
        "Authorization": f"Bearer {os.environ['SUMMER_TOKEN']}",
        "Idempotency-Key": str(uuid.uuid4()),
        "Prefer": "wait=60",
    },
    json={"model": "image/gpt-image-2.5", "input": {"prompt": "Wide painted title screen background for a cozy fantasy adventure game: a quiet forest hollow at dusk, an old mossy stump with a glowing lantern in the right third, soft fog lying low between dark tree trunks, a few fireflies, a small stream in the foreground catching the lantern light. The upper middle of the picture is calm soft sky and fog with little detail, as space for a logo. The lower left is darker and calm, as space for menu buttons. Painterly stylized look, warm orange lantern light against deep blue and green shadows, high contrast. Wide shot at eye level, no characters, no text, no logo, no letters.", "aspectRatio": "16:9", "width": 1920, "height": 1080, "title": "Title screen key art"}},
)
job = res.json()["job"]
print(job["state"], job["id"])
```

```js MCP theme={null}
// Summer's MCP server: npx -y summer-engine@latest setup <agent> --yes
summer_api_run({
  model: "image/gpt-image-2.5",
  input: {
    prompt: "Wide painted title screen background for a cozy fantasy adventure game: a quiet forest hollow at dusk, an old mossy stump with a glowing lantern in the right third, soft fog lying low between dark tree trunks, a few fireflies, a small stream in the foreground catching the lantern light. The upper middle of the picture is calm soft sky and fog with little detail, as space for a logo. The lower left is darker and calm, as space for menu buttons. Painterly stylized look, warm orange lantern light against deep blue and green shadows, high contrast. Wide shot at eye level, no characters, no text, no logo, no letters.",
    aspectRatio: "16:9",
    width: 1920,
    height: 1080,
    title: "Title screen key art"
  },
  out: "assets",
})
```

Look at it with your logo laid over it before you animate it. A key art costs \$0.053 per image and a video costs many times more, so get the picture right here. The same picture, without text, is also your store key art; the [`store-art`](https://docs.summerengine.com/skills/store-art) skill lists every store slot.

## Step 2: a short loop with no visible seam

Send the key art's `fileUrl` as `imageUrl`: the picture becomes the first frame. [Luma Ray 3.2](https://docs.summerengine.com/api/models/video/luma-ray-3-2.md) is the model for this step. It is made for cinematic camera work and silent background loops for menus, at \$0.20 per second.

Video jobs on the Summer API take one picture, the first frame. There is no end-frame field, so you cannot pin the last frame to the first. You win the loop three ways instead: in the prompt, in the choice of motion, and with one short ffmpeg command after.

**In the prompt.** Ambient motion only. Words that loop: drift, flicker, float, blink, ripple, sway, pulse, glow, shimmer. Words that do not: walks, enters, opens, appears, transforms, falls. Add "the camera stays locked off", "constant lighting" and "nothing enters or leaves the frame". Put the opposite in `negativePrompt`: camera movement, zoom, people, lighting change, fade to black.

**Short is better.** Five seconds is enough. The longer a clip runs, the further it drifts from the first frame, and the harder the seam.

```bash CLI theme={null}
npx -y summer-engine@latest api run video/luma-ray-3.2 \
  --input '{"prompt":"The camera stays locked off. Fog drifts slowly between the trunks, the lantern flame flickers gently, fireflies float and blink, the stream ripples softly. Slow, continuous, ambient motion that could loop, constant lighting, nothing enters or leaves the frame.","imageUrl":"<fileUrl of key art>","duration":5,"negativePrompt":"camera movement, zoom, people, animals, sudden movement, lighting change, fade to black, text"}' \
  --download .
```

```bash curl theme={null}
curl https://www.summerengine.com/v1/jobs \
  -H "Authorization: Bearer $SUMMER_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Prefer: wait=60" \
  -d '{"model":"video/luma-ray-3.2","input":{"prompt":"The camera stays locked off. Fog drifts slowly between the trunks, the lantern flame flickers gently, fireflies float and blink, the stream ripples softly. Slow, continuous, ambient motion that could loop, constant lighting, nothing enters or leaves the frame.","imageUrl":"<fileUrl of key art>","duration":5,"negativePrompt":"camera movement, zoom, people, animals, sudden movement, lighting change, fade to black, text"}}'
```

```ts TypeScript theme={null}
const res = await fetch("https://www.summerengine.com/v1/jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUMMER_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
    Prefer: "wait=60",
  },
  body: JSON.stringify({
    "model": "video/luma-ray-3.2",
    "input": {
      "prompt": "The camera stays locked off. Fog drifts slowly between the trunks, the lantern flame flickers gently, fireflies float and blink, the stream ripples softly. Slow, continuous, ambient motion that could loop, constant lighting, nothing enters or leaves the frame.",
      "imageUrl": "<fileUrl of key art>",
      "duration": 5,
      "negativePrompt": "camera movement, zoom, people, animals, sudden movement, lighting change, fade to black, text"
    }
  }),
});
const { job } = await res.json();
console.log(job.state, job.id);
```

```python Python theme={null}
import os, uuid, requests

res = requests.post(
    "https://www.summerengine.com/v1/jobs",
    headers={
        "Authorization": f"Bearer {os.environ['SUMMER_TOKEN']}",
        "Idempotency-Key": str(uuid.uuid4()),
        "Prefer": "wait=60",
    },
    json={"model": "video/luma-ray-3.2", "input": {"prompt": "The camera stays locked off. Fog drifts slowly between the trunks, the lantern flame flickers gently, fireflies float and blink, the stream ripples softly. Slow, continuous, ambient motion that could loop, constant lighting, nothing enters or leaves the frame.", "imageUrl": "<fileUrl of key art>", "duration": 5, "negativePrompt": "camera movement, zoom, people, animals, sudden movement, lighting change, fade to black, text"}},
)
job = res.json()["job"]
print(job["state"], job["id"])
```

```js MCP theme={null}
// Summer's MCP server: npx -y summer-engine@latest setup <agent> --yes
summer_api_run({
  model: "video/luma-ray-3.2",
  input: {
    prompt: "The camera stays locked off. Fog drifts slowly between the trunks, the lantern flame flickers gently, fireflies float and blink, the stream ripples softly. Slow, continuous, ambient motion that could loop, constant lighting, nothing enters or leaves the frame.",
    imageUrl: "<fileUrl of key art>",
    duration: 5,
    negativePrompt: "camera movement, zoom, people, animals, sudden movement, lighting change, fade to black, text"
  },
  out: "assets",
})
// It answers `next` while the job runs: follow it to the end.
summer_api_job({ jobId: "<jobId>", wait: true, out: "assets" })
```

A video job takes a minute or more. The CLI follows it and saves the MP4; over HTTP the call answers `running`, and you read `GET /v1/jobs/{id}` until `state` is `done` ([jobs](https://docs.summerengine.com/api/jobs.md)).

Play it on repeat and watch only the moment it restarts. If you see a jump, fix it with one of these. Both drop the sound track (`-an`): a title loop plays muted.

**A crossfade loop**, for fire, fog, water and particles. It blends the last second into the first, so the clip ends exactly where it begins. For a 5 second clip, `offset` is 3 (the length minus 2):

```bash theme={null}
ffmpeg -i title_loop.mp4 -filter_complex "[0:v]split[a][b];[a]trim=0:1,setpts=PTS-STARTPTS[head];[b]trim=1,setpts=PTS-STARTPTS[body];[body][head]xfade=transition=fade:duration=1:offset=3[v]" -map "[v]" -an title_loop_seamless.mp4
```

**A ping-pong loop**, for a gentle camera move or a slow sway. The clip plays forward, then backward, so the end always meets the start. A very slow push-in becomes a slow breath in and out, which looks deliberate. Do not use it on fire, rain, falling leaves or flowing water: backward motion shows.

```bash theme={null}
ffmpeg -i title_loop.mp4 -filter_complex "[0:v]split[f][b];[b]reverse[r];[f][r]concat=n=2:v=1:a=0[v]" -map "[v]" -an title_loop_pingpong.mp4
```

For a ping-pong loop, ask for the camera move in the prompt: "a very slow, gentle push in toward the lantern, steady and smooth", and leave camera movement out of `negativePrompt`.

**Other models for this step.** [Veo 3.1 Lite](https://docs.summerengine.com/api/models/video/veo3-1-lite.md) makes cheap ambient loop drafts for menus and loading screens (\$0.05 per second). [MiniMax H3 Max Turbo](https://docs.summerengine.com/api/models/video/minimax-h3-max-turbo.md) is the low-cost way to try many takes (\$0.026 per second). [Kling 3.0 Standard](https://docs.summerengine.com/api/models/video/kling-3.md) is the default video model, with fluid motion (\$0.14 per second). [Vidu Q4](https://docs.summerengine.com/api/models/video/vidu-q4.md) gives smooth, steady motion from one frame, good for idle loops. Draft three takes on a cheap model, then run the best prompt on the final one.

## Step 3: menu music that loops without a gap

A menu track loops for as long as the player sits there. Two things make it loop well: music written to loop, and a length that is a whole number of bars.

* **Ask for a loop in words.** "No intro build, no fade-in, no fade-out, no ending, the last bar leads straight back into the first."
* **Fix the tempo and the meter.** "90 bpm, 4/4, steady tempo, one key throughout." A track that speeds up or changes key cannot loop.
* **Pick the length in bars.** One bar of 4/4 is 240 divided by the tempo, in seconds. At 90 bpm a bar is 2.67 seconds, so 64 seconds is exactly 24 bars. A loop point on a bar line is a loop point the ear accepts.
* **Instrumental, calm, not too busy.** The player reads menus over it. Save the big theme for the trailer.

```bash CLI theme={null}
npx -y summer-engine@latest api run music/music-v2 \
  --input '{"prompt":"Calm title screen music for a cozy fantasy adventure game: warm fingerpicked acoustic guitar, a soft wooden flute melody, light hand percussion, gentle low strings. 90 bpm, 4/4, steady tempo, one key throughout. Instrumental, no vocals. Made to loop: no intro build, no fade-in, no fade-out, no ending, the last bar leads straight back into the first.","durationSeconds":64}' \
  --download .
```

```bash curl theme={null}
curl https://www.summerengine.com/v1/jobs \
  -H "Authorization: Bearer $SUMMER_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Prefer: wait=60" \
  -d '{"model":"music/music-v2","input":{"prompt":"Calm title screen music for a cozy fantasy adventure game: warm fingerpicked acoustic guitar, a soft wooden flute melody, light hand percussion, gentle low strings. 90 bpm, 4/4, steady tempo, one key throughout. Instrumental, no vocals. Made to loop: no intro build, no fade-in, no fade-out, no ending, the last bar leads straight back into the first.","durationSeconds":64}}'
```

```ts TypeScript theme={null}
const res = await fetch("https://www.summerengine.com/v1/jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUMMER_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
    Prefer: "wait=60",
  },
  body: JSON.stringify({
    "model": "music/music-v2",
    "input": {
      "prompt": "Calm title screen music for a cozy fantasy adventure game: warm fingerpicked acoustic guitar, a soft wooden flute melody, light hand percussion, gentle low strings. 90 bpm, 4/4, steady tempo, one key throughout. Instrumental, no vocals. Made to loop: no intro build, no fade-in, no fade-out, no ending, the last bar leads straight back into the first.",
      "durationSeconds": 64
    }
  }),
});
const { job } = await res.json();
console.log(job.state, job.id);
```

```python Python theme={null}
import os, uuid, requests

res = requests.post(
    "https://www.summerengine.com/v1/jobs",
    headers={
        "Authorization": f"Bearer {os.environ['SUMMER_TOKEN']}",
        "Idempotency-Key": str(uuid.uuid4()),
        "Prefer": "wait=60",
    },
    json={"model": "music/music-v2", "input": {"prompt": "Calm title screen music for a cozy fantasy adventure game: warm fingerpicked acoustic guitar, a soft wooden flute melody, light hand percussion, gentle low strings. 90 bpm, 4/4, steady tempo, one key throughout. Instrumental, no vocals. Made to loop: no intro build, no fade-in, no fade-out, no ending, the last bar leads straight back into the first.", "durationSeconds": 64}},
)
job = res.json()["job"]
print(job["state"], job["id"])
```

```js MCP theme={null}
// Summer's MCP server: npx -y summer-engine@latest setup <agent> --yes
summer_api_run({
  model: "music/music-v2",
  input: {
    prompt: "Calm title screen music for a cozy fantasy adventure game: warm fingerpicked acoustic guitar, a soft wooden flute melody, light hand percussion, gentle low strings. 90 bpm, 4/4, steady tempo, one key throughout. Instrumental, no vocals. Made to loop: no intro build, no fade-in, no fade-out, no ending, the last bar leads straight back into the first.",
    durationSeconds: 64
  },
  out: "assets",
})
```

The file is an MP3. MP3 files carry a short silence at the start from the encoder, which you hear as a tick or a gap at every loop. For a gapless loop, cut it to the bar length and convert it to Ogg Vorbis:

```bash theme={null}
ffmpeg -i menu.mp3 -t 64 -c:a libvorbis -q:a 6 menu.ogg
```

Listen across the loop point three times. If the end still trails off, ask again with more weight on "no ending", or cut at an earlier bar line. Music costs \$0.0025 per second, so two or three takes are cheap. The [`music-track`](https://docs.summerengine.com/skills/music-track) skill has more prompts for menu, level and boss music.

## Step 4: a confirm sound

The first sound the player makes in your game is pressing Start. Give it a short, clean sound that fits the music: soft and warm for a cozy game, a heavy hit for an action game.

```bash CLI theme={null}
npx -y summer-engine@latest api run sound/sfx-v2 \
  --input '{"text":"soft magical chime with a warm airy whoosh, game menu confirm sound, bright, short, clean ending","durationSeconds":1.5}' \
  --download .
```

```bash curl theme={null}
curl https://www.summerengine.com/v1/jobs \
  -H "Authorization: Bearer $SUMMER_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Prefer: wait=60" \
  -d '{"model":"sound/sfx-v2","input":{"text":"soft magical chime with a warm airy whoosh, game menu confirm sound, bright, short, clean ending","durationSeconds":1.5}}'
```

```ts TypeScript theme={null}
const res = await fetch("https://www.summerengine.com/v1/jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUMMER_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
    Prefer: "wait=60",
  },
  body: JSON.stringify({
    "model": "sound/sfx-v2",
    "input": {
      "text": "soft magical chime with a warm airy whoosh, game menu confirm sound, bright, short, clean ending",
      "durationSeconds": 1.5
    }
  }),
});
const { job } = await res.json();
console.log(job.state, job.id);
```

```python Python theme={null}
import os, uuid, requests

res = requests.post(
    "https://www.summerengine.com/v1/jobs",
    headers={
        "Authorization": f"Bearer {os.environ['SUMMER_TOKEN']}",
        "Idempotency-Key": str(uuid.uuid4()),
        "Prefer": "wait=60",
    },
    json={"model": "sound/sfx-v2", "input": {"text": "soft magical chime with a warm airy whoosh, game menu confirm sound, bright, short, clean ending", "durationSeconds": 1.5}},
)
job = res.json()["job"]
print(job["state"], job["id"])
```

```js MCP theme={null}
// Summer's MCP server: npx -y summer-engine@latest setup <agent> --yes
summer_api_run({
  model: "sound/sfx-v2",
  input: {
    text: "soft magical chime with a warm airy whoosh, game menu confirm sound, bright, short, clean ending",
    durationSeconds: 1.5
  },
  out: "assets",
})
```

A gentle ambience bed under the music, such as night crickets and a far stream, is one more sound job with `loop: true` and about 20 seconds. The [`sound-effect`](https://docs.summerengine.com/skills/sound-effect) skill covers UI sounds and ambience.

## Put it in your game

**Summer Engine.** Import the clip by its `assetId` or from its `fileUrl`. Summer Engine plays video as Ogg Theora (`.ogv`), and the import converts the MP4 for you: load the `.ogv` path the import answer names. If you made a seamless or ping-pong file with ffmpeg, import that file the same way.

Build the scene in layers, back to front: the key art as a `TextureRect` (it shows while the video starts), the `VideoStreamPlayer` filling the screen, the logo, then the menu. Later children draw on top.

```gdscript theme={null}
extends Control

@onready var loop_player: VideoStreamPlayer = $BackgroundLoop
@onready var music: AudioStreamPlayer = $Music
@onready var confirm: AudioStreamPlayer = $ConfirmSound

func _ready() -> void:
    loop_player.stream = load("res://assets/title/title_loop.ogv")
    loop_player.expand = true
    loop_player.loop = true
    loop_player.volume_db = -80.0  # the loop plays muted; the music is its own player
    loop_player.play()

    var track: AudioStreamOggVorbis = load("res://assets/title/menu.ogg")
    track.loop = true
    music.stream = track
    music.play()

    $Menu/Play.grab_focus()

func _on_play_pressed() -> void:
    confirm.play()
    var fade := create_tween()
    fade.tween_property(music, "volume_db", -40.0, 0.6)
    await fade.finished
    get_tree().change_scene_to_file("res://levels/level_01.tscn")
```

Set the `BackgroundLoop` anchors to full rect so it fills any window. The [`animated-loop`](https://docs.summerengine.com/skills/animated-loop) skill makes and wires the loop for you inside a project, and [`ui-graphics`](https://docs.summerengine.com/skills/ui-graphics) makes the buttons and panels in your style.

**Any other engine.** Play the MP4 in a full-screen video player set to loop and mute, under your UI layer. On a web page, use `<video autoplay loop muted playsinline>`. Loop the Ogg music on its own audio player.

**Keep it light.** A five-second ambient loop compresses well. Export it at 720p for mobile and web builds, and keep the key art as a still fallback for low-end devices.

## Make one for every season

Once the title screen works, the chain is a template. A winter version, a Halloween version or a version per update is the same four jobs with a new key art prompt and the same loop and music prompts. Send the key arts as one batch, check them, then the loops as another:

```bash theme={null}
npx -y summer-engine@latest api run --batch title-keyart.jsonl --download art/title
```

A batch takes up to 500 jobs, is priced when it arrives and runs all or none, so you know the total before anything starts ([batches](https://docs.summerengine.com/api/jobs.md#run-many-jobs-batches)).

## Common problems

| You see | Do this |
| - | - |
| A jump every time the video restarts | Make a crossfade loop with the ffmpeg command, or a ping-pong loop for camera moves |
| The camera drifts and never comes back | Add "the camera stays locked off" and put camera movement in `negativePrompt` |
| Something walks in or out of frame | Ambient verbs only; add "nothing enters or leaves the frame" |
| The light changes during the clip | Add "constant lighting" and "lighting change" in `negativePrompt` |
| The clip is the wrong shape for a phone | Make a 9:16 key art; the clip follows the shape of its picture |
| The menu text is hard to read | Ask for a darker, calm area where the menu goes, and keep the light away from it |
| A tick or gap when the music loops | Cut to a whole number of bars and convert to Ogg Vorbis |
| The music fades out at the end | Add "no fade-out, no ending, the last bar leads straight back into the first" |
| The video sound plays over the music | Mute the video player, or drop the track with `-an` in ffmpeg |

## Questions

**Can I animate my own key art?** Yes. Upload it ([send a picture](https://docs.summerengine.com/api/jobs.md#send-a-picture)) and start at step 2 with its `fileUrl`. Make sure it has the calm areas for the logo and menu.

**Can the loop be longer than five seconds?** Yes: you can ask for up to 20 seconds, and each model renders its nearest supported length. But a longer clip drifts further from its first frame and the seam is harder to hide. Five seconds with a crossfade looks the same to a player and costs less.

**Can I use all of it in a commercial game?** Yes. Every model on the Summer API allows commercial use of what it makes.

**Do I need a plan?** No. Jobs are paid from your paid Summer credits, your plan's credits or a top-up. Each connected agent has its own spend limit in Settings > Connected apps.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.