# Sequencer

> Build cinematics on a multi-track timeline with cameras, cuts, animation, audio, subtitles, post looks and time of day.

Source: https://feather-engine.com/docs/animation/sequencer/

The Sequencer turns a story cinematic into a multi-track timeline. Tracks key camera rigs and cuts,
object transforms and visibility, animation clips, audio, script events, story actions, subtitles,
post looks, time of day and weather, and nested shots. Sequences play in the editor and in exported
games, and you can scrub them in the viewport without pressing Play.

A sequence is a cinematic: the same item that [Story](/docs/gameplay/story/) uses, with tracks added.

## Create a sequence

1. Open **Window → Story · dialogues, quests, cinematics** and select the **Cinematics** tab.
2. Create a cinematic, or click **New from template** to start from a ready-made camera move.
3. Fly the editor camera to a shot and click **Key from view** to add a camera key at the playhead.
4. Click **+ Track** and choose a track type. Transform, Visibility and Animation tracks target the
   selected object, or the player when nothing is selected.
5. Scrub the timeline to preview. Turn on **Pilot viewport** to look through the cinematic camera while
   you scrub.
6. Select a key on the timeline to edit its values in the inspector. Drag a key to move it.

Keys snap to the sequence's frame rate as you drag them.

## Sequence settings

| Setting | Description | Default |
| --- | --- | --- |
| **Title** | Shown in the editor | New cinematic |
| **Id** | Used by `play_cinematic` and `play_sequence` | — |
| **Duration (s)** | Length; the sequence runs on past it if keys or events are later | 6 |
| **Frames per second** | Key snapping and the frame counter | 30 |
| **Playback speed** | Speed multiplier | 1 |
| **Blend in (s)** | Glide from the gameplay camera into the first shot | 0 |
| **Blend back (s)** | Glide back to the gameplay camera at the end | 0.8 |
| **Loop playback** | Play again until stopped; **Use loop range** limits it to **Loop from** – **Loop to** | Off |
| **Anchor** | An object whose position and heading the camera keys and moves follow. **World space** uses world coordinates | World space |
| **Letterbox** | Black bars during playback | On |
| **Skippable** | The player can skip it | On |
| **Hide HUD** | Hides the HUD during playback | On |
| **On end** | Rhai code run when the sequence ends or is skipped | Empty |

## Tracks

| Track | Keys |
| --- | --- |
| **Camera** | A camera rig: position, look-at target, field of view, depth of field, roll and shake |
| **CameraCuts** | Which Camera track is live from each key, with an optional blend time |
| **Transform** | Position, rotation and scale of a named object, or `player` |
| **Visibility** | Shows or hides a named object |
| **Animation** | Clips a character plays, with looping and a duration |
| **Audio** | Sounds or music with volume, duration and fades |
| **Event** | Sends an event to every script and/or runs a Rhai snippet |
| **Actions** | Story actions such as move, place, fade, shake and starting a dialogue |
| **Subtitles** | Lines with a speaker, text and duration |
| **Post** | Fade to colour, exposure, vignette, saturation, contrast and temperature |
| **Environment** | Time of day and weather changes |
| **Shots** | Other sequences placed on this timeline |

Each track has **Mute** and **Lock**. Muted tracks are skipped by playback; locked tracks cannot be edited
on the timeline, although commands still change them.

### Easing and curves

Camera, Transform, Post and Environment keys set how the value arrives at the key:

| Ease | Behaviour |
| --- | --- |
| Linear | Constant rate |
| Smooth | Eases in and out (default) |
| EaseIn, EaseOut | Accelerates or decelerates |
| Cut | Jumps straight to the key |
| Curve | A custom cubic Bézier `[x1, y1, x2, y2]`, edited in the curve view |

### Camera keys

