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

# Media

> MCP tools for Sound & Music, Cast & World, and retrievable media assets on one analysis.

Call-specific media packages and the asset list. Prefer these over `get_report(fields=[...])` when you only need sound, cast, or downloadable media.

Parent: [Connector API](/agents/connector-api). All three are **`mcp:read`**, free.

***

## `get_sound`

Read the Sound & Music package of one analysis you own — free, read-only, call-specific: music segments and cuts (mood, genre, BPM, instruments, timing), the SFX palette (event count, top types, density, isolated-clip count), voice mode, and the sound-design recreation recipe. Byte-capped by the server; never the full analysis dump. Audio media (music cuts, isolated SFX clips, stems) is served by `list_assets(job_id)`.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`. Annotation title: *Read an analysis' Sound & Music package (free)*.

**Byte budget:** package hard cap **`sound-v1` ≤ 4,608 B**. Measured worst compact package ≈ **4,341 B**; hosted delivery of a rich job was \~8.9 KB wire / \~7.8 KB tool text.

### Parameters

| Name     | Type   | Allowed / notes | Default  |
| -------- | ------ | --------------- | -------- |
| `job_id` | string | Analysis id     | required |

### Example call

```text theme={null}
get_sound("712621631268")
```

### Example response (trimmed — real package shape)

```json theme={null}
{
  "job_id": "712621631268",
  "owned": true,
  "title": "Worst sound job",
  "sound": {
    "schema": "sound-v1",
    "available": true,
    "audio": {
      "duration_seconds": 510.6,
      "speech_pct": 100.0,
      "silence_pct": 0.0,
      "has_music": true
    },
    "voice_mode": "mixed",
    "music": {
      "segment_count": 23,
      "segments": [
        {
          "start": "0:00",
          "end": "0:16",
          "mood": "tense",
          "genre": "electronic",
          "bpm": 100,
          "instruments": ["synth pads", "synth arpeggios", "rhythmic pulses"],
          "role": "intro"
        }
      ],
      "cut_count": 23,
      "cuts": [
        {
          "i": 0,
          "a": "0:00",
          "b": "0:16",
          "mood": "tense",
          "genre": "electronic",
          "seconds": 16.0,
          "bpm": 100
        }
      ],
      "includes_vocals": null
    },
    "sfx": {
      "total_events": 273,
      "top_types": [
        { "type": "UI-click", "count": 150 },
        { "type": "digital glitch/artifact", "count": 70 }
      ],
      "density": "dense",
      "dominant_purpose": "emphasis",
      "isolated_clips": 200
    },
    "recipe": "The video's audio features a dynamic mix of cinematic orchestral…",
    "signature_moves": [
      "Frequent UI clicks and digital glitches punctuate every key point and visual transition."
    ]
  },
  "media_note": "Audio media (music cuts, isolated SFX clips, stems) is served by list_assets(job_id)."
}
```

*(Segments/cuts arrays truncated in this doc — full response is larger within budget.)*

Honest empty (no sound package on the job):

```json theme={null}
{ "schema": "sound-v1", "available": false }
```

(wrapped under `sound` in the tool response). Incomplete analysis returns status + note to re-call.

***

## `get_cast`

Read the Cast & World package of one analysis you own — free, read-only, call-specific: characters (name, type, role, description, screen time), environments (name, type, mood, description), key objects, plus overall visual style, color palette, and production notes. Byte-capped; never the full analysis dump. Cast and location stills are served by `list_assets(job_id)`.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`. Annotation title: *Read an analysis' Cast & World package (free)*.

**Byte budget:** package hard cap **`cast-v1` ≤ 6,656 B**. Measured live: **6,004 B wire / 4,425 B compact** on a real founder job (vs \~31 KB for `get_report(fields=["cast"])` baseline).

### Parameters

| Name     | Type   | Allowed / notes | Default  |
| -------- | ------ | --------------- | -------- |
| `job_id` | string | Analysis id     | required |

### Example call

```text theme={null}
get_cast("bf5c393ddfd1")
```

### Example response (trimmed — real package shape)

```json theme={null}
{
  "job_id": "bf5c393ddfd1",
  "owned": true,
  "title": "Worst cast job",
  "cast": {
    "schema": "cast-v1",
    "available": true,
    "characters": [
      {
        "name": "Person in dark clothing",
        "type": "human",
        "role": "background",
        "description": "A person wearing dark, possibly black, hooded clothing…",
        "screen_time_pct": 2.0,
        "appearances": 1
      }
    ],
    "environments": [
      {
        "name": "White studio background",
        "type": "abstract",
        "mood": "clean",
        "description": "A clean, minimalist white background, often used for product shots or text overlays."
      }
    ],
    "objects": [
      {
        "name": "Sunscreen bottle",
        "category": "product",
        "significance": "medium",
        "description": "A white plastic squeeze bottle with a green label…"
      }
    ],
    "counts": { "characters": 11, "environments": 10, "objects": 7 },
    "visual_style": "The video features a mix of clean, minimalist motion graphics…",
    "color_palette": ["#FFFFFF", "#…"],
    "production_notes": "Requires a mix of motion graphics…"
  },
  "media_note": "Cast and environment stills (person/environment assets) are served by list_assets(job_id)."
}
```

*(Character / environment / object arrays truncated in this doc.)*

No normalized generation `elements` / recreation prompts in this package — those lived in the old field-sliced report dump and are intentionally out of scope here.

***

## `list_assets`

List the media assets of one analysis you own — free, read-only, paged. Each row is one retrievable asset: `key`, `kind` (`cut`, `cast`, `look`, `music`, `sfx`, `frame`, …), `title`, `url`, and duration when known. URLs are presigned and **short-lived (\~15 minutes)**: fetch promptly, never store. Pages are **byte-capped**, so a page can hold fewer rows than `limit` when signed URLs are long — follow `next_offset` while `has_more` is true.

**Charges:** read-only, 0 credits. **Scope:** `mcp:read`.

### Parameters

| Name     | Type   | Allowed / notes                       | Default                                                              |
| -------- | ------ | ------------------------------------- | -------------------------------------------------------------------- |
| `job_id` | string | Analysis id                           | required                                                             |
| `limit`  | int    | Soft row wish; pages also byte-capped | `25` (max **60** on the tool path consistent with other paged lists) |
| `offset` | int    | ≥ 0                                   | `0`                                                                  |

### Example call

```text theme={null}
list_assets("EXAMPLE_JOB_ID", limit=25, offset=0)
```

### Example response (shape)

```json theme={null}
{
  "job_id": "EXAMPLE_JOB_ID",
  "assets": [
    {
      "key": "cut-003",
      "kind": "cut",
      "title": "Intimate Static Two-Shot",
      "url": "<signed URL, short-lived ~15 min>",
      "duration_s": 3.8
    }
  ],
  "count": 12,
  "total": 40,
  "limit": 25,
  "offset": 0,
  "has_more": true,
  "next_offset": 12
}
```

***

## When to use which

| Need                                 | Call                                         |
| ------------------------------------ | -------------------------------------------- |
| Music / SFX / recipe only            | `get_sound`                                  |
| People, places, objects, world style | `get_cast`                                   |
| Downloadable clip / still URLs       | `list_assets`                                |
| One cut's clip + frames              | `get_cut` (Cuts group)                       |
| Full blueprint / transcript          | `get_report` lean or fields (Analyses group) |
