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

> ## Agent Instructions
> Reactor hosts multiple models, each with its own connect slug (modelName) and command/event schema. The catalog of every model — slug, typed SDK package, and links to its schema — is at /model-api-reference/overview. Some models expose one slug per experience (e.g. HappyOyster); always take the slug from the model's own pages, never guess it.
> Fastest path to a working app: `npx create-reactor-app my-app --model=<slug>` scaffolds a complete app with secure auth wired up. Typed TypeScript SDKs are published as @reactor-models/<model>; Python uses the base reactor-sdk package.
> Auth: exchange an API key (rk_...) for a JWT via POST https://api.reactor.inc/tokens from your server. Never put the API key in client-side code.
> Append .md to any docs URL for clean Markdown. Search these docs via the MCP server at https://docs.reactor.inc/mcp.

# Visko Orbis Stable overview

> What Visko Orbis Stable is, its key features, and a quick start.

export const ModelRate = ({model}) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(false);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    const ctrl = new AbortController();
    fetch("https://api.reactor.inc/pricing", {
      signal: ctrl.signal
    }).then(r => {
      if (!r.ok) throw new Error(`HTTP ${r.status}`);
      return r.json();
    }).then(json => {
      setData(json);
      setLoading(false);
    }).catch(err => {
      if (err.name === "AbortError") return;
      setError(true);
      setLoading(false);
    });
    return () => ctrl.abort();
  }, []);
  if (loading) {
    return <span aria-label="loading pricing" className="inline-block h-4 w-28 rounded bg-zinc-950/10 dark:bg-white/10 animate-pulse align-middle" />;
  }
  const creditsPerDollar = data?.settings?.credits_per_dollar;
  const amountPerSec = data?.models?.find(m => m.name === model)?.rate?.amount_per_sec;
  const canRender = !error && creditsPerDollar && typeof amountPerSec === "number";
  if (!canRender) {
    return <span className="text-zinc-950/60 dark:text-white/60">see current rate below</span>;
  }
  const perHour = Math.round(amountPerSec / creditsPerDollar * 3600);
  const perSec = (amountPerSec / creditsPerDollar).toFixed(4);
  return <span>
      <strong>${perHour}/hr</strong> (${perSec}/sec)
    </span>;
};

**Visko Orbis** is a real-time steerable video generation model. It produces a continuous stream of
video you can control mid-run by sending a new prompt; the picture morphs into your description at
the next chunk boundary instead of a hard cut. Start a scene from text alone, optionally anchor the
opening frame to a reference image, and let the model generate sound in realtime on a dedicated
audio track.

Visko-Orbis streams in 33-frame chunks (1.833 seconds), every prompt lands at the next chunk
boundary. This model is best for continuous scenes evolving inside one uninterrupted shot,
image-anchored openings that hold composition, and runs that want sound generated from the picture
without a separate sound generator.

The Visko Orbis reference is split across four pages: this overview, the complete
[command and event schema](/model-api-reference/visko-orbis-stable/schema), the
[prompt guide](/model-api-reference/visko-orbis-stable/prompt-guide) for writing prompts the model
renders best, and an end-to-end [tutorial](/model-api-reference/visko-orbis-stable/tutorial) against
the open-source reference frontend.

The base wire protocol is the same as every other Reactor model: open a session with the
[`Reactor`](/sdk-reference/reactor-class) class, send named commands, and receive events. Visko
Orbis has two versions of the same model: **`reactor/visko-orbis-stable`** and
**`reactor/visko-orbis-dynamic`**. See [Typed Model SDKs](/sdk-reference/typed-model-sdk) for more
information.

## At a glance

| Spec           | Value                                                           |
| -------------- | --------------------------------------------------------------- |
| **Model name** | `reactor/visko-orbis-stable` and `visko-orbis-dynamic`          |
| **Pricing**    | <ModelRate model="visko-orbis-stable" />                        |
| **Frame rate** | 18 fps                                                          |
| **Resolution** | 832 × 480 generated; with optional upscaling to 1080p / 2k / 4k |
| **Input**      | Text prompt + optional starting image                           |
| **Audio**      | 48 kHz mono track, chunk-aligned with video                     |

## Key features

<CardGroup cols={3}>
  <Card title="Delivery resolutions up to 4k" icon="scaling">
    Pick a delivery tier at any time — `1080p`, `2k`, or `4k` — and `main_video` upscales the
    832×480 raster the model generates. Render options from `state.available_resolutions`; never
    hard-code.
  </Card>

  <Card title="Image-anchored openings" icon="image">
    Upload a reference image before `start` to anchor generation to your chosen frame.
  </Card>

  <Card title="Picture-driven audio by default" icon="volume-2">
    `main_audio` streams alongside video; the model generates sound from the picture in realtime.
  </Card>
