# Free Image to Video: Elixir SDK

Free image to video AI with no daily cap: start with no sign-up, keep going on a free account. Every video comes with sound and no watermark. This is the official Elixir SDK for [Free Image to Video](https://freeimagetovideo.ai/?utm_source=hex&utm_medium=package): turn a prompt or a photo into a video clip from Elixir.

```elixir
{:ok, url} = FreeImageToVideo.generate_video("a paper lantern drifting over a night river")

{:ok, url} =
  FreeImageToVideo.generate_video("the camera slowly orbits the statue",
    image_url: "https://example.com/statue.jpg",
    options: %{"duration" => 6, "aspect_ratio" => "9:16"})
```

Each call submits the run, waits for it and returns the URL of the finished clip. With `image_url:` you [animate a photo](https://freeimagetovideo.ai/video/animate-photo-ai): it becomes the first frame. Without it, it is [free text to video AI](https://freeimagetovideo.ai/video/free-text-to-video-ai) from the prompt alone.

## Install

```elixir
def deps do
  [{:freeimagetovideo, "~> 0.1"}]
end
```

Elixir 1.18+. No dependencies: `:httpc` from OTP and the standard `JSON` module.

## API key and plans

Create a key at [freeimagetovideo.ai/settings/apikeys](https://freeimagetovideo.ai/settings/apikeys) and set `FREEIMAGETOVIDEO_API_KEY` (or pass `api_key:`). API runs need a paid plan: each run draws on the plan's full-speed allowance, then waits in the relaxed queue. See [pricing](https://freeimagetovideo.ai/pricing). To make clips without a key, use the generator on [freeimagetovideo.ai](https://freeimagetovideo.ai/?utm_source=hex&utm_medium=package): start with no sign-up, keep going on a free account.

## Options

| option | values |
|---|---|
| `"duration"` | 4, 5, 6, 8, 10, 15 (seconds) |
| `"resolution"` | `480p` (default), `768p` |
| `"aspect_ratio"` | `16:9` (default), `9:16`, `1:1` |

Model: MiniMax H3 (`minimax-h3`). Every clip comes with sound.

## Lower level

```elixir
{:ok, id}   = FreeImageToVideo.submit("a koi pond in the rain")
{:ok, run}  = FreeImageToVideo.status(id)   # run["status"]: pending | processing | success | failed | canceled
{:ok, url}  = FreeImageToVideo.wait(id)     # polls every 10 s, gives up after 30 minutes
{:ok, left} = FreeImageToVideo.credits()
```

## Errors

Failures are `{:error, reason, message}`: `:auth` (no key or a wrong one), `:quota` (not enough credits), `:plan` (API runs need a paid plan), `:busy` (too many runs at once), `:rejected` (the content filter refused the prompt, or a cooldown is active), `:generation` (the run failed or was canceled), `:timeout` (still generating; check later) and `:api` (anything else).

MIT licensed.
