Choose how to run this agent
Download Agent
Choose how you want to use this agent:
Use Security Settings Key (Recommended)
Use the API key you've already saved in Security Settings. Quick and convenient!
- No need to re-enter API key
- Works offline after download
- Centralized key management
No API key found in Security Settings. Add one now
Enter API Key Manually
Enter your API key now for this specific agent download.
- Use different key for this agent
- One-time use (not saved)
- Works offline after download
Configure Agent Encryption
Description
Upload a voice note or audio file and get an instant transcript, then ask questions about it — all on your device.
What this agent can do
Voice Transcriber is built from the Voice Transcriber template. Runs fully on your own device: llama.cpp compiled to WebAssembly, GPU-accelerated through WebGPU, with no API key and no server. After the one-time model download it works offline. Can run on OpenAI models with your own API key, encrypted in your browser. Can run on Anthropic Claude models with your own API key, encrypted in your browser.
Runs in the browser
- Speech to text. Transcribes speech in the browser with Whisper, from an uploaded recording or straight from the microphone.
- Text to speech. Can read its replies aloud using the browser's built-in speech synthesis.
Source Code
# Accumulated transcripts for this session: [{"source": name, "text": text}]
TRANSCRIPTS = []
async def _transcribe_audio(samples, name):
"""(JS-callable) Transcribe decoded audio samples and remember the result.
Underscore-prefixed so it is never exposed to the LLM as a tool. ``samples``
is a Float32Array of mono 16 kHz samples handed over by the page JS.
Returns the transcript text (for the UI).
"""
text = (await agentop_ml.transcribe(samples)).strip()
TRANSCRIPTS.append({"source": name, "text": text})
return text
async def process_user_query(query):
"""Answer questions / summarise grounded ONLY in the accumulated transcripts.
Overrides the default router so context is deterministic (small local
models are unreliable at deciding to call tools themselves).
"""
if not TRANSCRIPTS:
return (
"No audio has been transcribed yet - upload a voice note or "
"audio file first."
)
context = "\n\n".join(
f"[{i + 1}] (from {t['source']}) {t['text']}"
for i, t in enumerate(TRANSCRIPTS)
)
grounded_prompt = (
"Answer the QUESTION using ONLY the TRANSCRIPTS below. "
"If the answer is not in the transcripts, say you could not find it. "
"Cite transcript numbers like [1] where relevant.\n\n"
f"TRANSCRIPTS:\n{context}\n\nQUESTION: {query}"
)
# TEMPLATE_SYSTEM_PROMPT only exists as a JS global; the query bridge falls
# back to it when custom_prompt is empty (same idiom as the base template).
return await process_user_query_wllama(
grounded_prompt, globals().get("TEMPLATE_SYSTEM_PROMPT", "")
)
More by ozzo
Receipt & Invoice Extractor
Based on the Receipt & Invoice Extractor template.
New Hire Handbook Q&A
Based on the New Hire Handbook Q&A template.
Contract Plain-Language Explainer
Upload a contract and get it explained in plain language — obligations, fees, deadlines, exit claus…
WhatsApp Sales Copilot
Turn a raw WhatsApp chat export into a mini CRM — typed quotes, bookings, payments and boarding pas…
Private Quote & Material Estimator
Drop competing contractor quotes and compare them side by side — totals, inclusions, exclusions — t…
Messy Itinerary Travel Planner
Drop your messy pile of booking PDFs and trip notes and get a clean day-by-day itinerary — plus war…