Skip to content

Commit 87f6f67

Browse files
authored
Merge branch 'main' into worktree-resilient-popping-knuth
2 parents b040cbd + 888e8b7 commit 87f6f67

15 files changed

Lines changed: 327 additions & 157 deletions

File tree

.changeset/seedance-2-5.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@tanstack/ai-byteplus': patch
3+
---
4+
5+
Add first-class Seedance 2.5 support (`dreamina-seedance-2-5-260628`).
6+
7+
The model is fully open on ModelArk with documented capabilities: 4–30s
8+
duration (or `-1`), 480p/720p only, multimodal reference media including
9+
audio-only input, first-and-last-frame mode, `priority`, `generate_audio`, and
10+
`output_format` (`mp4` | `mov`). The video adapter, typed model tables, unit
11+
tests, docs, and Seedance Studio example catalog all treat it as a known
12+
model rather than an escape-hatch string.

docs/adapters/byteplus.md

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -321,42 +321,52 @@ Seedance options are model-specific, and **Ark rejects an inapplicable field wit
321321

322322
| Option | Models that accept it |
323323
| --- | --- |
324-
| `service_tier` (`'default'` \| `'flex'`) | Seedance 1.x only — the 2.0 family rejects it |
324+
| `service_tier` (`'default'` \| `'flex'`) | Seedance 1.x only — Seedance 2.5 and the 2.0 family reject it |
325325
| `camera_fixed` | Seedance 1.x only |
326326
| `frames` (fractional-second output, `25 + 4n` in `[29, 289]`) | `seedance-1-0-pro-250528`, `seedance-1-0-pro-fast-251015` |
327327
| `draft` (cheap low-fidelity preview) | `seedance-1-5-pro-251215` only |
328-
| `priority` (`0``9`) | the `dreamina-seedance-2-0-*` family only |
329-
| `duration: -1` (model picks the length) | Seedance 2.0 and `seedance-1-5-pro-251215` |
328+
| `priority` (`0``9`) | Seedance 2.5 and the `dreamina-seedance-2-0-*` family |
329+
| `duration: -1` (model picks the length) | Seedance 2.5, 2.0 and `seedance-1-5-pro-251215` |
330+
| `output_format` (`'mp4'` \| `'mov'`) | Seedance 2.5 (default `mp4`) |
330331
| `seed`, `watermark`, `generate_audio`, `return_last_frame`, `callback_url` | every model |
331332

332-
`watermark` defaults to `false` for video (the opposite of Seedream images). `generate_audio` is accepted everywhere but only Seedance 2.0 and 1.5-pro actually produce an audio track.
333+
`watermark` defaults to `false` for video (the opposite of Seedream images). `generate_audio` is accepted everywhere but only Seedance 2.5, 2.0 and 1.5-pro actually produce an audio track.
333334

334-
Resolutions are per model too, and the shipped table comes from live probes rather than the published docs: there is **no 2K tier on any Seedance model**, `4k` exists only on `dreamina-seedance-2-0-260128`, and `seedance-1-0-pro-fast-251015` does accept `1080p` despite being documented as 480p/720p only. An unsupported combination is caught locally with a clear error before the request goes out.
335+
Resolutions are per model too: there is **no 2K tier on any Seedance model**, `4k` exists only on `dreamina-seedance-2-0-260128`, Seedance 2.5 is **480p/720p only**, and `seedance-1-0-pro-fast-251015` does accept `1080p` despite older prose listing it as 480p/720p only. An unsupported combination is caught locally with a clear error before the request goes out.
335336