</CardGroup>

Beyond these, steer mid-run by sending a new `prompt`, seed runs for reproducibility, and toggle
sound compute at start time. The
[prompt guide](/model-api-reference/visko-orbis-stable/prompt-guide) covers how to write the
continuous takes that make the morph read as cinematography.

## Quick start

The fastest path to a working Visko Orbis Stable app is the `create-reactor-app` CLI, which
scaffolds the reference frontend into a runnable project. You can also clone the
[reference frontend](https://github.com/reactor-team/js-sdk/tree/main/examples/visko-orbis-stable)
itself, or follow the [tutorial](/model-api-reference/visko-orbis-stable/tutorial) for a guided
walkthrough.

<Tabs>
  <Tab title="npm">
    ```shell theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
    npx create-reactor-app my-visko-app --model=visko-orbis-stable
    ```
  </Tab>

  <Tab title="pnpm">
    ```shell theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
    pnpm create reactor-app my-visko-app --model=visko-orbis-stable
    ```
  </Tab>
</Tabs>

Working in Python instead? The CLI is JavaScript-only, so install the SDK with
`pip install reactor-sdk` and follow the Python example below (see the [quickstart](/quickstart) for
the full walkthrough):

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
  import { Reactor } from "@reactor-team/js-sdk";

  const video = document.querySelector("video")!;
  const reactor = new Reactor({ modelName: "reactor/visko-orbis-stable" });

  // Render frames as soon as they arrive.
  reactor.on("trackReceived", (name, track, stream) => {
    if (name !== "main_video") return;
    video.srcObject = stream;
    void video.play();
  });

  // Once the session is ready, set a prompt and start.
  reactor.on("statusChanged", async (status) => {
    if (status !== "ready") return;
    await reactor.sendCommand("set_prompt", {
      prompt:
        "A dramatic coastline of black volcanic cliffs at golden hour, huge dark waves rolling in from a blood-orange sea and exploding into white foam against the rocks. Cinematic slow aerial motion, a single unbroken take.",
    });
    await reactor.sendCommand("start", {});
  });

  const jwt = await getToken(); // token minted on your server
  await reactor.connect(jwt);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
  import asyncio
  import os
  from reactor_sdk import Reactor, ReactorStatus

  async def main():
      reactor = Reactor(model_name="reactor/visko-orbis-stable",
                        api_key=os.environ["REACTOR_API_KEY"])

      # Once the session is ready, set a prompt and start.
      @reactor.on_status(ReactorStatus.READY)
      async def on_ready(status):
          # Frames arrive as (H, W, 3) uint8 RGB NumPy arrays.
          output = reactor.tracks.with_direction("recvonly").with_kind("video").one()

          @output.on_frame
          def on_frame(frame):
              print(f"Frame: {frame.shape}")

          await reactor.send_command("set_prompt", {
              "prompt": "A dramatic coastline of black volcanic cliffs at golden hour, huge dark waves rolling in from a blood-orange sea. Cinematic slow aerial motion, a single unbroken take.",
          })
          await reactor.send_command("start", {})

      await reactor.connect()
      await asyncio.Event().wait()  # run until interrupted

  asyncio.run(main())
  ```
</CodeGroup>

The above JS example uses the base SDK. The typed SDK, `@reactor-models/visko-orbis-stable`, gives
you named methods and React hooks, which is discussed in the
[tutorial](/model-api-reference/visko-orbis-stable/tutorial).

To learn more about Reactor's typed SDK's, see [Typed Model SDKs](/sdk-reference/typed-model-sdk).

## How it works

On connect the model is live but idle; it won't produce frames until it has a prompt and you call
`start`. To get your first stream:

1. **Connect** to the model. The connection moves `disconnected → connecting → waiting → ready`.
2. **Optionally set a reference image** with
   [`set_image`](/model-api-reference/visko-orbis-stable/schema#commands).
3. **Set a prompt** with [`set_prompt`](/model-api-reference/visko-orbis-stable/schema#commands).
4. **Start** generation. `start` will fail with a `command_error` until a prompt is set.
5. **Steer mid-run** by calling `set_prompt` again. The picture morphs at the next chunk boundary
   (\~1.8 s) without restarting. Every steering command applies at the next chunk boundary.
6. **Pause / resume / reset.** `generation_complete` (or `pause`) returns the session to `WAITING`.
   The model does NOT auto-restart, so call `start` again with the same conditions, or `reset` to
   clear the prompt and image.
