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

# Image Input

> Capture video frames on demand and send them to the LLM with a prompt.

For a snapshot-style "look at this" interaction, capture the most recent frames with
`capture_frames()` and pass them to `session.reply()` with a prompt. The frames and prompt go
to the LLM together. This works in [Cascade](/build/configure-a-pipeline/modes) pipelines and
is the simplest way to add vision.

## Capture and send

<CodeGroup>
  ```python title="main.py" Python theme={null}
  # Capture the two most recent frames and ask the LLM to describe them
  frames = agent.capture_frames(num_of_frames=2)
  if frames:
      await session.reply(
          "Describe what you see in this frame in one sentence.",
          frames=frames,
      )
  ```
</CodeGroup>

`capture_frames()` never raises: it returns an empty list when vision is not active or
no frames have arrived yet, so no exception handling is needed.

## Trigger a capture

A common pattern is to capture when the client sends a [pub/sub](/build/modalities/text/chat)
message, for example, a "capture" button in your app:

<CodeGroup>
  ```python title="main.py" Python theme={null}
  # Inside the agent, e.g. in on_enter:
  async def on_message(message):
      if isinstance(message, dict) and message.get("message") == "capture_frames":
          frames = self.capture_frames(num_of_frames=2)
          if frames:
              await self.session.reply(
                  "Analyze this frame and describe what you see.", frames=frames
              )

  await self.session.subscribe_pubsub(
      "CHAT", lambda m: asyncio.create_task(on_message(m))
  )
  ```
</CodeGroup>

You can also build `ImageContent` directly from PIL images, NumPy arrays, or `av.VideoFrame`s
for fully custom flows.

## Encoding

Before frames reach the model they're encoded with `EncodeOptions`: JPEG by default, resized (default `1024×1024`) and compressed (`quality=75`). Raise these when you need higher fidelity
(for example, to read fine text on camera) at the cost of more tokens and latency.

## References

<Tabs>
  <Tab title="Python">
    #### Examples

    <CardGroup cols={2}>
      <Card title="Vision (Cascade)" icon="github" href="https://github.com/ZeroRuntimeAI/zrt-python-sdk-examples/blob/main/features/vision.py">
        Send images to a cascade agent.
      </Card>
    </CardGroup>
  </Tab>
</Tabs>