336-
Reference media follows the shared [role hints](../media/video-generation#role-hints)`start_frame`, `end_frame` and `reference`. The Seedance 2.0 family takes full multimodal references (reference images, video and audio); the 1.x models take start/end frames only, and `seedance-1-0-pro-fast-251015` takes a start frame only.
337+
Reference media follows the shared [role hints](../media/video-generation#role-hints)`start_frame`, `end_frame` and `reference`. Seedance 2.5 and the 2.0 family take full multimodal references (reference images, video and audio); Seedance 2.5 additionally accepts **audio-only** reference input and up to 30 reference images / 10 videos / 10 audio clips (2.0 is 9 / 3 / 3). The 1.x models take start/end frames only, and `seedance-1-0-pro-fast-251015` takes a start frame only.
337338

338339
### Seedance 2.5
339340

340-
Seedance 2.5 was announced on 2026-07-31, initially on BytePlus's consumer surfaces. Its Ark id — `dreamina-seedance-2-5-260628` — is real and reachable, but it is **activation-gated per account**: until the model is switched on in the Ark Console, Ark answers `404 ModelNotOpen`.
341-
342-
Because its capabilities could not be probed from a non-activated account, 2.5 is **deliberately absent from the typed model tables** above. It is still usable today — `byteplusVideo()`'s model parameter accepts any string, so an id BytePlus publishes after this release works without upgrading the package:
341+
Seedance 2.5 (`dreamina-seedance-2-5-260628`) is a first-class model in this package. It is the current multimodal flagship for longer clips (up to **30 seconds**), audio-only reference input, and `output_format: 'mov'`. Like the 2.0 series it may still require model activation / a resource pack in the Ark Console before the account can call it (`404 ModelNotOpen` until then).
343342

344343
```typescript
345344
import { generateVideo } from '@tanstack/ai'
346345
import { byteplusVideo } from '@tanstack/ai-byteplus'
347346

348-
// Activate Seedance 2.5 in the Ark Console first, or this 404s.
349347
const { jobId } = await generateVideo({
350348
adapter: byteplusVideo('dreamina-seedance-2-5-260628'),
351349
prompt: 'a guitar being played in a store',
352350
size: '16:9_720p',
353-
duration: 5,
351+
duration: 10,
352+
modelOptions: {
353+
generate_audio: true,
354+
priority: 5,
355+
output_format: 'mp4',
356+
},
354357
})
355358
```
356359

357-
An unknown id relaxes both halves of the adapter: `size` widens to any string, provider options are ungated, and the local runtime guards that encode per-model capabilities — resolution tiers, closing-frame and reference-media support, frame cardinality and mode exclusivity, duration snapping — stand down so Ark validates the request instead. Known ids keep their probe-verified narrowing. Typed narrowing for 2.5 follows in a package update once its capabilities can be verified.
360+
| Capability | Seedance 2.5 |
361+
| --- | --- |
362+
| Duration | 4–30s, or `-1` (model chooses; required for video-editing tasks) |
363+
| Resolution | `480p`, `720p` (default `720p`) — no 1080p / 4k |
364+
| Reference media | images 1–30, videos 0–10, audio 0–10; **audio-only allowed** |
365+
| First + last frame | yes |
366+
| `priority` / `generate_audio` | yes |
367+
| `service_tier` / `camera_fixed` / `frames` / `draft` | no |
358368

359-
The quickest way to try a newly-released id is the [Seedance Studio example](https://github.com/TanStack/ai/tree/main/examples/ts-react-media): its **Advanced: custom model id** field (placeholder `dreamina-seedance-2-5-260628`) takes an arbitrary id, switches the studio into unknown-model mode with every option enabled, and spells the activation caveat out in the UI — so a `ModelNotOpen` response reads as expected rather than broken.
369+
`byteplusVideo()` still accepts any string for ids BytePlus ships between package releases. An unknown id relaxes local guards so Ark validates the request; known ids (including 2.5) keep their documented narrowing.
360370

361371
### Seedance here vs. Seedance via fal
362372

@@ -495,7 +505,7 @@ Audio can be a `File`, base64, a data URL or a public URL, up to two hours and 1
495505
## Supported models
496506

497507
- **Chat**`dola-seed-2-1-turbo-260628`, `seed-2-0-lite-260428`, `seed-2-0-mini-260428`, `seed-2-0-pro-260328`, `seed-2-0-lite-260228`, `seed-2-0-mini-260215`, `seed-2-0-code-preview-260328`, `seed-1-8-251228`, `seed-1-6-250915`, `seed-1-6-250615`, `seed-1-6-flash-250715`, `seed-1-6-flash-250615`, `glm-5-2-260617`, `glm-4-7-251222`, `deepseek-v4-pro-260425`, `deepseek-v4-flash-260425`, `deepseek-v3-2-251201`, `gpt-oss-120b-250805`.
498-
- **Video**`dreamina-seedance-2-0-260128`, `dreamina-seedance-2-0-fast-260128`, `dreamina-seedance-2-0-mini-260615`, `seedance-1-5-pro-251215`, `seedance-1-0-pro-250528`, `seedance-1-0-pro-fast-251015`. (Seedance 2.5, `dreamina-seedance-2-5-260628`, is untyped-but-usable pending account activation — see [Seedance 2.5](#seedance-25).)
508+
- **Video**`dreamina-seedance-2-5-260628`, `dreamina-seedance-2-0-260128`, `dreamina-seedance-2-0-fast-260128`, `dreamina-seedance-2-0-mini-260615`, `seedance-1-5-pro-251215`, `seedance-1-0-pro-250528`, `seedance-1-0-pro-fast-251015`.
499509
- **Image**`dola-seedream-5-0-pro-260628`, `seedream-5-0-260128`, `seedream-5-0-lite-260128`, `seedream-4-5-251128`, `seedream-4-0-250828`.
500510
- **Speech**`seed-audio-1.0` (TTS) and `seed-asr` (transcription).
501511

docs/config.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@
442442
"label": "Video Generation",
443443
"to": "media/video-generation",
444444
"addedAt": "2026-04-15",
445-
"updatedAt": "2026-08-04"
445+
"updatedAt": "2026-08-07"
446446
},
447447
{
448448
"label": "Generation Hooks",
@@ -869,7 +869,8 @@
869869
{
870870
"label": "BytePlus",
871871
"to": "adapters/byteplus",
872-
"addedAt": "2026-08-04"
872+
"addedAt": "2026-08-04",
873+
"updatedAt": "2026-08-07"
873874
}
874875
]
875876
},

docs/media/video-generation.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ await generateVideo({
392392
| **OpenAI** | Sora-2 / Sora-2-Pro → the image part goes to `input_reference`; flattened text is the prompt. Single image only — throws if more than one. |
393393
| **fal.ai** | Field names resolve per endpoint from a map generated from the fal SDK's endpoint types — e.g. `role: 'start_frame'` lands on `image_url` for Kling/Veo image-to-video, `first_frame_url` for first-last-frame endpoints, and `start_image_url` otherwise. Defaults: single input → `image_url` (start frame); `role: 'end_frame'``end_image_url`; `role: 'reference'` / `'character'``reference_image_urls`. Override per-endpoint via `modelOptions` — the media-conditioning fields are typed optional there (even when the endpoint requires them) since they usually arrive as prompt parts. |
394394
| **Gemini** | Veo → the first un-roled / `'start_frame'` image becomes the input image; `'end_frame'``lastFrame`; `'reference'` / `'character'``referenceImages` (asset references, Veo 3.1). Throws on multiple starting images. |
395-
| **BytePlus** | Seedance → a single un-roled or `'start_frame'` image becomes `first_frame`; `'end_frame'``last_frame` (needs a first frame alongside it, and is rejected by `seedance-1-0-pro-fast-251015`); `'reference'` / `'character'``reference_image`, video parts → `reference_video`, audio parts → `reference_audio` (Seedance 2.0 family only). Frame roles and reference roles are mutually exclusive modes — mixing them throws. |
395+
| **BytePlus** | Seedance → a single un-roled or `'start_frame'` image becomes `first_frame`; `'end_frame'``last_frame` (needs a first frame alongside it, and is rejected by `seedance-1-0-pro-fast-251015`); `'reference'` / `'character'``reference_image`, video parts → `reference_video`, audio parts → `reference_audio` (Seedance 2.5 and 2.0 family; 2.5 also accepts audio-only reference input). Frame roles and reference roles are mutually exclusive modes — mixing them throws. |
396396

397397
Adapters whose underlying API can't accept image inputs throw a clear
398398
runtime error so calls fail fast.
@@ -739,7 +739,7 @@ Generated clips include an audio track. When the job completes, the adapter repo
739739

740740
#### BytePlus (Seedance) Model Options
741741

742-
Seedance is aspect-ratio sized like Grok Imagine — `size` takes a `ratio` or `ratio_resolution` template. Ratios are `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, `21:9` and `adaptive`; resolutions are `480p`, `720p`, `1080p` and (on `dreamina-seedance-2-0-260128` only) `4k`. There is no 2K tier on any Seedance model:
742+
Seedance is aspect-ratio sized like Grok Imagine — `size` takes a `ratio` or `ratio_resolution` template. Ratios are `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, `21:9` and `adaptive`; resolutions are `480p`, `720p`, `1080p` and (on `dreamina-seedance-2-0-260128` only) `4k`. Seedance 2.5 (`dreamina-seedance-2-5-260628`) is 480p/720p only and runs up to 30 seconds. There is no 2K tier on any Seedance model:
743743

744744
```typescript
745745
import { generateVideo } from '@tanstack/ai'
@@ -753,12 +753,12 @@ const { jobId } = await generateVideo({
753753
modelOptions: {
754754
seed: 42,
755755
generate_audio: true,
756-
priority: 5, // Seedance 2.0 family only — queue priority, 0-9
756+
priority: 5, // Seedance 2.5 / 2.0 family — queue priority, 0-9
757757
},
758758
})
759759
```
760760

761-
Options are **model-specific and validated server-side**: Ark rejects an inapplicable field with a `400` instead of ignoring it. `service_tier` and `camera_fixed` are Seedance 1.x only, `frames` works on the 1.0-pro models, `draft` on 1.5-pro, `priority` on the 2.0 family, and `duration: -1` (let the model choose) on 2.0 and 1.5-pro. Durations are 4–15s on the 2.0 family, 4–12s on 1.5-pro and 2–12s on the 1.0-pro models.
761+
Options are **model-specific and validated server-side**: Ark rejects an inapplicable field with a `400` instead of ignoring it. `service_tier` and `camera_fixed` are Seedance 1.x only, `frames` works on the 1.0-pro models, `draft` on 1.5-pro, `priority` on Seedance 2.5 and the 2.0 family, and `duration: -1` (let the model choose) on 2.5, 2.0 and 1.5-pro. Durations are 4–30s on Seedance 2.5, 4–15s on the 2.0 family, 4–12s on 1.5-pro and 2–12s on the 1.0-pro models.
762762

763763
**Seedance video URLs expire 24 hours after the task completes** (the task record is kept for seven days), so persist the bytes rather than the link. See the [BytePlus adapter](../adapters/byteplus#video-generation-seedance) for the full option table.
764764

examples/ts-react-media/src/components/SeedanceStudio.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -870,9 +870,8 @@ export default function SeedanceStudio({
870870
<p className="text-xs text-amber-200/90">
871871
Capabilities unverified — every option below is enabled and
872872
the API validates the request, because the adapter switches
873-
its per-model guards off for an id it has no table for.
874-
Seedance 2.5 additionally requires activation in the Ark
875-
Console; without it the task returns 404{' '}
873+
its per-model guards off for an id it has no table for. A
874+
model that is not activated on your Ark account returns 404{' '}
876875
<code className="text-amber-300">ModelNotOpen</code>.
877876
</p>
878877
</div>
@@ -1110,7 +1109,7 @@ export default function SeedanceStudio({
11101109
</div>
11111110

11121111
{entry.extras.priority && (
1113-
<Control label="Queue priority" hint="0-9, Seedance 2.0 family only">
1112+
<Control label="Queue priority" hint="0-9, Seedance 2.5 / 2.0 family">
11141113
<div className="flex items-center gap-3">
11151114
<input
11161115
type="range"

examples/ts-react-media/src/lib/seedance.ts

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,21 @@ import type {
2222
export interface SeedanceExtras {
2323
/**
2424
* `generate_audio` — accepted by every model at the validation layer, but
25-
* only the Seedance 2.0 family and 1.5-pro actually produce an audio track.
25+
* only Seedance 2.5, the 2.0 family and 1.5-pro actually produce an audio
26+
* track.
2627
*/
2728
generateAudio: boolean
28-
/** `camera_fixed` — Seedance 1.x only; the 2.0 family rejects it. */
29+
/** `camera_fixed` — Seedance 1.x only; the 2.x family rejects it. */
2930
cameraFixed: boolean
30-
/** `service_tier: 'flex'` — Seedance 1.x only (no offline tier on 2.0). */
31+
/** `service_tier: 'flex'` — Seedance 1.x only (no offline tier on 2.x). */
3132
serviceTier: boolean
3233
/** `frames` — Seedance 1.0-pro and 1.0-pro-fast only. */
3334
frames: boolean
3435
/** `draft` — Seedance 1.5-pro only. */
3536
draft: boolean
36-
/** `priority` (0-9) — Seedance 2.0 family only. */
37+
/** `priority` (0-9) — Seedance 2.5 and the 2.0 family. */
3738
priority: boolean
38-
/** `duration: -1` (model picks the length) — Seedance 2.0 and 1.5-pro. */
39+
/** `duration: -1` (model picks the length) — Seedance 2.5, 2.0 and 1.5-pro. */
3940
autoDuration: boolean
4041
}
4142

@@ -50,16 +51,30 @@ export interface SeedanceModelEntry {
5051
type AssertNever<T extends never> = T
5152

5253
/**
53-
* The six Seedance models, with the option applicability probed live against
54-
* Ark on 2026-07-31 and documented on `BytePlusVideoProviderOptions`. Ark 400s
55-
* on an inapplicable field rather than ignoring it, so these flags decide what
56-
* the studio is allowed to send — not just what it renders.
54+
* The Seedance models, with option applicability from
55+
* `BytePlusVideoProviderOptions` (2.0/1.x live-probed; 2.5 from ModelArk
56+
* docs). Ark 400s on an inapplicable field rather than ignoring it, so these
57+
* flags decide what the studio is allowed to send — not just what it renders.
5758
*/
5859
export const SEEDANCE_MODELS = [
60+
{
61+
id: 'dreamina-seedance-2-5-260628',
62+
name: 'Seedance 2.5',
63+
blurb: 'Current multimodal flagship — up to 30s, audio-only references',
64+
extras: {
65+
generateAudio: true,
66+
cameraFixed: false,
67+
serviceTier: false,
68+
frames: false,
69+
draft: false,
70+
priority: true,
71+
autoDuration: true,
72+
},
73+
},
5974
{
6075
id: 'dreamina-seedance-2-0-260128',
6176
name: 'Seedance 2.0',
62-
blurb: 'Flagship — the only Seedance model with a 4k tier',
77+
blurb: '2.0 flagship — the only Seedance model with a 4k tier',
6378
extras: {
6479
generateAudio: true,
6580
cameraFixed: false,
@@ -143,10 +158,10 @@ export const SEEDANCE_MODELS = [
143158
] as const satisfies ReadonlyArray<SeedanceModelEntry>
144159

145160
/**
146-
* Compile-time link between this catalog and the package's model list: a
147-
* seventh model shipping in `@tanstack/ai-byteplus` fails the example's build
148-
* here — naming the id it is missing — instead of silently going absent from
149-
* the picker with no capability copy or option policy.
161+
* Compile-time link between this catalog and the package's model list: a new
162+
* model shipping in `@tanstack/ai-byteplus` fails the example's build here —
163+
* naming the id it is missing — instead of silently going absent from the
164+
* picker with no capability copy or option policy.
150165
*/
151166
export type SeedanceCatalogCoversEveryModel = AssertNever<
152167
Exclude<BytePlusVideoModel, (typeof SEEDANCE_MODELS)[number]['id']>
@@ -182,14 +197,11 @@ export interface SeedanceCapability {
182197
}
183198

184199
/**
185-
* Placeholder for the advanced custom-id field: the real Seedance 2.5 id.
186-
*
187-
* The June date suffix is the whole reason it needs typing out — guessing ids
188-
* around the 2026-07-31 announcement never landed on it. The id is reachable
189-
* but activation-gated: an account that has not enabled it in the Ark Console
190-
* gets 404 `ModelNotOpen`.
200+
* Placeholder for the advanced custom-id field when trying an id this package
201+
* has not catalogued yet. Known models (including Seedance 2.5) live in the
202+
* picker above.
191203
*/
192-
export const SEEDANCE_CUSTOM_MODEL_PLACEHOLDER = 'dreamina-seedance-2-5-260628'
204+
export const SEEDANCE_CUSTOM_MODEL_PLACEHOLDER = 'dreamina-seedance-…-yymmdd'
193205

194206
/**
195207
* Option applicability for an id the package has no table for: everything on.
@@ -234,7 +246,7 @@ export interface SeedanceJobOptions {
234246
* unknown model's template shape before handing the values to Ark.
235247
*/
236248
size?: string
237-
/** Whole seconds, or `-1` to let the model choose (2.0 / 1.5-pro only). */
249+
/** Whole seconds, or `-1` to let the model choose (2.5 / 2.0 / 1.5-pro). */
238250
duration?: number
239251
/** Frame count instead of seconds; wins over `duration` server-side. */
240252
frames?: number

examples/ts-react-media/src/lib/server-functions.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,7 @@ export const getSeedanceCapabilitiesFn = createServerFn({
558558
interface SeedanceRequest {
559559
prompt: MediaPrompt
560560
// Open by design: the studio's advanced field takes an id this package
561-
// has no metadata for (Seedance 2.5 today), which the adapter forwards
562-
// ungated for Ark to judge.
561+
// has no metadata for, which the adapter forwards ungated for Ark to judge.
563562
model: BytePlusVideoModelOrString
564563
options?: SeedanceJobOptions
565564
}

packages/ai-byteplus/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ Result URLs expire after 24 hours; pass `response_format: 'b64_json'` in
166166
- **Chat**`dola-seed-2-1-turbo-260628`, the `seed-2-0-*` family,
167167
`seed-1-8-251228`, the `seed-1-6-*` family, plus `glm-*`, `deepseek-*` and
168168
`gpt-oss-120b-250805`.
169-
- **Video**`dreamina-seedance-2-0-260128` (and `-fast-`/`-mini-`),
169+
- **Video**`dreamina-seedance-2-5-260628`,
170+
`dreamina-seedance-2-0-260128` (and `-fast-`/`-mini-`),
170171
`seedance-1-5-pro-251215`, `seedance-1-0-pro-250528`,
171172
`seedance-1-0-pro-fast-251015`.
172173
- **Image**`dola-seedream-5-0-pro-260628`, `seedream-5-0-260128`,

0 commit comments

Comments
 (0)