Skip to content
21/30Chapter 21 of 30

Multimodal Pricing: What Images, Audio and Video Really Bill

Three models given the same 500 photographs disagree by a factor of 5.5, and which one is cheapest flips the moment somebody resizes them.

On this page

Here is one task, priced three ways: describe five hundred product photographs, one short caption each. Same photographs, same instruction, same length of answer. The only thing that changes is which model reads them.

photographgpt-5.6-lunagemini-3.1-flash-liteclaude-haiku-4.5
800 × 600$0.0848$0.1638$0.4380
1024 × 768$0.1200$0.1638$0.6370
1280 × 960$0.1718$0.1638$0.9010
1600 × 1200$0.2558$0.1638$0.9010
4000 × 3000$0.3220$0.1638$0.9010

Three things in that table are worth stopping on.

The cheapest model changes between the third row and the fourth, on the same task, because somebody resized the photographs. Ask for a paragraph instead of a caption and the crossing point moves again: at 1280 × 960 the winner is Gemini for a forty-token caption and OpenAI for a four-hundred-token paragraph.

The Gemini column does not move at all, in any row: a 4000 \u00d7 3000 photograph costs it exactly what a 640 \u00d7 480 one costs. A 4000 × 3000 photograph costs it exactly what a 640 × 480 photograph costs. That is not a cap. It is a consequence of how it counts, and it means the most common cost optimisation in this business — downsample before you upload — pays like this:

image tokens, 4000 × 3000 → 800 × 600cost of the runsaved
gpt-5.6-luna2,942 → 570$0.3220 → $0.084873.7 %
claude-haiku-4.51,564 → 638$0.9010 → $0.438051.4 %
gemini-3.1-flash-lite1,032 → 1,032$0.1638 → $0.16380.0 %

None of those numbers is a price the vendor publishes. All three had to be computed, from three different rules, because a photograph is not a billable unit anywhere: it is converted into tokens first, by an arithmetic written down in three incompatible places.

Chapter 16 built the bill for text and stopped where text stops. This chapter is the rest of the invoice: images, speech, transcription, video and raw compute, which between them are billed in eight different units, and the method for comparing things that are not sold by the same measure.

Show details

What this chapter needs from the earlier ones.

  • Chapter 7 built the tokenizer and the unit. Everything here is an attempt to turn something that is not text into that unit.
  • Chapter 8 established what a model consumes: not symbols, but vectors in an embedding space. That is why an image can be priced in tokens at all.
  • Chapter 16 built computeCost, its price tiers and its five token buckets. This chapter extends that function rather than replacing it.
  • Chapter 11 introduced LoRA as a fine-tuning technique and Chapter 20 priced it as a budget decision. Here it turns up on a model that is not a language model.

No tensors, by the rule from Chapter 14: this is tariffs, conversions and accounting, so it is TypeScript.

A transformer takes a sequence of vectors. It has no opinion about where they came from. Chapter 8 fed it embeddings looked up from a token id; nothing in the architecture requires the lookup.

So: cut the picture into fixed squares, flatten each square into a list of numbers, and push each list through one learned linear layer to get a vector of the model's width. A 32 × 32 patch of colour pixels is 32×32×3=307232 \times 32 \times 3 = 3072 numbers; the projection ERd×3072E \in \mathbb{R}^{d \times 3072} turns it into one dd-dimensional vector, exactly the shape a text token arrives in. That is the whole of it, and it is the paper whose title says it: an image is worth 16 × 16 words.1 Add a positional encoding so the model knows which square was where, interleave the results with the text embeddings, and the sequence the model reads is part picture and part sentence.

Three papers made it a product. CLIP trained an image encoder and a text encoder to agree, on four hundred million scraped pairs, which is where the idea that pixels and words can share a space stopped being a hypothesis.2 Flamingo bolted a frozen vision encoder onto a frozen language model with a few trained bridging layers.3 LLaVA showed the bridge could be a single linear projection and the instruction-following could be taught with generated data, which is why every open vision-language model since looks roughly the same.4

The consequence for your invoice is immediate and unglamorous: the patches are positions in the sequence, so they are input tokens, so you pay for them at the input rate. How many is arithmetic, and each provider does it differently.

