Skip to content

feat (video): add first-class frameImages and inputReferences call options for video generation - #16219

Merged
joshualipman123 merged 12 commits into
mainfrom
feat/video-frame-images
Jun 29, 2026
Merged

feat (video): add first-class frameImages and inputReferences call options for video generation#16219
joshualipman123 merged 12 commits into
mainfrom
feat/video-frame-images

Conversation

@joshualipman123

Copy link
Copy Markdown
Contributor

Summary

This PR implements first-class, provider-agnostic media inputs for video generation. Today, last-frame and multi-reference images are buried under inconsistent providerOptions keys (klingai.imageTail vs bytedance.lastFrameImage, klingai.elementList vs bytedance.referenceImages). This PR lifts those concepts to top-level call options.

Manual Verification

Manually verified by running examples to check cases like:

  • First-last-frame requests produce videos interpolating between the provided start and end images
  • Reference-to-video requests produce videos incorporating the provided reference images
  • Legacy providerOptions paths (imageTail, lastFrameImage, referenceImages) still work when the new top-level fields are omitted

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/google/src/google-video-model.ts Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feedback from claude -- not sure if it is accurate, take a look?

🔴 Blocking — @ai-sdk/google image wire format is broken (regression)

packages/google/src/google-video-model.ts — the new convertFileToGoogleImage emits the Vertex shape:

return { bytesBase64Encoded: base64Data, mimeType: file.mediaType || 'image/png' };

But @ai-sdk/google targets https://generativelanguage.googleapis.com/v1beta (confirmed in google-provider.ts:152), and the Gemini Developer API requires the inlineData shape — { inlineData: { mimeType, data } } — which is exactly what main produced. bytesBase64Encoded is the Vertex-only field name. The two endpoints genuinely differ on this (Gemini API video docs, Vertex Veo reference).

