Designing a Cost-Aware AI Video Workflow: Show the Price Before Render

typescript dev.to

AI video forms often make the expensive decision feel like a cheap one. A creator chooses a model, duration, resolution, and audio mode, but the interface hides the consequence until after they press Generate.

That is more than a pricing problem. It is a product-state problem: the cost is derived from the same controls that define the output, so it should update in the same interaction loop.

This post explains the pattern I used while building an image-to-video workflow around Grok Imagine 1.5 Preview.

1. Make cost a derived field, not a checkout surprise

For the current Grok workflow, the supported duration is 1–15 seconds. The UI offers 480p and 720p. In this implementation, 480p is charged at 1.6 credits per second and 720p at 3 credits per second, rounded up to a whole credit.

The estimator can stay intentionally small:

type Resolution = "480p" | "720p";

function estimateCredits(
  duration: number,
  resolution: Resolution,
): number {
  const rate = resolution === "720p" ? 3 : 1.6;
  return Math.ceil(duration * rate);
}
Enter fullscreen mode Exit fullscreen mode

The important part is not the formula. It is where the formula runs. Duration and resolution are already controlled form state, so the estimate belongs beside the Generate button and should change immediately when either control changes.

Do not calculate it only on the server and reveal it after submission. The server should still recalculate the authoritative amount, but the client estimate is what lets the user make a decision.

2. Model capabilities should shape the form

A generic video form tends to expose every control for every model. That creates impossible combinations and forces error handling to do work the interface could have prevented.

Instead, describe each model as data:

const grokImagine = {
  modes: ["image-to-video"],
  durations: Array.from({ length: 15 }, (_, index) => index + 1),
  resolutions: ["480p", "720p"],
  audio: "native",
  defaults: {
    duration: 8,
    resolution: "480p",
  },
} as const;
Enter fullscreen mode Exit fullscreen mode

The form then renders only valid choices. Because this model creates video and audio together, there is no separate audio toggle. Hiding a control is better than showing a switch that does nothing.

This also reduces drift between marketing copy, the form, and the API. The same capability object can power validation, defaults, and explanatory text.

3. Design the default around a first successful result

A default is a recommendation. It should not silently consume most of a new user's allowance.

In this example, an 8-second 480p render costs 13 credits. A new account receives 20 credits, so the default can produce one full result with some room left. Moving the same duration to 720p raises the estimate to 24 credits, and the interface makes that trade-off visible before submission.

This is a useful acceptance test:

  • Can a new user complete the default workflow with the initial allowance?
  • Does changing resolution visibly change the estimate?
  • Does an unaffordable combination become obvious before the API call?
  • Is the default still long enough to demonstrate the product?

Free credits are not useful if they cannot produce a first result.

4. Put guidance next to the expensive choice

The creator should not need a separate pricing page to understand a control. Short, local guidance works better:

  • Start at 480p while testing motion and framing.
  • Move to 720p after the prompt is stable.
  • Keep the first clip short when exploring a new visual direction.
  • Describe subject motion, camera movement, and environmental motion separately.

This turns cost visibility into workflow advice instead of a warning banner.

5. Revalidate on the server

The preview is advisory. The API must normalize and validate the same settings before creating a provider task.

A safe request path is:

  1. Parse duration as an integer.
  2. Confirm the selected model supports that duration.
  3. Confirm the resolution is in the model's capability list.
  4. Recompute the cost on the server.
  5. Check the current balance.
  6. Deduct credits and create the asynchronous task.
  7. Refund the deduction if the generation fails.

Client and server can share types and configuration, but the server remains authoritative.

6. Test decisions, not just controls

A useful UI test does more than confirm that a dropdown opens. It verifies the decision loop:

  • The 8-second 480p default shows 13 credits.
  • Switching to 720p shows 24 credits.
  • A 1-second 480p clip rounds up to 2 credits.
  • Unsupported durations never appear.
  • The submitted payload matches the estimate the user approved.
  • A failed generation restores the deducted balance.

These checks protect the promise the interface makes.

Live reference

The finished interaction is available in the MICT Grok image-to-video workflow. I am the builder of MICT; I am linking it as the concrete implementation discussed above, not as an independent recommendation.

Disclosure

I used AI assistance to edit the structure and wording of this article. I verified the technical details and code examples against the implementation before publishing.

Source: dev.to

arrow_back Back to Tutorials