Every rule below is implemented from the provider's own documentation and checked against the worked examples in that same documentation.

OpenAI covers the image with 32 × 32 patches and multiplies the count by a per-model factor. If the patch count exceeds the budget for that model and detail level, the image is scaled down until it fits:

patches=w32×h32,shrink=322budgetwh\text{patches} = \left\lceil \frac{w}{32} \right\rceil \times \left\lceil \frac{h}{32} \right\rceil, \qquad \text{shrink} = \sqrt{\frac{32^2 \cdot \text{budget}}{w \cdot h}}

Anthropic covers it with 28 × 28 patches, one visual token each, and caps both the long edge and the token count — 1,568 pixels and 1,568 tokens on standard-tier models, 2,576 and 4,784 on the high-resolution tier. Oversized images are scaled to the largest size that fits both.5

Google does not count pixels at all. An image with both sides at or below 384 pixels costs a flat 258 tokens. Anything larger is cut into tiles of 258 tokens each, and the tile grid comes from a crop unit of min(w,h)/1.5\lfloor \min(w,h) / 1.5 \rfloor.6

imagetokens.tsTS
export function openaiImageTokens(
  w: number, h: number,
  { maxDim, patchBudget, multiplier }: { maxDim: number; patchBudget: number; multiplier: number },
) {
  const fit = Math.min(1, maxDim / Math.max(w, h));      // never enlarges
  w = Math.floor(w * fit); h = Math.floor(h * fit);
  let patches = Math.ceil(w / 32) * Math.ceil(h / 32);   
  if (patches > patchBudget) {
    const s = Math.sqrt((32 * 32 * patchBudget) / (w * h));
    const adj = s * Math.min(
      Math.floor((w * s) / 32) / ((w * s) / 32),
      Math.floor((h * s) / 32) / ((h * s) / 32));
    patches = Math.ceil(Math.floor(w * adj) / 32) * Math.ceil(Math.floor(h * adj) / 32);
  }
  return Math.ceil(patches * multiplier);                
}

export function anthropicVisualTokens(
  w: number, h: number,
  { maxLongEdge, maxTokens }: { maxLongEdge: number; maxTokens: number },
) {
  const tok = (a: number, b: number) => Math.ceil(a / 28) * Math.ceil(b / 28);
  const long = Math.max(w, h), short = Math.min(w, h);
  for (let L = Math.min(long, maxLongEdge); L >= 1; L--) {     
    const t = tok(L, Math.round((short * L) / long));
    if (t <= maxTokens) return t;                              
  }
  return 0;
}

export function geminiImageTokens(w: number, h: number) {
  if (w <= 384 && h <= 384) return 258;
  const crop = Math.floor(Math.min(w, h) / 1.5);               
  return Math.ceil(w / crop) * Math.ceil(h / crop) * 258;      
}

Run each against the numbers its own vendor prints:

three implementations against three documentationsTEXT
OpenAI, gpt-5.4 at detail:high (2048 px, 2,500 patches, 1.2x)
  1024x1024 -> 1024 patches -> 1229 tokens   doc says 1229   MATCH
  2048x2048 -> 2500 patches -> 3000 tokens   doc says 3000   MATCH

Anthropic, the published table (one tier per row shown)
  200x200    std   64 @ 200x200     doc   64, not resized    OK
  1000x1000  std 1296 @ 1000x1000   doc 1296, not resized    OK
  1092x1092  std 1521 @ 1092x1092   doc 1521, not resized    OK
  1920x1080  std 1560 @ 1456x819    doc 1560, 1456x819       OK
  2000x1500  std 1564 @ 1269x952    doc 1564, 1269x952       OK
  3840x2160  hi  4784 @ 2576x1449   doc 4784, 2576x1449      OK

Google, the worked example
  960x540 -> crop 360 -> 3 x 2 = 6 tiles     doc says 6      MATCH

Nine agreements are printed; the full run checks fifteen, since Anthropic's table gives both tiers for all six sizes. The rules are now yours to run on any photograph you have, which is the point: these are the only three functions in this chapter you cannot get from a price page.

Put the same 4:3 photograph through all three at six sizes:

