pricing calculator usage-based estimator ai voice models interactive costs pricing calculator usage-based estimator ai-models llm stt tts per-minute costs pricing calculator for usage-based billing interactive cost estimator with model selection voice ai pricing calculator
Pricing Calculator
Fetch pattern JSON:
curl https://webspire.de/patterns/pricing/calculator.json calculator.html
<section class="ws-pricing bg-[var(--ws-pricing-bg)] py-20">
<div class="mx-auto max-w-4xl px-6">
<div class="mx-auto max-w-2xl text-center">
<p class="text-sm font-semibold uppercase tracking-[0.18em] text-[var(--ws-pricing-highlight-bg)]">Pricing estimator</p>
<h2 class="mt-3 text-balance text-3xl font-bold tracking-tight text-[var(--ws-pricing-text)] sm:text-4xl">Calculate your costs</h2>
<p class="mt-4 text-base text-[var(--ws-pricing-text-soft)]">Usage-based pricing — only pay for what you use. Adjust the options to estimate your monthly bill.</p>
</div>
<div class="mt-12 overflow-hidden rounded-2xl border border-[var(--ws-pricing-card-border)] bg-[var(--ws-pricing-card-bg)]">
<!-- Connection type toggle -->
<div class="border-b border-[var(--ws-pricing-card-border)] p-6">
<p class="mb-3 text-sm font-semibold text-[var(--ws-pricing-text)]">Connection type</p>
<div class="inline-flex rounded-lg border border-[var(--ws-pricing-card-border)] p-1" role="group" aria-label="Connection type">
<button id="type-web" data-type="web" class="ws-type-btn rounded-md px-4 py-2 text-sm font-medium transition-all bg-[var(--ws-pricing-highlight-bg)] text-white" aria-pressed="true">
Web / Mobile
</button>
<button id="type-phone" data-type="phone" class="ws-type-btn rounded-md px-4 py-2 text-sm font-medium transition-all text-[var(--ws-pricing-text-soft)] hover:text-[var(--ws-pricing-text)]" aria-pressed="false">
Phone (SIP)
</button>
</div>
</div>
<!-- Model selectors -->
<div class="grid gap-6 border-b border-[var(--ws-pricing-card-border)] p-6 sm:grid-cols-3">
<div>
<label for="select-llm" class="block text-sm font-semibold text-[var(--ws-pricing-text)]">LLM</label>
<p class="mt-0.5 text-xs text-[var(--ws-pricing-text-soft)]">Language model for reasoning</p>
<select id="select-llm" class="mt-3 w-full rounded-lg border border-[var(--ws-pricing-card-border)] bg-[var(--ws-pricing-bg)] px-3 py-2 text-sm text-[var(--ws-pricing-text)] focus:outline-none focus:ring-2 focus:ring-[var(--ws-pricing-highlight-bg)]">
<option value="0.003">GPT-4o — $0.0030/min</option>
<option value="0.002">Claude 3.5 Sonnet — $0.0020/min</option>
<option value="0.001">Gemini 2.0 Flash — $0.0010/min</option>
<option value="0.005">GPT-4o mini — $0.0005/min</option>
<option value="0">Self-hosted — $0.0000/min</option>
</select>
</div>
<div>
<label for="select-stt" class="block text-sm font-semibold text-[var(--ws-pricing-text)]">Speech-to-Text</label>
<p class="mt-0.5 text-xs text-[var(--ws-pricing-text-soft)]">Transcription model</p>
<select id="select-stt" class="mt-3 w-full rounded-lg border border-[var(--ws-pricing-card-border)] bg-[var(--ws-pricing-bg)] px-3 py-2 text-sm text-[var(--ws-pricing-text)] focus:outline-none focus:ring-2 focus:ring-[var(--ws-pricing-highlight-bg)]">
<option value="0.0034">Deepgram Nova-2 — $0.0034/min</option>
<option value="0.006">Google Chirp — $0.0060/min</option>
<option value="0.003">Whisper (hosted) — $0.0030/min</option>
<option value="0">Self-hosted — $0.0000/min</option>
</select>
</div>
<div>
<label for="select-tts" class="block text-sm font-semibold text-[var(--ws-pricing-text)]">Text-to-Speech</label>
<p class="mt-0.5 text-xs text-[var(--ws-pricing-text-soft)]">Voice synthesis model</p>
<select id="select-tts" class="mt-3 w-full rounded-lg border border-[var(--ws-pricing-card-border)] bg-[var(--ws-pricing-bg)] px-3 py-2 text-sm text-[var(--ws-pricing-text)] focus:outline-none focus:ring-2 focus:ring-[var(--ws-pricing-highlight-bg)]">
<option value="0.015">OpenAI TTS-1 — $0.0150/min</option>
<option value="0.01">ElevenLabs — $0.0100/min</option>
<option value="0.004">Google TTS — $0.0040/min</option>
<option value="0.008">Cartesia Sonic — $0.0080/min</option>
<option value="0">Self-hosted — $0.0000/min</option>
</select>
</div>
</div>
<!-- Result display -->
<div class="p-6">
<div class="flex flex-col items-start justify-between gap-6 sm:flex-row sm:items-center">
<div>
<p class="text-sm text-[var(--ws-pricing-text-soft)]">Estimated cost per minute</p>
<p class="mt-1 text-4xl font-bold tabular-nums tracking-tight text-[var(--ws-pricing-text)]">
$<span id="cost-per-min">0.0214</span>
<span class="text-lg font-medium text-[var(--ws-pricing-text-soft)]">/min</span>
</p>
<p class="mt-1 text-sm text-[var(--ws-pricing-text-soft)]">
≈ $<span id="cost-per-hour">1.28</span>/hour · $<span id="cost-per-1k">21.40</span> per 1,000 minutes
</p>
</div>
<div class="w-full rounded-xl border border-[var(--ws-pricing-card-border)] sm:w-auto sm:min-w-64">
<div class="flex items-center justify-between border-b border-[var(--ws-pricing-card-border)] px-4 py-3">
<span class="text-xs font-semibold uppercase tracking-wider text-[var(--ws-pricing-text-soft)]">Plan</span>
<span class="text-xs font-semibold uppercase tracking-wider text-[var(--ws-pricing-text-soft)]">Included mins/mo</span>
</div>
<div id="plan-included-web" class="divide-y divide-[var(--ws-pricing-card-border)]">
<div class="flex items-center justify-between px-4 py-2.5"><span class="text-sm text-[var(--ws-pricing-text)]">Build (Free)</span><span class="text-sm font-semibold text-[var(--ws-pricing-text)]">1,000</span></div>
<div class="flex items-center justify-between px-4 py-2.5"><span class="text-sm text-[var(--ws-pricing-text)]">Ship ($50/mo)</span><span class="text-sm font-semibold text-[var(--ws-pricing-text)]">3,000</span></div>
<div class="flex items-center justify-between px-4 py-2.5"><span class="text-sm text-[var(--ws-pricing-text)]">Scale ($500/mo)</span><span class="text-sm font-semibold text-[var(--ws-pricing-text)]">30,000</span></div>
</div>
<div id="plan-included-phone" class="hidden divide-y divide-[var(--ws-pricing-card-border)]">
<div class="flex items-center justify-between px-4 py-2.5"><span class="text-sm text-[var(--ws-pricing-text)]">Build (Free)</span><span class="text-sm font-semibold text-[var(--ws-pricing-text)]">500</span></div>
<div class="flex items-center justify-between px-4 py-2.5"><span class="text-sm text-[var(--ws-pricing-text)]">Ship ($50/mo)</span><span class="text-sm font-semibold text-[var(--ws-pricing-text)]">1,500</span></div>
<div class="flex items-center justify-between px-4 py-2.5"><span class="text-sm text-[var(--ws-pricing-text)]">Scale ($500/mo)</span><span class="text-sm font-semibold text-[var(--ws-pricing-text)]">15,000</span></div>
</div>
</div>
</div>
<!-- Cost breakdown -->
<div class="mt-6 rounded-xl bg-[var(--ws-pricing-bg)] p-4">
<p class="mb-3 text-xs font-semibold uppercase tracking-wider text-[var(--ws-pricing-text-soft)]">Cost breakdown</p>
<div class="space-y-2 text-sm">
<div class="flex justify-between">
<span class="text-[var(--ws-pricing-text-soft)]">Platform (<span id="breakdown-type">web</span>)</span>
<span id="breakdown-platform" class="font-medium text-[var(--ws-pricing-text)]">$0.0010/min</span>
</div>
<div class="flex justify-between">
<span class="text-[var(--ws-pricing-text-soft)]">LLM</span>
<span id="breakdown-llm" class="font-medium text-[var(--ws-pricing-text)]">$0.0030/min</span>
</div>
<div class="flex justify-between">
<span class="text-[var(--ws-pricing-text-soft)]">Speech-to-Text</span>
<span id="breakdown-stt" class="font-medium text-[var(--ws-pricing-text)]">$0.0034/min</span>
</div>
<div class="flex justify-between">
<span class="text-[var(--ws-pricing-text-soft)]">Text-to-Speech</span>
<span id="breakdown-tts" class="font-medium text-[var(--ws-pricing-text)]">$0.0150/min</span>
</div>
<div class="flex justify-between border-t border-[var(--ws-pricing-card-border)] pt-2">
<span class="font-semibold text-[var(--ws-pricing-text)]">Total</span>
<span id="breakdown-total" class="font-bold text-[var(--ws-pricing-highlight-bg)]">$0.0224/min</span>
</div>
</div>
</div>
<p class="mt-4 text-xs text-[var(--ws-pricing-text-soft)]">* Estimates are for illustration purposes. Actual costs may vary based on usage patterns and plan overages.</p>
</div>
</div>
</div>
<script>
const PLATFORM_RATES = { web: 0.001, phone: 0.003 };
let currentType = 'web';
function fmt(n) { return n.toFixed(4); }
function recalculate() {
const llm = parseFloat(document.getElementById('select-llm').value);
const stt = parseFloat(document.getElementById('select-stt').value);
const tts = parseFloat(document.getElementById('select-tts').value);
const platform = PLATFORM_RATES[currentType];
const total = platform + llm + stt + tts;
document.getElementById('cost-per-min').textContent = fmt(total);
document.getElementById('cost-per-hour').textContent = (total * 60).toFixed(2);
document.getElementById('cost-per-1k').textContent = (total * 1000).toFixed(2);
document.getElementById('breakdown-platform').textContent = '$' + fmt(platform) + '/min';
document.getElementById('breakdown-llm').textContent = '$' + fmt(llm) + '/min';
document.getElementById('breakdown-stt').textContent = '$' + fmt(stt) + '/min';
document.getElementById('breakdown-tts').textContent = '$' + fmt(tts) + '/min';
document.getElementById('breakdown-total').textContent = '$' + fmt(total) + '/min';
document.getElementById('breakdown-type').textContent = currentType === 'phone' ? 'SIP' : 'web';
}
document.querySelectorAll('.ws-type-btn').forEach((btn) => {
btn.addEventListener('click', () => {
currentType = btn.dataset.type;
document.querySelectorAll('.ws-type-btn').forEach((b) => {
const active = b.dataset.type === currentType;
b.setAttribute('aria-pressed', String(active));
b.classList.toggle('bg-[var(--ws-pricing-highlight-bg)]', active);
b.classList.toggle('text-white', active);
b.classList.toggle('text-[var(--ws-pricing-text-soft)]', !active);
});
document.getElementById('plan-included-web').classList.toggle('hidden', currentType !== 'web');
document.getElementById('plan-included-phone').classList.toggle('hidden', currentType !== 'phone');
recalculate();
});
});
['select-llm', 'select-stt', 'select-tts'].forEach((id) => {
document.getElementById(id).addEventListener('change', recalculate);
});
recalculate();
</script>
</section>
Details
Responsive Dark Mode Tailwind Only Copy & Paste Requires JS
Stable Published
pricingcalculatorusage-basedestimatoraivoicemodelsinteractivecosts
Slots
| Name | Required | Description |
|---|---|---|
| heading | No | Section title and description. |
| type-toggle | Yes | Toggle buttons for connection/usage type. |
| model-selectors | Yes | Dropdown menus for each billable model/service. |
| result | Yes | Live cost display with per-minute, per-hour, and per-1000-min rates. |
| breakdown | Yes | Itemized cost breakdown by service. |
| plan-table | No | Side-by-side plan comparison showing included minutes per tier. |
An interactive pricing calculator for usage-based billing. Users select a connection type (e.g. Web vs Phone) and choose from model dropdowns (LLM, STT, TTS) — the total per-minute cost updates instantly. A side panel shows included free minutes per plan tier. A breakdown table itemizes the cost per service. Inspired by LiveKit’s pricing estimator.