Braindump

Not a quick voice memo app. Braindump is for the longer stuff — the 5-minute architecture walkthrough, the 30-minute problem deep-dive. Dump your brain, get it transcribed, then refine it with an inline AI rewriting chat.

Up to ~2h20m in a single recording

View on GitHub Architecture

How It Works

1

Record

Hit record in your browser. Pick your microphone. Talk for as long as you need — this is for real explanations, not quick memos, and a recording runs to about 2 hours 20 minutes. Give it a title.

2

Transcribe

A background worker transcribes your audio on-device with a local Whisper model — no API key, nothing leaves your machine. The text appears automatically when it's ready, and the audio file is deleted once it has been transcribed. Want the cloud? Switch to the OpenAI Whisper API with one env var.

3

Search

Full-text search across all your transcriptions. Find that idea you had last Tuesday.

4

Refine with AI

Below the transcript, an AI assistant locked to rewriting/editing streams suggestions inline. Toggle in your saved skills (tone, persona, format rules) and iterate via text or a quick voice button. Pick your provider — Anthropic, OpenAI, Google, and more.

Screenshots

The New Recording form: title field, microphone picker, and Record/Stop buttons.
1. Record Pick your microphone and hit record. Skip the title field if you want — the app will generate one from the transcript.
Recording detail page showing transcript and a Start AI chat button.
2. Read the transcript Whisper transcribes in the background. Once it’s done, the title fills in automatically and a Start AI chat button appears.
Inline rewriting chat with the transcript as the first user message and an assistant reply streaming in.
3. Refine with AI The transcript becomes the first message; the assistant streams its reply via Mercure. Toggle Skills in the header to load extra context.

Features

Long-Form Browser Recording

Choose your microphone, hit record, and keep talking — a single recording runs to about 2 hours 20 minutes. Mono 24 kbps Opus is transparent to Whisper (which downsamples to 16 kHz mono anyway) while being small enough that length stops being the constraint. Live waveform, elapsed timer, and a readout of how much recording time you have left.

Background Transcription

Audio is queued and transcribed asynchronously — on-device via whisper.cpp by default (no key), or the OpenAI Whisper API if you opt in. Real-time status updates via Server-Sent Events.

Full-Text Search

PostgreSQL full-text search with weighted ranking (title matches rank higher). Optional OpenSearch backend for larger deployments.

Inline Rewriting Chat

The transcript becomes the first message to a writing assistant locked to rewriting/editing — no shells, no execution, just text. Replies stream live over Mercure (every open tab sees the same deltas), markdown is rendered safely, and history persists across reloads. Voice input button with a mic device picker for quick refinements. Supports Anthropic, OpenAI, Google, Groq, Mistral, DeepSeek, xAI, and OpenRouter; each user brings their own API key, encrypted at rest (libsodium from APP_SECRET when self-hosted, Vault KMS on Symfony Cloud).

Skills

Reusable context documents you define once and toggle on per chat: tone guidelines ("slightly sarcastic, short sentences"), persona definitions ("formal bank email"), domain knowledge, writing rules. Activated skills get concatenated into the system prompt for every assistant call in that conversation — invisible in the message stream, but they shape every reply. Like agent skills in coding tools, but for writing.

Auto-Titled Recordings

If you don't type a title before recording, gpt-4.1-mini generates a short descriptive one from the transcript once Whisper finishes. The page header swaps in live via Mercure — no reload.

Enterprise-Ready Auth

Built-in form login plus OpenID Connect (OIDC) single sign-on. Connect Okta, Azure AD, Google Workspace, Keycloak, or any OIDC provider. Set OIDC_ENABLED=1 and three env vars to activate.

Admin Back-Office

EasyAdmin dashboard for user management. Create accounts, manage roles, view all recordings.

Why This Architecture

Workers for Transcription

OpenAI requests with large audio files can take minutes. Workers handle this outside the HTTP request path, so users aren't stuck waiting. The web request enqueues a job and returns immediately.

Mercure for Live Updates

Transcription status updates and rewriting-chat token deltas are published to per-resource topics. Browsers subscribe via SSE; PHP-FPM never holds the long-lived connection itself, so the app stays responsive.

Shared Network Storage

Audio files must be accessible by both the web app and the transcription worker. Symfony Cloud's network-storage service gives both containers access to the same files.

Audio Is Disposable

Whisper resamples everything to 16 kHz mono, so recordings are captured as mono 24 kbps Opus — same accuracy, a fifth of the bytes. Once the transcript is saved the audio is deleted, so storage never grows. Failed transcriptions keep their audio, with a download link.

PostgreSQL for Everything

Database, message queue (a durable Doctrine transport, woken by LISTEN/NOTIFY), and full-text search all in PostgreSQL. No extra services to manage. Swap in RabbitMQ or OpenSearch when you need to scale.

Vault KMS for API Keys

User API keys are encrypted at rest via Symfony Cloud's managed Vault KMS transit encryption. The encryption key never leaves the vault.

Tasks for Dependency Auto-Updates

A weekly Symfony Cloud task branches the app, runs composer update and the test suite on the branch, then auto-merges security fixes or emails a merge link — on its own on-demand container, not the production app.

Display, Don't Execute

The AI is locked to rewriting via a server-side system prompt. The app never runs anything it produces — replies are rendered as sanitized markdown (marked + DOMPurify). No shells, no tools, no eval.

Tech Stack

Symfony PHP Symfony AI Whisper (local + OpenAI) Symfony Messenger Mercure PostgreSQL EasyAdmin Stimulus Turbo marked + DOMPurify Vault KMS Symfony Cloud

Getting Started

Start with one command and nothing installed. Add hosted services later, one at a time — only if you want them.

1 · Run it — just Docker

No PHP, no database, no API keys. You get the whole app on localhost:8000 with on-device transcription, a bundled database and Mercure, and a seeded demo login (admin@example.com / password). First build takes a few minutes; later starts are quick.

git clone https://github.com/ralt/braindump
cd braindump && docker compose up --build

Prefer no Docker?

You only need PHP 8.4 and Composer — SQLite is the default, so there's no database to install. Add ffmpeg + whisper.cpp and grab a model for transcription.

composer install
php bin/console doctrine:migrations:migrate
php bin/console app:whisper:download
symfony server:start

2 · Add services as you grow

Everything below is optional — turn it on when you're ready, in any order. Secrets live in .env.local.

  • OpenAI — faster transcription, smart titles, and the rewriting chat (OPENAI_API_KEY).
  • PostgreSQL — swap SQLite for Postgres with one DATABASE_URL.
  • OpenSearch — scale full-text search beyond the database.
  • OIDC SSO — enterprise single sign-on next to form login (OIDC_ENABLED=1).
  • Symfony Cloud — deploy it all (Postgres, Mercure, Vault KMS, workers) with upsun push.