| Field | Unit | Range | Default |
| --- | --- | --- | --- |
| Position, target | Metres | — | — |
| Field of view | Degrees (vertical) | 5 to 150 | 45 |
| Focus distance | Metres that stay sharp; 0 turns depth of field off | 0 to 10,000 | 0 |
| Aperture | f-stops; smaller blurs more | 0.1 to 64 | — |
| Roll | Degrees | −360 to 360 | 0 |
| Shake | Hand-held amount, 0 is steady | 0 to 10 | 0 |

**Set from view** replaces the selected key with the editor camera.

### Camera blending

A **CameraCuts** key names a Camera track by ID. With a **blend** of 0 it cuts; with a positive blend
(up to 10 s) it blends from the previous camera over that time. Use several Camera tracks and one
CameraCuts track to edit between shots.

### Audio keys

| Field | Description | Default |
| --- | --- | --- |
| Sound | A sound name or cue; see [Audio](/docs/presentation/audio/) | — |
| Volume | Linear, 0 to 2 | 1 |
| Duration | Seconds the sound is held before it stops | 4 |
| Fade in, fade out | Seconds | 0 |
| Music | Shows the key as a music clip | Off |

### Event keys

An Event key emits an event, by default named `cue`, with a JSON data object. The engine adds
`sequence` and `time` to the data. Scripts receive it with `on(name, |data| ...)` or the `on_event`
hook. A key can also run a Rhai snippet.

### Environment keys

**Set time of day** keys an hour from 0 to 24. Hours interpolate forward between keys and wrap past
midnight. A key can also change the weather, over a transition time that defaults to 2 seconds.

### Shots

A Shots key plays another sequence on this timeline, with an offset into it, a duration (0 plays the
rest), a speed and optional looping. Shots nest up to 4 levels deep.

## Templates

**New from template** creates a complete sequence around a point:

| Template | Shot |
| --- | --- |
| `orbit_reveal` | The camera circles the subject once while rising, fading in from black |
| `dolly_push_in` | A slow push towards the subject with a narrowing lens and focus pulled onto it |
| `two_shot_dialogue` | A wide establishing shot and over-the-shoulder shots of two speakers, cut on each line |
| `flyover` | A high sweeping pass over the area, descending gently, with the light warming over time |

Templates use a radius of 6 m and a duration of 8 s unless you set them.

## Play a sequence

| Function | Description |
| --- | --- |
| `play_cinematic(id)`, `play_sequence(id)` | Plays a sequence |
| `stop_cinematic()` | Stops the playing sequence |
| `cinematic_playing()` | Whether a sequence is playing |

The world-script hook `on_cinematic_end(id)` runs when a sequence finishes.

```rust
fn on_key(key) {
    if key == "G" {
        play_sequence("gate_opens");
    }
}

fn on_cinematic_end(id) {
    if id == "gate_opens" {
        print("Back to gameplay");
    }
}
```

## Limits

| Limit | Value |
| --- | --- |
| Tracks per sequence | 64 |
| Keys per track | 1,024 |
| Key times | 0 to 600 s |
| Shot nesting | 4 levels |

## Automate it

| Command | Purpose |
| --- | --- |
| `sequence.get` | Lists sequences and templates, or returns one sequence's tracks |
| `sequence.template` | Creates a sequence from a template |
| `sequence.track_upsert`, `sequence.track_remove` | Creates, replaces or removes a track |
| `sequence.key_upsert`, `sequence.key_remove` | Adds, replaces or removes a key by zero-based index |
| `sequence.sample` | Evaluates a sequence at a time without playing it |

Each edit is one undo step, and invalid references are rejected. Create an orbit around a point, then
check the camera two seconds in:

```bash
feather-cli --connect .feather-session.json command sequence.template \
  --json '{"id":"tower_reveal","template":"orbit_reveal","center":[0,4,0],"radius":10,"duration":8}'

feather-cli --connect .feather-session.json command sequence.sample \
  --json '{"id":"tower_reveal","time":2}'
```

See [Agents & automation](/docs/agents/overview/) for connecting a live session.
