Skip to content

weijt606/livebrief

Repository files navigation

📋 Live Brief

English 简体中文 License: MIT Next.js 15

Turn a live conversation or meeting recording into a fact-checked, cited brief — and an optional audio briefing.

What it is

Meetings and conversations are full of claims you can't verify in the moment. Live Brief listens (mic or uploaded file), pulls out the entities, claims and topics, researches each claim on the web, marks every one as supported / unverified / contradicted with source links, and synthesises a concise, cited brief — optionally narrated as a single-host or two-host audio briefing.

It's a small Next.js app with no database. Every third-party call runs in a serverless route handler, and every API key is read server-side only (never NEXT_PUBLIC_*). It is vendor-flexible — point the LLM calls at any OpenAI-compatible endpoint — and degrades gracefully: with no keys at all, it runs end-to-end on a sample transcript and deterministic heuristics, so the whole flow is demoable offline.

How it works

mic / file ─▶ transcribe ─▶ distil ─▶ research ─▶ audit ─▶ report ─▶ 🔊
  1. Transcribe — chunked, pseudo-streaming speech-to-text from the mic or an uploaded file
  2. Distil — clean the transcript and extract entities, claims and topics
  3. Research — advanced web search on the subject and its claims
  4. Audit — cross-check each claim against sources → supported / unverified / contradicted, with links
  5. Report — synthesise a concise, cited brief
  6. Audio briefing (optional) — a single-narrator or two-host podcast of the brief, via text-to-speech

Every stage streams to an animated workflow diagram over Server-Sent Events (/api/orchestrate).

Features

  • 🔎 Claim-level auditing — each claim cross-checked and labelled supported / unverified / contradicted, with source links
  • 🎙️ Live or uploaded — chunked pseudo-streaming STT from the mic, or one-shot from a file
  • 🗣️ Speaker diarization — text-level turns you can rename, feeding the pipeline and the audio briefing
  • 🔊 Audio briefing — single-narrator or two-host podcast of the final brief
  • 📊 Animated workflow — every stage streamed live over Server-Sent Events
  • 🧩 Graceful degradation — runs fully offline on a sample transcript when no keys are set
  • 🔑 BYOK — bring your own keys from the UI; stored only in your browser, never on the server
  • 🔐 Keys never client-bundled — no database, no NEXT_PUBLIC_* secrets; requests carry keys as headers
  • 🔌 Vendor-flexible LLM — any OpenAI-compatible endpoint via base URL + model

Who it's for

Live Brief is built for fact-checking a spoken conversation against the open web. Its report is shaped as an investment-screening memo — team · traction · market · risks · recommendation, plus an NPS-style conviction score — so the sharpest fit is VC diligence, but the same pipeline serves any conversation full of checkable claims:

  • 🧑‍💼 VC / angel diligence — record a founder call and get a cited screening memo: which traction and market claims check out, which stay unverified, and a risk + conviction read. (This is the built-in report shape.)
  • 🎙️ Journalists & researchers — interview a source, then audit their factual claims against the web before publishing.
  • 👥 User & customer research — turn a call into a structured, sourced summary instead of re-listening to the recording.
  • 🧭 Meetings & panels — fact-check a recorded discussion and hand out a cited brief afterwards.
  • 🎧 On the go — generate a short audio briefing and listen back to the verdict while commuting.

Bring your own keys (BYOK)

Every key is optional and there are three ways to supply one — they're tried in this order:

  1. In the UI — click 🔑 Keys in the capture bar, paste your keys, hit Save. They're stored only in your browser (localStorage) and sent with each request as x-* headers. The server reads them per-request and never persists them.
  2. Server env — set them in .env.local (see Environment) as the fallback for any field a user leaves blank. Good for a shared/self-hosted instance.
  3. Nothing — the app still runs end-to-end on a sample transcript and deterministic heuristics.

Each pipeline stage degrades gracefully when its key is absent — using a heuristic fallback or being skipped with a note.

Providers (defaults are swappable)

The default column is what ships; the swap for column lists drop-in alternatives.

Capability Used for Default Swap for
LLM (OpenAI-compatible Chat Completions) distil · audit · report · diarize · podcast script OpenAI gpt-4o-mini Drop-in via base URL + model — Groq · Together · OpenRouter · DeepSeek · Mistral · xAI · local Ollama / vLLM / LM Studio
Web research research + claim audit Tavily Brave Search · Serper · Exa · SerpAPI · Bing — needs a small adapter in tavilySearch (different response shape)
Speech (STT + TTS) live/upload transcription · audio briefing Gradium STT: Whisper API · Deepgram · AssemblyAI · Groq Whisper · local faster-whisper · TTS: OpenAI TTS · ElevenLabs · Cartesia · Azure · edge-tts (free) — needs an adapter (bespoke API shape)