This breaks three paths on the Google (non-Vertex) provider with a 400 "Unable to process input image":
- instance.image — existing i2v start frame (regression from main's inlineData)
- instance.lastFrame — new feature
- instance.referenceImages legacy path — convertProviderReferenceImage now returns bytesBase64Encoded/gcsUri, where main returned inlineData/gcsUri

The tests don't catch it because they were rewritten to assert the new (wrong) shape — main had it('should send image as inlineData'), the PR replaced it with it('should send image as bytesBase64Encoded'). This is the classic case of updated tests masking a wire-format regression; the "manual verification" in the description most likely exercised Vertex, not the generativelanguage endpoint.

Fix: @ai-sdk/google must keep wrapping inline bytes as { inlineData: { mimeType, data } } (and reference images likewise). google-vertex is correct as-is. The shared helper can't be identical across the two packages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya, got gemini api & vertex mixed up

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another claude thought, wdyt?

🟡 Silent data loss when frameImages + inputReferences are both passed

In generate-video.ts, effectiveInputReferences is set to undefined whenever frameImages is present, and the test should ignore inputReferences when frameImages is provided locks this in — with no warning. Because the core nulls it before doGenerate, the provider-level "inputReferences ignored" warnings can never fire for this combination either. A user who passes both gets their references dropped silently. This should emit a Warning so it surfaces via logWarnings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dropping inputRefs is intentional but ya should warn before doing so.

Comment thread packages/ai/src/generate-video/generate-video.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if below is accurate may be worth a logic edit, take a look and let me know thoughts. I would think we would want the providers to prioritize what we host into prompt.image as well -- is this consistent re: the gist of PR prioritizes in-general-prompt params over provider-options params, or did we go the other direction?

  • image vs first_frame precedence: the core copies first_frame into image only when no prompt image exists, but every provider's resolveStartImage is firstFrame ?? image. So if a caller passes both prompt.image and a frameImages first_frame, the core keeps prompt.image in the image field yet providers use first_frame — prompt.image is silently ignored. Worth a comment documenting the intended precedence, or a warning.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prompt.image and frameImages are both first class. i think it makes sense to keep prioritizing firstFrame as this is the more specific/intentional field. added a warning.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • xai fileToXaiImageUrl builds data:${file.mediaType};base64,...; if mediaType is ever undefined you get data:undefined;base64,. Low risk since type:'file' normally carries it, but a fallback (?? 'image/png') matches the other providers.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

klingai buildMultiImageBody: the start-frame warning uses feature: 'image' while the last-frame warning uses feature: 'frameImages' — slightly inconsistent labeling.

Comment thread packages/ai/src/generate-video/generate-video.ts Outdated
joshualipman123 and others added 2 commits June 26, 2026 16:26
…ntentToUint8Array

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… labeling, handle xai passing data:undefined
@joshualipman123
joshualipman123 merged commit 0274f34 into main Jun 29, 2026
49 checks passed
@joshualipman123
joshualipman123 deleted the feat/video-frame-images branch June 29, 2026 23:02
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Published in:

Package Version
ai 7.0.8 github npm
@ai-sdk/alibaba 2.0.3 github npm
@ai-sdk/amazon-bedrock 5.0.4 github npm
@ai-sdk/angular 3.0.8 github npm
@ai-sdk/anthropic 4.0.3 github npm
@ai-sdk/assemblyai 3.0.2 github npm
@ai-sdk/azure 4.0.4 github npm
@ai-sdk/baseten 2.0.2 github npm
@ai-sdk/black-forest-labs 2.0.2 github npm
@ai-sdk/bytedance 2.0.3 github npm
@ai-sdk/cerebras 3.0.2 github npm
@ai-sdk/cohere 4.0.2 github npm
@ai-sdk/deepgram 3.0.2 github npm
@ai-sdk/deepinfra 3.0.2 github npm
@ai-sdk/deepseek 3.0.2 github npm
@ai-sdk/devtools 1.0.1 github npm
@ai-sdk/elevenlabs 3.0.3 github npm
@ai-sdk/fal 3.0.3 github npm
@ai-sdk/fireworks 3.0.3 github npm
@ai-sdk/gateway 4.0.6 github npm
@ai-sdk/gladia 3.0.2 github npm
@ai-sdk/google 4.0.3 github npm
@ai-sdk/google-vertex 5.0.4 github npm
@ai-sdk/groq 4.0.2 github npm
@ai-sdk/harness 1.0.10 github npm
@ai-sdk/harness-claude-code 1.0.10 github npm
@ai-sdk/harness-codex 1.0.10 github npm
@ai-sdk/harness-deepagents 1.0.9 github npm
@ai-sdk/harness-opencode 1.0.10 github npm
@ai-sdk/harness-pi 1.0.10 github npm
@ai-sdk/huggingface 2.0.2 github npm
@ai-sdk/hume 3.0.2 github npm
@ai-sdk/klingai 4.0.3 github npm
@ai-sdk/langchain 3.0.8 github npm
@ai-sdk/llamaindex 3.0.8 github npm
@ai-sdk/lmnt 3.0.2 github npm
@ai-sdk/luma 3.0.3 github npm
@ai-sdk/mcp 2.0.4 github npm
@ai-sdk/mistral 4.0.2 github npm
@ai-sdk/moonshotai 3.0.4 github npm
@ai-sdk/open-responses 2.0.2 github npm
@ai-sdk/openai 4.0.4 github npm
@ai-sdk/openai-compatible 3.0.2 github npm
@ai-sdk/otel 1.0.8 github npm
@ai-sdk/perplexity 4.0.2 github npm
@ai-sdk/policy-opa 1.0.8 github npm
@ai-sdk/prodia 2.0.3 github npm
@ai-sdk/provider 4.0.1 github npm
@ai-sdk/provider-utils 5.0.2 github npm
@ai-sdk/quiverai 2.0.2 github npm
@ai-sdk/react 4.0.9 github npm
@ai-sdk/replicate 3.0.3 github npm
@ai-sdk/revai 3.0.2 github npm
@ai-sdk/rsc 3.0.8 github npm
@ai-sdk/sandbox-just-bash 1.0.10 github npm
@ai-sdk/sandbox-vercel 1.0.10 github npm
@ai-sdk/svelte 5.0.8 github npm
@ai-sdk/togetherai 3.0.3 github npm
@ai-sdk/tui 1.0.8 github npm
@ai-sdk/valibot 3.0.2 github npm
@ai-sdk/vercel 3.0.2 github npm
@ai-sdk/voyage 2.0.2 github npm
@ai-sdk/vue 4.0.8 github npm
@ai-sdk/workflow 1.0.8 github npm
@ai-sdk/workflow-harness 1.0.10 github npm
@ai-sdk/xai 4.0.3 github npm

joshualipman123 added a commit that referenced this pull request Jun 30, 2026
…es call options for video generation (#16503)

Backport of #16219 to `release-v6.0`.

## Summary

Promotes two image inputs to first-class top-level options on
`experimental_generateVideo`, instead of requiring provider-specific
passthrough:

- **`frameImages`** — role-tagged images (`first_frame` / `last_frame`)
for image-to-video and first-last-frame generation.
- **`inputReferences`** — reference images for reference-to-video (r2v)
generation.

Both are normalized once in core and passed through to providers, with
warnings when they conflict (e.g. `frameImages` + `inputReferences`
supplied together, or a `first_frame` overriding `prompt.image`).

## Backport notes

`release-v6.0` is on the **VideoModelV3** spec, whereas the original PR
targeted **VideoModelV4** on `main`. Adaptations:

- Added `frameImages` / `inputReferences` to the v3 call-options type
and a new `video-model-v3-frame-image.ts` (frame-image / frame-type
definitions). All v4-only files from the PR were dropped (`v4`
call-options, `v4` frame-image, `as-video-model-v4.test.ts`).
- `generate-video.ts` keeps the v3 `satisfies
Experimental_VideoModelV3CallOptions` shape; all `VideoModelV4*` types
swapped to their `V3` equivalents.
- Adapted `normalizeImageData` to v6.0's `detectMediaType({ signatures:
imageMediaTypeSignatures })` API (the PR used main-only `{ topLevelType:
'image' }`).
- The 7 provider implementations (google, google-vertex, alibaba,
bytedance, klingai, xai, gateway) keep `specificationVersion = 'v3'`
with `VideoModelV4` → `VideoModelV3` renames throughout.
- `google-generative-ai-video-model.ts` keeps v6.0's class name
`GoogleGenerativeAIVideoModel` (renamed to `GoogleVideoModel` on main).
- `google-vertex-video-model.ts` keeps v6.0's `vertexOptions` variable
name (renamed to `googleVertexOptions` on main).
- Fixed the back-ported vertex examples + docs to use the v6.0 provider
name `vertex` (the PR used the main-only `googleVertex`).
joshualipman123 added a commit that referenced this pull request Jul 1, 2026
Rebase the branch onto main now that the parent PR (#16219) has landed,
keeping referenceType support while incorporating main's generateAudio
and Google inlineData/GCS URI fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants