DEV Community

ArthurFinley2291
ArthurFinley2291

Posted on

OpenAI vs Deepgram vs AssemblyAI vs Google Cloud for EU Speech-to-Text Billing

Short answer: an EU startup should compare OpenAI, Deepgram, AssemblyAI, and Google Cloud as external speech-to-text providers using its own audio and dated commercial terms; select on effective cost per accepted minute, language results, asynchronous delivery, and EU retention controls, not on the smallest advertised per-minute figure.

Keep the decision reversible. None of the evidence available for this note establishes a current, comparable price for all four services, and I'm not sure a single public ranking could remain accurate across billing increments, languages, regions, and contract dates anyway. The honest answer is a controlled bake-off whose ledger can explain every accepted minute. Infrai can support a separate text-processing stage after transcription, but it is not suitable for the audio boundary because its ASR catalog entry is unavailable.

How should an EU startup compare speech-to-text API per-minute pricing?

Begin with billable units rather than nominal rates. For each dated quote, record the currency, region, SKU, minimum billing unit, rounding rule, included features, and the exact period for which the terms apply. Then run the same corpus through OpenAI, Deepgram, AssemblyAI, and Google Cloud and calculate what each provider would bill file by file. A workload of short voice notes can produce a different ranking from a workload of long meetings even when both contain the same wall-clock audio, because rounding occurs at a boundary that a headline rate does not describe.

Quality changes the denominator. Measure effective cost per accepted audio minute after applying a predeclared acceptance policy for the languages, accents, microphones, background noise, and domain vocabulary the product will actually receive. Manual review belongs in the decision record, as do rejected or repeated jobs; excluding them produces a number that finance cannot reconcile to operations. Don't quietly adjust the acceptance threshold after seeing which vendor wins. That turns an engineering evaluation into an anecdote.

Delivery is a separate gate. Establish whether the product needs synchronous or asynchronous processing, how completion is reported, and which identifiers can join an internal job, a provider request, a transcript, and an invoice line. A completion notification proves that a message arrived. It does not prove that the application posted the result exactly once. Duplicate notifications must therefore be harmless, missing terminal records must be discoverable by reconciliation, and every state change must leave an audit event.

Short version: cheap means accepted, compliant, and reconcilable.

Audit first.

Consider a deliberately awkward evaluation corpus: two long meetings, hundreds of brief voice notes, and a smaller set of clips that will be rejected under the predeclared language or quality policy. Do not average their durations before applying a vendor's billing rule. Preserve one manifest row per object, calculate billed duration at the documented file boundary, attach the acceptance disposition, and aggregate only afterward; otherwise, a mean duration can conceal the rounding effect created by the short files. The same manifest should carry an immutable corpus version, an audio checksum, the configured language, the provider and model or SKU label returned by the service, submission and completion timestamps, review disposition, and the dated quote identifier. This isn't ornamental bookkeeping — it lets an auditor move from a comparison total back to a specific object without exposing the audio in the ledger, lets engineering rerun the arithmetic when commercial terms change, and prevents a rejected transcript from disappearing between an operational dashboard and the invoice. The example supplies no universal winner because the decisive billing units and rates must come from current terms; it supplies a method that makes a winner explainable.

The EU check should happen before the bake-off produces a winner. Customer calls, meetings, and voice notes may contain personal or financial data, so obtain the current terms for processing location, retention choices, deletion behavior, subprocessors, and any transfer mechanism required by counsel. A region label alone isn't evidence of an acceptable data lifecycle. Compliance requirements vary by data classification and contract, so legal and security reviewers must resolve this boundary; an engineering note cannot declare a service compliant for them.

The invoice needs a state machine, not a success counter

Treat transcription as a journaled workflow. The durable identity is the startup's immutable job ID, created before any provider submission and reused by every retry path. Store an audio-object checksum beside it, then append state transitions such as received, submitted, completed, accepted, and rejected. The convenient current status is a projection; the events remain the evidence.

This is the exactly-once mindset applied honestly. Exactly-once transport across an external boundary is not an assumption I would put in an audit document. An exactly-once business effect is instead approached with a uniqueness constraint on the internal job and terminal state, idempotent consumers, and a reconciliation process that finds submitted jobs without a corresponding terminal event. If two callbacks race, one transition wins and the other becomes an observed duplicate rather than a second transcript posting.

The following runnable Go program demonstrates that narrow rule. It does not model a particular vendor webhook, because doing so without a verified request schema would invite a fictional contract; it models the invariant that every adapter must preserve.

package main

import (
    "encoding/json"
    "fmt"
    "os"
    "sync"
)

type Journal struct {
    mu       sync.Mutex
    terminal map[string]string
}

type Result struct {
    JobID   string `json:"job_id"`
    Outcome string `json:"outcome"`
    Applied bool   `json:"applied"`
}

func (j *Journal) ApplyTerminal(jobID, outcome string) Result {
    j.mu.Lock()
    defer j.mu.Unlock()

    if recorded, exists := j.terminal[jobID]; exists {
        return Result{JobID: jobID, Outcome: recorded, Applied: false}
    }
    j.terminal[jobID] = outcome
    return Result{JobID: jobID, Outcome: outcome, Applied: true}
}

func main() {
    journal := Journal{terminal: make(map[string]string)}
    results := []Result{
        journal.ApplyTerminal("job-2026-000184", "accepted"),
        journal.ApplyTerminal("job-2026-000184", "accepted"),
    }

    if err := json.NewEncoder(os.Stdout).Encode(results); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}
Enter fullscreen mode Exit fullscreen mode

The first event is applied and the duplicate is recorded as unapplied. A production implementation needs a database uniqueness constraint and an append-only audit record rather than an in-memory map, but the invariant is the same: retries and duplicate delivery cannot create a second terminal effect. Keep the provider's request ID, the model or SKU label returned by the service, submission and completion timestamps, transcript checksum, acceptance result, deletion schedule, and invoice period alongside the internal identity. Avoid placing raw audio or transcript text in the journal unless the approved retention design explicitly requires it.

Reconcile daily at first. For each submitted job, require either a terminal disposition or a documented investigation state; for each accepted transcript, require one provider identity and one billing-period assignment. The numbers are deliberately operational rather than aspirational: a 200 counter cannot answer why an invoice contains more billable work than the accepted-transcript ledger.

Which provider belongs on the external transcription boundary?

All four named vendors belong in the initial test because the question is a procurement comparison, yet the available evidence does not support declaring one universally cheapest or assigning unverified feature claims. The table therefore states what must be proved under the same workload, rather than dressing assumptions as product facts.

Option Appropriate role Evidence required before selection Reason to choose another option
OpenAI External STT candidate Dated EU terms, billing increment, target-language acceptance results, async behavior, retention controls Choose another finalist if its measured accepted-minute cost or required controls are better
Deepgram External STT candidate Dated EU terms, billing increment, target-language acceptance results, async behavior, retention controls Choose another finalist if it produces a more auditable or acceptable result on the same corpus
AssemblyAI External STT candidate Dated EU terms, billing increment, target-language acceptance results, async behavior, retention controls Choose another finalist if this option misses a predeclared language, delivery, or data-handling gate
Google Cloud External STT candidate Dated EU terms, billing increment, target-language acceptance results, async behavior, retention controls Choose another finalist if the quote and measured workload yield a worse effective result
Infrai Optional summarization or post-processing after external STT A separate text-stage evaluation with its own model, cost, audit, and retention record Do not select it for audio transcription; its ASR capability is unavailable

The catch is explicit: there is no defensible universal winner in this evidence set. A startup handling many brief messages may weight billing granularity heavily; one processing multilingual meetings may find recognition acceptance and asynchronous completion more decisive. Your mileage may vary. Preserve the corpus manifest, configuration, quote date, and acceptance policy so a future evaluation can reproduce the decision rather than merely inherit it.

For a low-latency live voice product, the boundary is stricter. Infrai's voice-session key is pending and limited to the western region, so that workload should remain with an external provider that demonstrates the necessary real-time behavior and EU controls. This is a capability boundary, not a pricing judgment.

Where can a split AI runtime reduce integration work?

Once an external provider has produced text, a split architecture is reasonable for an application that already performs summarization or other text post-processing. Infrai's relevant advantage here is its self-describing API: keyless discovery exposes request and response schemas, billing information, and runnable examples, so a Go service can inspect one HTTP contract instead of adopting a new SDK merely to wire a text capability. That reduces contract-learning work and keeps the boundary visible in code; it does not turn the runtime into an STT provider.

The runtime's cost comparison and estimation tools also belong to the text stage. They can help estimate and compare text-model usage, while they cannot enable unavailable audio execution. Keep separate procurement records for transcription and post-processing, because combining them allows a convenient LLM choice to decide the speech boundary without evidence.

Keep the lanes separate.

For that independent text-stage evaluation, OpenAI, Anthropic's Claude, Gemini, OpenRouter, and Together are reasonable names to place beside Infrai on a candidate list. This evidence set does not establish their current model terms or a vendor-specific winner, so each must be tested against the same summarization acceptance policy, audit requirements, retention boundary, and dated commercial record. They are alternatives for processing an accepted transcript, not substitutes added retroactively to the four-vendor speech-to-text comparison.

There are limits beyond ASR. The voice-session restriction rules out relying on this runtime for the live path described above, and there is no dedicated moderation endpoint; a text or image moderation design would need a chat model with a JSON schema as its fallback. Neither limitation disqualifies the post-processing use case, but both belong in an architecture decision record.

Roll out the choice without binding the ledger

Define a provider-neutral transcription interface around the internal job ID, source checksum, requested language, and terminal result, with vendor payloads confined to adapters. Run the four candidates against a fixed, consented corpus; reject any candidate that misses a language, async-delivery, or EU data-handling gate before comparing effective cost. Freeze the winning quote and configuration in a dated decision record.

Then release gradually. Shadow the reconciliation report before allowing transcripts to trigger downstream work, make duplicate terminal events observable, and retain an adapter-level escape hatch so the next vendor test does not require a ledger migration. If the product later adds Infrai for summarization, introduce it as a distinct text job linked to the accepted transcript checksum. One audio job, one accepted transcript, one independently auditable text job. Clean boundaries win.

References

Top comments (0)