sizeOpenAI, highAnthropic, standardAnthropic, high-resGemini
384 × 288130154154258
640 × 4803604144141,032
800 × 6005706386381,032
1600 × 12002,2801,5642,4941,032
3200 × 24002,9421,5644,7401,032
4000 × 30002,9421,5644,7401,032

Read the last column downwards. Once the picture is over 384 pixels the number never changes again, and that is not a coincidence or a cap. Substitute the crop unit back into the tile formula, for an image at least as wide as it is tall:

tiles=wh/1.5×hh/1.51.5wh×2\text{tiles} = \left\lceil \frac{w}{\lfloor h/1.5 \rfloor} \right\rceil \times \left\lceil \frac{h}{\lfloor h/1.5 \rfloor} \right\rceil \approx \left\lceil \frac{1.5\,w}{h} \right\rceil \times 2

The size cancels. Google's image tokens depend on the aspect ratio and nothing else. A 4:3 photograph is four tiles whether it is a thumbnail or a poster. That single algebraic fact is the entire explanation of the zero in the savings table above, and no price page anywhere states it.

The other two columns cap instead, at different heights and for different reasons — Anthropic at a declared token ceiling, OpenAI at a patch budget after a pixel limit — which is why the three curves cross at different sizes.

Now break it. The obvious way to spend less on a vision model is to ask for less detail, so send detail: "low":

gpt-5.4, the same photograph, two detail levelsTEXT
1600x1200   low = 2280   high = 2280   ratio 1.00
3200x2400   low = 3687   high = 2942   ratio 1.25

Asking for less detail cost 25 % more. This is not a bug and OpenAI says so in one line of the sizing table: on that model family, low uses a 2048-pixel limit with a 6,144-patch budget while high uses the same pixel limit with a 2,500-patch budget, "so it can use more tokens than high".7 The word low names a fidelity setting, not a price: on two of the five documented model families it buys no saving at all, and on one of those two it costs more.

Everything so far has been a model reading an image. Making one runs on a mechanism with no tokens in it at all, and that is the reason it is sold by the picture rather than by the word.

Making an image: a per-picture price is a per-token price

Link to the section: Making an image: a per-picture price is a per-token price

Vendors publish image generation as a price per picture. It is not one. GPT Image models emit specialised image tokens whose count depends on the requested size and quality; multiply the published counts by GPT Image 1's published image output rate of $40 per million and compare with the per-image prices on the same page:

quality1024 × 10241024 × 15361536 × 1024
low272 tok → $0.0109 ($0.011)408 tok → $0.0163 ($0.016)400 tok → $0.0160 ($0.016)
medium1,056 tok → $0.0422 ($0.042)1,584 tok → $0.0634 ($0.063)1,568 tok → $0.0627 ($0.063)
high4,160 tok → $0.1664 ($0.167)6,240 tok → $0.2496 ($0.25)6,208 tok → $0.2483 ($0.25)

Nine derived figures against nine published ones, every pair agreeing to within $0.002.11 Google is more explicit still and does the conversion for you on the price page itself: image output at $60 per million tokens, "output images at 1K (1024x1024px) consume 1120 tokens and are equivalent to $0.067 per image".12

So a per-image price is a per-token price with the count folded in. Which is fine, and it hides something. Take the current generation's table and divide backwards:

gpt-image-2, published price -> implied output tokens at $30/MTEXT
quality   1024x1024            1024x1536
low       $0.006 -> 200 tok    $0.005 -> 167 tok
medium    $0.053 -> 1767 tok   $0.041 -> 1367 tok
high      $0.211 -> 7033 tok   $0.165 -> 5500 tok

The larger image is the cheaper one at every quality. A 1024 × 1536 canvas is 50 % more pixels than a 1024 × 1024 one and costs 23 % fewer tokens at medium. OpenAI flags it in a sentence you would skip — "a larger non-square resolution can sometimes produce fewer output tokens than a smaller or square resolution at the same quality setting" — and on the previous model generation it ran the other way, portrait costing 50 % more than square.11 Every default of 1024x1024 written before that change is now the expensive option.

Sound, billed by the second, the character, and the token

Link to the section: Sound, billed by the second, the character, and the token

Ask three products to speak the same 519 characters — about 38 seconds of audio — and you get three unit systems from two vendors:

modelunitprice
tts-1per character$15.00 per million characters → $0.007785
tts-1-hdper character$30.00 per million characters → $0.015570
gemini-3.1-flash-ttsper audio token, 25 per second$20.00 per million → $0.019319

The same vendor sells both units: OpenAI's tts-1 is priced per million characters while gpt-4o-mini-tts is priced per million tokens, $0.60 in and $12.00 out.13 So "cheapest text-to-speech" is not a question with an answer until you say what you are speaking.

And the two units are blind to opposite things. A per-character price cannot see duration: choose a slow, deliberate voice, or add pauses, and the bill does not move while the audio gets longer. A per-second price cannot see content: thirty seconds costs the same whether it is a dense technical paragraph or somebody counting to ten. Change the voice and exactly one of your two vendors reprices.

Transcription runs the other way and is the simplest line on the whole invoice — per minute of audio, flat:

transcribing 59.6 secondsTEXT
whisper                  $0.005960     ($0.006 / min)
gpt-transcribe           $0.004470     ($0.0045 / min)
gpt-4o-mini-transcribe   $0.002980     ($0.003 / min)
gpt-live-transcribe      $0.016887     ($0.017 / min)

Note the last row against the third: doing it live, as the words arrive, costs 5.7 times doing it on a finished file. That gap is the price of not being able to batch, and it is what makes the next section expensive.

Now the number that decides whether voice is a feature or a product.

The call: a ten-turn support conversation, 149 words, which at a declared 150 words per minute is 59.6 seconds of speech — 21.2 spoken by the caller, 38.4 spoken back. The token conversions are the providers' own. OpenAI: "audio tokens in user messages are 1 token per 100 ms of audio, while audio tokens in assistant messages are 1 token per 50 ms".14 Google: 25 tokens per second, in both directions, which its price page confirms by publishing $12.00 per million and $0.018 per minute on the same line.12

The conversation accumulates exactly as Chapter 16 said it would, because it is the same mechanism: "the entire conversation is sent to the model for each Response... thus turns later in the session will be more expensive".14 Only now the history is measured in audio tokens.

turnuserassistantfresh audio incached audio inaudio outcost
14.4 s9.2 s440184$0.013224
25.6 s9.6 s56228192$0.014211
35.2 s9.2 s52476184$0.013670
44.0 s4.8 s4071296$0.007749
52.0 s5.6 s20848112$0.008187

Now the comparison that decides the product, all four normalised to a minute:

per minuteversus text
gpt-realtime-2.1, no caching$0.13125937.9×
gpt-realtime-2.1, history cached$0.05742516.6×
gemini-3.1-flash-live, no caching$0.0239656.9×
the same words typed, gpt-5.6-terra$0.003461

Thirty-eight times. Not thirty-eight per cent. The identical exchange, conducted in sound instead of text, is nearly two orders of magnitude dearer, and none of that gap is a margin somebody chose to charge — it is the conversion rate. One second of assistant audio is twenty tokens. That same second carries 2.5 words at the declared rate, and the measured transcript runs at 1.26 tokens per word, so as text it is 3.15 tokens. Sound is a 6.3 times bulkier package for the same meaning, and each of its tokens is billed at 5.3 times the text output rate and 16 times the text input rate. Multiply a bulk ratio by a price ratio and the order of magnitude is already there before any accounting begins.

Two operational consequences fall straight out of the table.

Audio caching is not an optimisation, it is the business model. Cached audio input is $0.40 per million against $32.00 fresh — a 98.75 % discount that halves the call. The rule is Chapter 16's, unchanged: the cache matches a prefix, so anything inserted at the front of the conversation mid-call destroys it, and the natural place to put "the caller is now verified" is exactly there.

And nothing you do in the client un-bills a sound. The user talks over the assistant, your code stops the playback, the speaker goes quiet. Whatever had already been generated was already charged, because billing accrues when the response is created; and by Chapter 16's rule whatever stays in the conversation is re-sent, as input audio, every turn after. Chapter 14 made this point about aborting a text stream. In voice it costs thirty times more.

Video, GPU-seconds, and a price that is not a price

Link to the section: Video, GPU-seconds, and a price that is not a price

Video is sold per second by some vendors and per clip by others, with tiers for resolution and sometimes for duration. Those two shapes do not merely differ in convenience; they cross.

model1 s2 s5 s10 s20 s
veo-3.1, per second, 1080p$0.400$0.800$2.000$4.000$8.000
veo-3.1-fast, per second, 1080p$0.120$0.240$0.600$1.200$2.400
sora-2, per second, 720p$0.100$0.200$0.500$1.000$2.000
hailuo-02, per clip, 1080p$0.480$0.480$0.480$0.480$0.480
mochi, per GPU-second$0.018$0.037$0.092$0.183$0.366

The per-clip vendor is dearer than the per-second one below 1.2 seconds and 16.7 times cheaper at twenty. No ordering of those two models survives a change in clip length, so "which video model is cheapest" is not a question about models.

The last row is worse, and it is the honest heart of the chapter. mochi is billed against real GPU seconds — the measured prediction time of the job — at $0.001400 per second on an A100 and $0.001525 on an H100, which are the rented machine's rates and nothing else.15 That is a perfectly precise tariff and it is not a price, because the quantity it multiplies is unknown until after you have committed to paying it. The row above assumes twelve GPU-seconds per second of output; quadruple that assumption and it leaves the cheapest band, and only at six times does it land mid-table. It is the only tariff on this page you cannot put in a quote.

So: tokens, image tokens, characters, minutes, video seconds, whole clips, GPU seconds, flat units. Eight quantities, and the only way to put them on one axis is to declare a workload and price it.

That is the extension to Chapter 16's computeCost — the same tier machinery, now with criteria that are not prompt length:

normalise.tsTS
export interface MediaCriteria {
  resolution?: string[]; quality?: string[];
  hasAudio?: boolean; maxDurationSeconds?: number;
}
export interface MediaTier { when?: MediaCriteria; price: number }
export type MediaRate = number | MediaTier[];

const matches = (when: MediaCriteria, u: Usage) => {
  const inList = (l?: string[], v?: string) => !l || (v !== undefined && l.includes(v));
  if (!inList(when.resolution, u.resolution)) return false;
  if (!inList(when.quality, u.quality)) return false;
  if (when.hasAudio !== undefined && when.hasAudio !== (u.hasAudio ?? false)) return false;
  if (when.maxDurationSeconds !== undefined
      && (u.videoSeconds ?? 0) > when.maxDurationSeconds) return false;   
  return true;
};

const mediaPrice = (rate: MediaRate | undefined, u: Usage): number => {
  if (rate === undefined) return 0;
  if (typeof rate === "number") return rate;
  for (const t of rate.filter((t) => t.when)) if (matches(t.when!, u)) return t.price;
  return rate.find((t) => !t.when)?.price ?? 0;      // the tier with no criteria is the default
};

export function computeCost(p: Pricing, u: Usage): number {
  let c = textCost(p, u);                             // Chapter 16, unchanged
  if (p.imageInputToken || p.imageOutputToken) {
    c += (u.imageInputTokens ?? 0) * (p.imageInputToken ?? 0)
       + (u.imageOutputTokens ?? 0) * (p.imageOutputToken ?? 0);
  } else if (p.imageUnit !== undefined) c += (u.images ?? 1) * mediaPrice(p.imageUnit, u);  
  if (p.videoSecond !== undefined) c += (u.videoSeconds ?? 0) * mediaPrice(p.videoSecond, u);
  if (p.videoUnit   !== undefined) c += (u.videoCount ?? 1)   * mediaPrice(p.videoUnit, u);
  c += (u.audioInputTokens ?? 0)       * (p.audioInputToken ?? 0)
     + (u.cachedAudioInputTokens ?? 0) * (p.cachedAudioInputToken ?? p.audioInputToken ?? 0)
     + (u.audioOutputTokens ?? 0)      * (p.audioOutputToken ?? 0)
     + (u.computeSeconds ?? 0)         * (p.computeSecond ?? 0)
     + (u.chars ?? 0)                  * (p.perChar ?? 0)
     + (u.minutes ?? 0)                * (p.perMinute ?? 0);
  return c;
}

The two marked lines are where it breaks. A tariff quoted per unit multiplies u.images ?? 1; a tariff quoted per token multiplies something that defaults to zero. Feed both an empty usage — the shape you get when a measurement failed — and watch:

the same missing measurement, priced by unitTEXT
per image (nano-banana-pro)     empty usage => $0.1500
per clip  (hailuo-02)           empty usage => $0.1500
per unit  (a cloned voice)      empty usage => $3.0000
per token (gpt-image-2)         empty usage => $0.0000
per second (veo-3.1)            empty usage => $0.0000
per GPU-second (mochi)          empty usage => $0.0000

Nothing happened, six times, and it cost three dollars once and nothing five times. That is not a rounding difference; it is a decision about what an absent number means, taken separately for each unit and never written down. The sound rule is that a field nobody measured stays absent, because "not measured" and "measured and came out zero" are different things. This function quietly disagrees.

The second failure is duration. The clip-priced tariff selects its tier with maxDurationSeconds against u.videoSeconds ?? 0, so a usage that never recorded a duration matches the shortest tier:

hailuo-02, 768pTEXT
duration recorded    ->  $0.45
duration missing     ->  $0.27

Forty per cent off for not knowing how long the video was. Both bugs have the same root: a default chosen for convenience inside a function whose whole job is to be exact.

With costs computable, the comparison needs the other half — a declared representative workload, one per engine, stated in public so a reader can disagree with it:

workloads.tsTS
export const representative = {
  text:   { blend: [[{ promptTokens: 1e6 }, 0.25], [{ completionTokens: 1e6 }, 0.75]] },
  image:  { images: 1, imageInputTokens: 50, imageOutputTokens: 1500 },
  video:  { videoSeconds: 5, videoCount: 1, resolution: "1080p", hasAudio: true, computeSeconds: 60 },
  voice:  { chars: 1000, computeSeconds: 10 },
  stt:    { minutes: 1 },
};

Every one of those lines is an argument. Text mixes a quarter input and three quarters output because real usage skews to output; a fifty-fifty blend ranks the models differently. The image workload assumes 1,500 output tokens, between OpenAI's 1,056 for a medium square and its 1,584 for a medium portrait. Video assumes five seconds at 1080p, and we have just seen two vendors swap places at 1.2 seconds. The compute entry assumes sixty GPU-seconds because there is nothing else to assume.

Which is the method, and it is the only honest one available: you cannot compare prices in different units; you can only compare the cost of a workload you have written down. Any table that ranks multimodal models without printing its workload is ranking its own assumptions.

You can now price anything a model can produce, in whatever unit it is sold, and say out loud which workload your comparison assumed. That closes the invoice Chapter 16 opened, and it closes Part III: everything from Chapter 14 to here has been about one call — how to make it, what to put in it, how to sample it, what it returns, what it costs.

Chapter 22 changes the unit of analysis, and the change is expensive. An agent is not one call; it is a loop that decides for itself how many calls to make, and the arithmetic of the last two chapters is what turns that from an architecture diagram into a budget. It opens by asking the same question of the same model twice, with one tool added to the catalogue the second time, and measuring what that one tool did: one call became two, thirty-nine input tokens became 420.

Whether that makes it an agent depends on which of two published definitions you open, and they do not agree. One of them does not agree with itself.


Every price, formula and conversion rate in this chapter was read from the provider's own page on 7 September 2026 and is quoted with that date, because all of them will move. The token counts, costs and comparisons were computed on that data by the code printed above, on one machine, with no paid API call made — which is also the honest reason there is not a single latency claim in this chapter.

