# Generate media from JavaScript

Generate images, videos, voices, music and sound effects with any catalog model from Block code, paid with StillMade credits after one approval.

A JavaScript Block can generate images and videos with any model in the shared
catalog (the same models the app's own Canvas and Image Panels use), speech in
any catalog voice, music and sound effects by returning a declared
`media.generate` action. Declare it in the manifest:

```json
"permissions": {"project": [], "actions": ["media.generate"], "network": [], "filesystem": [], "secrets": []},
"outputs": {"request": {"type": "json"}, "media": {"type": "asset[]"}}
```

Return the action from your code. Each item is an `image`, `video`, `speech`,
`music` or `sfx` item with a prompt and optional `settings`. Image and video
items may also set `references` (images), `firstFrame`/`lastFrame` (video),
`negativePrompt` and `seed`. Audio items take only `settings`:

- `speech`: the prompt is the text to speak (up to 3,800 characters);
  `settings: {voice, speed}` with a catalog voice id and a speed from 0.25 to 4.
- `music`: `settings: {durationSec}`, 5 to 240 whole seconds (default 30).
- `sfx`: `settings: {durationSec}`, 0.5 to 22 seconds in tenths (default 4).

```js
return {request: {
  schemaVersion: 1, kind: "stillmade.media-action", operation: "media.generate",
  resultPort: "media",
  request: {items: [
    {key: "hero", operation: "image", prompt: input.prompt,
     settings: {model: "nano-banana-pro", aspectRatio: "16:9", resolution: "2K"},
     references: input.styleImages},
    {key: "clip", operation: "video", prompt: "Slow push in on the harbor",
     settings: {model: "kling-v3-turbo", duration: 5, aspectRatio: "16:9"}},
    {key: "intro", operation: "speech", prompt: "Welcome back to the show.",
     settings: {voice: "adam", speed: 1}},
    {key: "bed", operation: "music", prompt: "Warm lo-fi piano", settings: {durationSec: 30}},
    {key: "whoosh", operation: "sfx", prompt: "A fast whoosh", settings: {durationSec: 1.5}}
  ]}
}};
```

StillMade turns every item into one exact generation request and asks the server
for one maximum price for the whole batch, using StillMade's own prices. The user
sees that maximum and approves it once; credits are reserved before any provider
call, each call is settled from provider evidence, and unused credits are
returned when the batch closes. The approval is bound to this Block's exact
content digest, so changed code needs a new approval. A Block cannot name a
price, a provider, a key or another Block. References and frames must be images
saved in the user's own library. Up to 50 items per action.

When it finishes, the declared `resultPort` receives an array of
`{key, kind, assetId, versionId, url}` in item order (`kind` is `image`,
`video` or `audio`); failed items are listed
separately and are not charged beyond what the provider actually received.