The LLM is fully swappable with zero code changes — point it at any OpenAI-compatible endpoint by setting the base URL and model (in the UI or via OPENAI_BASE_URL / EXTRACT_MODEL). Web research and speech use provider-specific request/response shapes, so swapping those means editing the matching helper in lib/agents.ts (tavilySearch, listVoices / ttsPcm, and the STT call in app/api/stt/route.ts).

Quick start

Requires Node.js ≥ 18.

git clone https://github.com/weijt606/livebrief.git
cd livebrief

npm install
cp .env.example .env.local   # fill in the keys you have (all optional)
npm run dev                  # http://localhost:3000

Production:

npm run build
npm run start

The project builds to a standalone server (output: "standalone") and is straightforward to containerise or deploy to any Node host (Vercel-ready).

Just want to see it? Run npm run dev, open the app, and click SampleRun — no keys required. The whole pipeline plays through on a built-in transcript.

Usage guide

Once the app is open at http://localhost:3000:

  1. (Optional) Add your keys. Click 🔑 Keys in the capture bar and paste any you have (OpenAI-compatible, Tavily, Gradium). Skip this to fall back to the server's env keys — or run the built-in sample with no keys at all. See BYOK.
  2. Get a transcript — three ways:
    • Sample — loads a built-in founder-interview transcript. Zero setup; the best first run.
    • Record — captures the mic and transcribes in near-real-time (needs a Gradium key, mic permission, and HTTPS or localhost).
    • Upload — drop in an audio file for one-shot transcription.
  3. (Optional) Name the brief. Add a topic line — e.g. "Interview with Halcyon Grid — founder Dr. Lena Brandt" — so the pipeline anchors the company and people even if the name is never said aloud.
  4. (Optional) Identify speakers. Split the transcript into turns and rename S1 / S2 to real people; the labelled transcript then feeds the pipeline and the audio briefing.
  5. Run. Watch the animated workflow stream each stage live over SSE: distil → research → audit → report. Stages whose key is missing are skipped with a note rather than failing.
  6. Read the brief. A cited screening memo — summary, team, traction, market, risks, recommendation — with a risk/conviction gauge. Every claim is tagged supported / unverified / contradicted and linked to its source.
  7. (Optional) Generate the audio briefing. Pick single-narrator or two-host, choose the voice(s) and a target length, and synthesise a spoken version of the brief (needs a Gradium key).

Environment

See .env.example. All variables are optional and server-side only — they act as the fallback for any key a user doesn't supply in the UI (see BYOK):

  • OPENAI_API_KEY — and optionally EXTRACT_MODEL, OPENAI_BASE_URL
  • TAVILY_API_KEY
  • GRADIUM_API_KEY

Never commit real keys; .env.local is gitignored. For a public/shared deployment you can leave these unset and let each visitor bring their own keys.

Project layout

app/
  api/orchestrate/route.ts          # SSE orchestrator — runs the 5-stage pipeline
  api/stt/route.ts                  # speech-to-text (chunked)
  api/diarize/route.ts              # speaker turns
  api/extract|research/route.ts     # standalone distil / web-search wrappers
  api/voices, api/podcast/{script,audio}/route.ts   # optional audio briefing
  page.tsx                          # hosts the LiveBrief UI
lib/
  agents.ts        # server-only: chat (JSON), web search, distil/audit/report, TTS
  orchestrate.ts   # shared SSE types + helpers (client + server safe)
  interview.ts     # deterministic entity/claim heuristics + sample transcript
  audio.ts         # client-only: decode → 16 kHz mono WAV, recorder mime pick
components/
  LiveBrief.tsx    # the orchestrated workflow UI
  ui/              # small presentational primitives

How streaming STT works

Browser MediaRecorder fragments aren't independently decodable, so the client keeps one mic stream and cycles short (~2–8 s) recorder sessions; each finished clip is decoded and resampled to 16 kHz mono WAV (lib/audio.ts) and posted to /api/stt, appending to a growing transcript. Upload and the sample path are one-shot. (No browser-direct WebSocket: the STT provider authenticates by API key, which must stay server-side.)

Tech

Next.js 15 (App Router) · React 19 · TypeScript · Tailwind CSS 3. No database. Streaming via Server-Sent Events with X-Accel-Buffering: no so it streams unbuffered through nginx.

License

MIT — © 2026 weijt606.

About

the live capture → brief flow

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages