AI AgentsCase study

Notula: A Measured Two-Pass Meeting Notes Pipeline

Delivered scope

A transcript as system of record makes bilingual EN/ID summaries re-runnable without touching the audio again, with per-stage cost metering in the API

Conceptual artwork. Not a photograph or screenshot of the client's system.
Client
Open-source project
Category
AI Agents
Location
Remote
Completed
August 16, 2026

The problem

Most meeting-notes apps assert quality instead of measuring it. And architecturally they blur two things with very different costs: turning audio into a transcript is an expensive, slow call, while turning a transcript into a summary is cheap text-in, text-out. Without separating them, every summary-prompt improvement means paying for transcription again.

What we built

Notula — Indonesian for “meeting minutes” — is a two-pass pipeline: audio comes in, gets normalized by ffmpeg, is transcribed and diarized by Gemini in a single schema-constrained call, and is then summarized by DeepSeek from the transcript text into a TL;DR, decisions, action items with owners, and open questions — in English or Bahasa Indonesia.

The transcript is the system of record. Storing it makes summaries re-runnable: switch the summary language or improve the prompt, and only pass two re-executes — the state machine allows COMPLETED → SUMMARIZING → COMPLETED, and a failed re-run keeps the last good summary. Every stage reports wall time, tokens, and cost computed from the provider’s own usage metadata, surfaced in both the API and the UI.

Engineering decisions

Two providers, two reasons. Gemini is one of the few APIs that transcribes and diarizes audio in a single call; DeepSeek v4-flash is the cheapest capable text model, so it handles the re-runnable half of the pipeline.

Schema repair, not schema hope. json_object mode enforces JSON, not your schema. The parser validates field by field with errors naming the exact offending path, and the repair loop feeds that error plus the failed output back to the model — at most twice, then it fails loudly.

Long audio is split at silence. Recordings over 20 minutes are cut at silence-snapped boundaries with 15-second overlaps, transcribed per chunk, and merged — duplicates in the overlap are dropped, and generic speaker labels are reconciled across chunks.

The measured runs

On a 60-second public meeting recording through the live pipeline: $0.0050 total — $0.0046 to transcribe, $0.0003 to summarize, and an Indonesian re-summary added $0.0003 without touching the audio again. The honest observations were kept, not tidied: transcription latency varied 20x between two identical runs (traced to a stalled IPv6 connection — every provider client now carries explicit timeouts), and proper nouns were unstable across runs, exactly the failure mode the participant-roster feature exists to pin down.

The live eval (2026-08-16, 5 bilingual golden cases, judge deepseek-v4-flash): 5/5 passing, schema validity 1.00, faithfulness 1.00. The deliberately included no-decisions case correctly returned empty lists — no invented decisions. Every offline number from the mock provider is labelled as mock; it proves the machine, not the model.

Running it

git clone https://github.com/ridwanspace/notula && cd notula, then make install && make demo — the bundled sample audio is processed, pipeline events stream, and the per-stage cost table prints, all offline with zero API keys. make run opens the web UI at http://localhost:8000.

From this study to your project

Does your team face a similar problem?

Tell us about the workflow and its constraints. We start with a scope we can describe and verify.

Next case study

Prompt Injection Bench — Measuring Defenses