The image-token functions, the cost tables, the voice-call breakdown and the empty-usage results were produced by the TypeScript printed in this chapter, run on Node 22. The dialogue used for the voice comparison is 149 words and was tokenized with tiktoken under the o200k_base encoding at 188 tokens; its duration follows from a declared rate of 150 words per minute, which is a parameter of the comparison and not a measurement. Every provider figure carries the footnote that names the page it came from.

  1. Dosovitskiy, A. et al. An Image Is Worth 16x16 Words: Transformers for Image Recognition at Scale. arXiv:2010.11929 (2020). Patches, the linear projection into the embedding dimension, and the position embeddings that make the grid legible to a sequence model.

  2. Radford, A. et al. Learning Transferable Visual Models From Natural Language Supervision. arXiv:2103.00020 (2021). Contrastive training of an image encoder and a text encoder on 400 million pairs, and the shared space that everything downstream assumes.

  3. Alayrac, J.-B. et al. Flamingo: a Visual Language Model for Few-Shot Learning. arXiv:2204.14198 (2022). Frozen vision encoder, frozen language model, trained bridging layers — the architecture that turned image understanding into a chat capability.

  4. Liu, H., Li, C., Wu, Q. and Lee, Y. J. Visual Instruction Tuning. arXiv:2304.08485 (2023). A single linear projection as the bridge and generated instruction data as the training set; the reason open vision-language models converged on one shape.

  5. Anthropic, Vision, platform.claude.com/docs/en/build-with-claude/vision, accessed 2026-09-07. "Claude views images in patches instead of pixels. Each patch is a 28×28-pixel block of the image, referred to as a visual token. An image, therefore, costs ⌈width / 28⌉ × ⌈height / 28⌉ visual tokens." Also the two resolution tiers (standard: 1568-pixel long edge, 1568 visual tokens; high-resolution, on Claude 4.7 and later: 2576 pixels and 4784 tokens), the downsizing rule, and the six-row table of sizes and token counts reproduced above. Model rates from Anthropic, Pricing, platform.claude.com/docs/en/about-claude/pricing, same date: Claude Haiku 4.5 at $1 and $5 per million input and output tokens.

  6. Google, Image understanding, ai.google.dev/gemini-api/docs/image-understanding, accessed 2026-09-07. "258 tokens if both dimensions <= 384 pixels. Larger images are tiled into 768x768 pixel tiles, each costing 258 tokens", with the crop-unit formula — floor(min(width, height) / 1.5), dimensions divided by it and multiplied together — and the worked example of 960 × 540 giving 3 × 2 = 6 tiles. Google calls it "a rough formula"; the scale-invariance derived above is a property of the formula as published. Audio input on the same family is 32 tokens per second of audio (ai.google.dev/gemini-api/docs/audio, same date).

  7. OpenAI, Images and vision, developers.openai.com/api/docs/guides/images-vision, accessed 2026-09-07. Source of the patch-based rule (32 × 32 patches, patch_count = ceil(width/32)×ceil(height/32), the shrink_factor formula and its integer adjustment, the 30,000-patch rejection limit); the model sizing table, including that low on gpt-5.4 uses a 2048-pixel limit and a 6,144-patch budget "so it can use more tokens than high", against high's 2,500-patch budget; the multiplier table (1.2 for the GPT-5.x families, 1.62 for gpt-4.1-mini, 2.46 for gpt-4.1-nano); the two worked examples reproduced above (1024 × 1024 → 1229 tokens, 2048 × 2048 → 3000 tokens); the tile-based rules for older models (base plus 512-pixel tiles, 85 + 170 on gpt-4o); and the limitations list quoted in the vision box. 2

  8. Ho, J., Jain, A. and Abbeel, P. Denoising Diffusion Probabilistic Models. arXiv:2006.11239 (2020). The forward noising schedule, the reparameterisation that turns the objective into predicting the added noise, and the sampling loop.

  9. Rombach, R., Blattmann, A., Lorenz, D., Esser, P. and Ommer, B. High-Resolution Image Synthesis with Latent Diffusion Models. arXiv:2112.10752 (2022). Running the diffusion process in a compressed latent space, which is what made the fixed step count affordable enough to sell per image.

  10. Prince, S. J. D. Understanding Deep Learning (MIT Press, 2023), chapter 18. The declared delegation for everything this chapter skipped about diffusion — the variational bound, the noise schedules, classifier-free guidance and the sampler families. Hu, E. et al., LoRA: Low-Rank Adaptation of Large Language Models, arXiv:2106.09685 (2021), is the adapter itself, introduced in Chapter 11 on a language model and used here on an image model without a change of mathematics. Radford, A. et al., Robust Speech Recognition via Large-Scale Weak Supervision (Whisper), arXiv:2212.04356 (2022), is the transcription model whose per-minute price appears above.

  11. OpenAI, Image generation, developers.openai.com/api/docs/guides/image-generation, Pricing, developers.openai.com/api/docs/pricing, and the model page for gpt-image-1, all accessed 2026-09-07. The model page for gpt-image-2 carries no pricing section; its rates come from the pricing page above. GPT Image 1's page publishes text input at $5.00, image input at $10.00 and image output at $40.00 per million tokens beside the per-image table used in the derivation above. Also: the output-token table for models prior to gpt-image-2 (272 / 408 / 400 low, 1056 / 1584 / 1568 medium, 4160 / 6240 / 6208 high, for square, portrait and landscape); the per-image price tables for GPT Image 2, 1.5, 1 and 1 Mini used in the derivations above; the sentence "a larger non-square resolution can sometimes produce fewer output tokens than a smaller or square resolution at the same quality setting"; the note that each streamed partial image costs an extra 100 image output tokens; and gpt-image-2's rates of $8.00 image input, $2.00 cached image input, $30.00 image output and $5.00 text input per million tokens. Text model rates used for the comparisons: gpt-5.6-terra at $2.00 input, $0.20 cached input and $12.00 output, gpt-5.6-luna at $0.20 and $1.20, standard tier, short context. Video: sora-2 at $0.10 per second at 720p and sora-2-pro at $0.30, $0.50 and $0.70 at 720p, 1024p and 1080p. Transcription: $0.006, $0.0045, $0.003 and $0.017 per minute for gpt-4o-transcribe, gpt-transcribe, gpt-4o-mini-transcribe and gpt-live-transcribe. 2

  12. Google, Gemini Developer API pricing, ai.google.dev/gemini-api/docs/pricing, accessed 2026-09-07. Gemini 3.1 Flash-Lite at $0.25 per million input tokens (text, image and video) and $1.50 output. Gemini 3.1 Flash Image: image output at $60 per million tokens, with the published equivalences of 747, 1120, 1680 and 2520 tokens for 0.5K, 1K, 2K and 4K images and their per-image prices of $0.045, $0.067, $0.101 and $0.151. Gemini 3.1 Flash TTS: $1.00 text input, $20.00 audio output, "audio tokens correspond to 25 tokens per second of audio". Gemini 3.1 Flash Live Preview: $0.75 text and "$3.00 or $0.005/min" audio input, "$4.50 (text) $12.00 or $0.018/min (audio)" output. Veo 3.1 per second with audio: $0.40 at 720p and 1080p and $0.60 at 4K standard; $0.10, $0.12 and $0.30 fast. Gemini Omni Flash bills video output "at a rate of 5,792 tokens per second of 720p video", which the same footnote converts to about $0.10 per second — the clearest published statement anywhere that a per-second media price is a token price. 2

  13. OpenAI model pages for tts-1, tts-1-hd and gpt-4o-mini-tts, developers.openai.com/api/docs/models, accessed 2026-09-07. tts-1 at $15.00 and tts-1-hd at $30.00 per million characters; gpt-4o-mini-tts at $0.60 per million text input tokens and $12.00 per million audio output tokens — the same vendor, the same operation, two units.

  14. OpenAI, Managing costs (Realtime API), developers.openai.com/api/docs/guides/realtime-costs, accessed 2026-09-07. "Audio tokens in user messages are 1 token per 100 ms of audio, while audio tokens in assistant messages are 1 token per 50ms of audio." Also: "The entire conversation is sent to the model for each Response... thus turns later in the session will be more expensive"; costs accrue when a Response is created; the worked two-turn example whose accumulation the table above reproduces; and the response.done usage payload with its input_token_details and output_token_details splits. Rates from the pricing page, same date: gpt-realtime-2.1 audio at $32.00 input, $0.40 cached input and $64.00 output per million tokens, text at $4.00, $0.40 and $24.00, image input at $5.00. 2

  15. Replicate, Pricing, replicate.com/pricing, accessed 2026-09-07. Nvidia A100 (80GB) at $0.001400 per second and $5.04 per hour; Nvidia H100 at $0.001525 per second and $5.49 per hour.

Ready to let LIA do the choosing?

Build with every AI model in one place — start free today.