neal lee

Aug 11, 2026 • 9 min read

Seedance 2.5 has a minimum billing window. Six published prices give away the number.

Seedance 2.5 charges 40% less per token when your request carries video input, and the bill still goes up. The reason is a minimum billing window ByteDance names but never quantifies. Here is how to r

Seedance 2.5 has a minimum billing window. Six published prices give away the number.

A 2-second reference clip made my 5-second render more expensive. Here is the arithmetic.

I was writing a cost estimator for video generation last week and got it wrong twice. It backs the billing on reAPI, where Seedance 2.5 and MiniMax H3 both run behind one endpoint, so a wrong estimate is not a rounding error in a spreadsheet. It is money.

The first version was the obvious one: per-second rate times duration. Every vendor quotes a price per second, so a 5-second clip costs five times that. It survived about ten minutes against real numbers.

The second version accounted for input. That one was closer, and still wrong, because ByteDance's Seedance 2.5 has a minimum billing window that the pricing page mentions in one sentence and never quantifies. You can work out the number, though. The published price examples give away enough.

What ByteDance actually publishes

Seedance 2.5 does not bill per second internally. It bills per token, and the token count comes from a formula printed on the Ark pricing page:

tokens = (input_video_seconds + output_seconds) x width x height x fps / 1024
price = token_rate x tokens

Two things in there are easy to skim past.

The first is input_video_seconds. If your request carries a reference clip, that clip's runtime is added to the billable total. The model processes input footage and output footage alike, so both sides land in the token count. A 12-second reference driving a 10-second render is a 22-second bill. Every integration I have seen gets this wrong on the first pass, which is why we spell it out in the Seedance 2.5 API reference rather than leaving it to the vendor's formula.

The second is that the token rate is not fixed. For Seedance 2.5 it is ¥70 per million tokens when the request carries no video, and ¥42 per million when it does. Adding a reference clip drops your rate by 40%.

That discount is where I went wrong.

The cheaper rate produced a bigger bill

ByteDance publishes price examples for a 5-second 16:9 output. Without video input, 480p costs ¥3.36 and 720p costs ¥7.56. With video input, the same 5-second output is quoted as a range: ¥3.63 to ¥14.12 at 480p, ¥8.16 to ¥31.75 at 720p.

Look at the bottom of those ranges. The cheapest possible video-input render at 480p is ¥3.63. The same render with no video input is ¥3.36. You moved onto a rate that is 40% lower and the bill went up 8%.

The table has a footnote explaining which input length produces the floor price, and it is the detail that gives the whole thing away:

最低价对应输入 2~4 秒
(lowest price corresponds to 2 to 4 seconds of input)

A 2-second input and a 4-second input cost exactly the same. Under the published formula they should not. Two seconds plus a 5-second output is 7 billable seconds; four seconds plus the same output is 9. Those are different numbers and they produce the same price, which means something is clamping the low end.

Deriving the floor

The pricing page names the mechanism without giving the value:

对于 Seedance 2.0 系列、Seedance 2.5 模型,当输入包含视频时,存在最低 token 用量限制
(for the Seedance 2.0 series and Seedance 2.5, requests that include video input are subject to a minimum token usage)

The actual minimum lives in a Lark spreadsheet behind a login wall. But the six published prices are enough to recover it, so long as you can pin down the pixel dimensions the formula uses.

Start with the no-input case, where billable seconds equal output seconds and there is nothing hidden. 720p 16:9 at 24fps is 1280 x 720:

tokens = 5 x 1280 x 720 x 24 / 1024 = 108,000
price = 108,000 / 1,000,000 x ¥70 = ¥7.56

That is the published number, exactly. 480p 16:9 turns out to be 854 x 480 rather than 864 x 480, which you can confirm the same way: it yields ¥3.363, and ¥3.36 is what the table says.

Now run the video-input case backwards. Take the 720p floor price of ¥8.16 and solve for billable seconds:

tokens = ¥8.16 / ¥42 x 1,000,000 = 194,285
per_sec = 1280 x 720 x 24 / 1024 = 21,600
seconds = 194,285 / 21,600 = 8.99

Nine seconds. For a 5-second output. The 480p floor gives 8.996 on the same arithmetic, and both ceilings of the ranges resolve to 35 seconds, which is 30 seconds of input plus the 5-second output. Six published prices, six clean reconstructions:

480p, 5s out, no input ¥3.36 -> 5 billable seconds
720p, 5s out, no input ¥7.56 -> 5 billable seconds
480p, 5s out, 2-4s input ¥3.63 -> 9 billable seconds
720p, 5s out, 2-4s input ¥8.16 -> 9 billable seconds
480p, 5s out, 30s input ¥14.12 -> 35 billable seconds
720p, 5s out, 30s input ¥31.75 -> 35 billable seconds

Nine over five is 1.8. The rule we settled on in production is ceil(5/3 x output_seconds), which gives 9 for a 5-second output and matches the pattern across the rest of the vendor's quick-reference table. So the billable window is:

billable_seconds = max(input_seconds + output_seconds, ceil(5/3 x output_seconds))

Short reference clip, long render, and the floor is the term that wins. Everything under a 2:3 input-to-output ratio is billed as if you had supplied more footage than you did.

The estimator that survives contact with invoices

const RATE_PER_MTOK = { withVideo: 42, withoutVideo: 70 }; // CNY
const DIMS = { '480p': [854, 480], '720p': [1280, 720] } as const;

function estimate(
 outputSeconds: number,
 inputSeconds: number,
 resolution: '480p' | '720p',
 fps = 24,
) {
 const billable = inputSeconds > 0
 ? Math.max(inputSeconds + outputSeconds, Math.ceil((5 / 3) * outputSeconds))
 : outputSeconds;

 const [w, h] = DIMS[resolution];
 const tokens = (billable * w * h * fps) / 1024;
 const rate = inputSeconds > 0
 ? RATE_PER_MTOK.withVideo
 : RATE_PER_MTOK.withoutVideo;

 return (tokens / 1_000_000) * rate;
}

estimate(5, 0, '720p'); // 7.56
estimate(5, 2, '720p'); // 8.16, not 6.35

The naive version of line two, inputSeconds + outputSeconds with no floor, would have quoted ¥6.35 for that second call. Under-quoting by 22% is the kind of bug that only shows up in aggregate, weeks later, in a margin report.

Those are the vendor's own CNY figures, and they are the ones worth reasoning about because they explain the shape of the bill. What you pay at the top of the stack is a separate question: our current per-second rates for Seedance 2.5 are published on the model page and track the upstream card when it moves.

MiniMax H3 hides a different dimension

Hailuo 03, shipped as minimax-h3, went live around the same time and does none of this. Flat per-second rate, no resolution tiers, no minimum window. It looks like the simple case until you read what counts as a second.

Two things stack on top of the duration you asked for. Reference clips bill their own runtime the same way Seedance does, so a 12-second reference feeding a 10-second render bills 22 seconds. And reference images are metered: the first five are free, images six through nine each carry a flat charge on top. Audio references are free, and cap out at three.

So the H3 bill is a sum of two unrelated terms:

cost = per_second x (duration + input_video_seconds)
 + per_image x max(0, reference_images - 5)

No floor, but two independent quantities the caller does not control precisely. Different shape, same underlying problem. The per-second and per-image rates are on the MiniMax H3 model page if you want to run the sum for your own clip lengths.

What this costs you as an integrator

The uncomfortable part is not the arithmetic. It is that you cannot price a request from the request body alone.

duration you know. resolution you know. The runtime of a reference video sitting behind a customer-supplied URL, you do not, and the customer's claim about it is not something you can bill against. We probe every reference URL server-side before quoting, and reject the request outright if a clip's duration cannot be read: that is what the 30002 in our error catalog means, and it fires before anything is charged. Guessing here means either eating the difference or overcharging, and both are worse than a 400.

Seedance 2.5 adds one more wrinkle. Setting duration: -1 lets the model pick its own output length, which is mandatory for video-edit prompts. You cannot know the final length at submit time, so the reserve goes out at the 30-second cap and settles down to the real number when the video lands, with the difference refunded. Reserve high, settle honest. There is no version of this where you skip the reservation step.

What I did not verify

The floor coefficient is the soft spot. ByteDance publishes worked examples only for 5-second outputs, and 9 billable seconds is the value I can prove from those. The 5/3 generalisation comes from the pattern in the vendor's quick-reference table rather than from six numbers I reconstructed myself, and I would not bet a margin model on it holding at every duration without checking your own invoices first.

The pricing page also says plainly that estimated token counts are estimates, and that usage.completion_tokens in the API response is authoritative. Treat any pre-flight estimate, including the code above, as a reserve rather than a bill.

Rates move, too. The 2.0 fast and mini variants are running a promotional discount through early September as I write this, which tells you how stable these numbers are. Everything here was checked on 11 August 2026.

The takeaway

Per-second pricing on video models is a presentation layer. Underneath, at least on the Seedance family, you are buying pixels times frames times seconds, with a minimum purchase attached when you bring your own footage. The published rate card and the invoice agree only if you know which seconds count.

If a vendor gives you a price range instead of a price, the range endpoints are usually solvable. It took six numbers and a calculator to find a rule that would have quietly cost 22% on a whole class of requests.


Join neal on Peerlist!

Join amazing folks like neal and thousands of other builders on Peerlist.

peerlist.io/

It’s available... this username is available! 😃

Claim your username before it's too late!

This username is already taken, you’re a little late.😐

0

1

1