|
2 | 2 | title: Video Generation |
3 | 3 | id: video-generation |
4 | 4 | order: 6 |
5 | | -description: "Generate video from text prompts with OpenAI Sora, Google Veo, xAI Grok Imagine, or fal.ai using TanStack AI's experimental generateVideo() jobs/polling API." |
| 5 | +description: "Generate video from text prompts with OpenAI Sora, Google Veo, Gemini Omni Flash, xAI Grok Imagine, or fal.ai using TanStack AI's experimental generateVideo() jobs/polling API." |
6 | 6 | keywords: |
7 | 7 | - tanstack ai |
8 | 8 | - video generation |
9 | 9 | - sora |
10 | 10 | - veo |
| 11 | + - omni flash |
| 12 | + - interactions api |
11 | 13 | - gemini |
12 | 14 | - grok imagine |
13 | 15 | - fal |
@@ -40,7 +42,7 @@ TanStack AI provides experimental support for video generation through dedicated |
40 | 42 |
|
41 | 43 | Currently supported: |
42 | 44 | - **OpenAI**: Sora-2 and Sora-2-Pro models (when available) |
43 | | -- **Google Gemini**: Veo 3.1, Veo 3, and Veo 2 models (via the long-running operations API) |
| 45 | +- **Google Gemini**: Veo 3.1 models (via the long-running operations API), and Gemini Omni Flash (via the Interactions API) |
44 | 46 | - **Grok (xAI)**: grok-imagine-video (text-to-video + image-to-video) and grok-imagine-video-1.5 (image-to-video only) models |
45 | 47 | - **fal.ai**: MiniMax, Luma, Kling, Hunyuan, and other hosted video models |
46 | 48 |
|
@@ -569,6 +571,85 @@ Adapters that haven't declared a per-model duration map keep the plain |
569 | 571 | > Files API and requires your API key to download (send it as an |
570 | 572 | > `x-goog-api-key` header or `key` query parameter). |
571 | 573 |
|
| 574 | +### Gemini Omni Flash (Interactions API) Model Options |
| 575 | + |
| 576 | +Gemini Omni Flash (`gemini-omni-flash-preview`) is Google's multimodal |
| 577 | +video-generation model with conversational editing. It only serves the |
| 578 | +[Interactions API](https://ai.google.dev/gemini-api/docs/omni) — the same |
| 579 | +`geminiVideo()` adapter routes it automatically: `generateVideo` creates a |
| 580 | +background interaction, `getVideoJobStatus` polls it by id, and the |
| 581 | +finished clip comes back **inline as a `data:video/mp4;base64,…` URL** |
| 582 | +(when Google delivers by reference instead, the Files API URI passes |
| 583 | +through and needs your API key to download, like Veo). |
| 584 | + |
| 585 | +Clips are 720p at 24 FPS, and `duration` accepts any value in the **3–10 |
| 586 | +second** range (fractional seconds included), defaulting to 10 seconds when |
| 587 | +omitted. `availableDurations()` reports |
| 588 | +`{ kind: 'range', min: 3, max: 10, unit: 'seconds' }`; out-of-range |
| 589 | +`duration` values are rejected at job creation, and `snapDuration(n)` snaps |
| 590 | +raw seconds into the range (clamping to its bounds and rounding to whole |
| 591 | +seconds). The `size` option maps onto the interaction's output aspect |
| 592 | +ratio: |
| 593 | + |
| 594 | +```typescript ignore |
| 595 | +import { generateVideo, getVideoJobStatus } from '@tanstack/ai' |
| 596 | +import { geminiVideo } from '@tanstack/ai-gemini' |
| 597 | + |
| 598 | +const adapter = geminiVideo('gemini-omni-flash-preview') |
| 599 | + |
| 600 | +const { jobId } = await generateVideo({ |
| 601 | + adapter, |
| 602 | + prompt: 'A woman playing violin outdoors at golden hour', |
| 603 | + size: '9:16', // aspect ratio: '16:9' (default) or '9:16' |
| 604 | + duration: 6, // 3-10 seconds; omit for the 10s default |
| 605 | +}) |
| 606 | + |
| 607 | +const status = await getVideoJobStatus({ adapter, jobId }) |
| 608 | +// status.url → 'data:video/mp4;base64,…' once completed |
| 609 | +``` |
| 610 | + |
| 611 | +Image and video prompt parts are sent to the interaction as content blocks |
| 612 | +— grouped as images, then videos, then the text prompt (Omni doesn't use |
| 613 | +Veo's `metadata.role` routing) — so you can condition the generation on |
| 614 | +stills or short reference clips. `data` sources |
| 615 | +are sent inline as base64; `url` sources pass through as-is — the adapter |
| 616 | +never downloads them, so use Gemini Files API URIs (upload large media via |
| 617 | +the Files API first). |
| 618 | + |
| 619 | +#### Conversational video editing |
| 620 | + |
| 621 | +Omni's headline capability is iterative refinement: pass the interaction id |
| 622 | +of a prior generation (its `jobId`) as |
| 623 | +`modelOptions.previous_interaction_id` and describe the change — the model |
| 624 | +edits the video while preserving everything you didn't mention: |
| 625 | + |
| 626 | +```typescript ignore |
| 627 | +import { generateVideo } from '@tanstack/ai' |
| 628 | +import { geminiVideo } from '@tanstack/ai-gemini' |
| 629 | + |
| 630 | +const adapter = geminiVideo('gemini-omni-flash-preview') |
| 631 | + |
| 632 | +// Turn 1: generate |
| 633 | +const first = await generateVideo({ |
| 634 | + adapter, |
| 635 | + prompt: 'A woman playing violin outdoors at golden hour', |
| 636 | +}) |
| 637 | + |
| 638 | +// …poll first.jobId to completion, then… |
| 639 | + |
| 640 | +// Turn 2: edit the result conversationally |
| 641 | +const second = await generateVideo({ |
| 642 | + adapter, |
| 643 | + prompt: 'Make the violin invisible', |
| 644 | + modelOptions: { previous_interaction_id: first.jobId }, |
| 645 | +}) |
| 646 | +``` |
| 647 | + |
| 648 | +`modelOptions` also passes through the Interactions API's request fields |
| 649 | +(e.g. `generation_config.video_config.task` to pin |
| 650 | +`'text_to_video' | 'image_to_video' | 'reference_to_video' | 'edit'` |
| 651 | +instead of letting the model infer the task mode). |
| 652 | + |
572 | 653 | ### Grok (xAI Imagine) Model Options |
573 | 654 |
|
574 | 655 | Based on the [xAI video generation API](https://docs.x.ai/docs/guides/video-generations). Two models are available: `grok-imagine-video` (v1.0) supports **text-to-video and image-to-video**, while `grok-imagine-video-1.5` is **image-to-video only** (a text-only prompt is rejected by the API; the adapter throws a clear error pointing you at `grok-imagine-video`). Both are aspect-ratio sized — the generic `size` option takes an `aspectRatio_resolution` template (like the Grok Imagine image models), and clips can be 1–15 seconds long. |
|
0 commit comments