Self-hosted AI transcription interface for Plaud Note devices
Replace Plaud's $20/month AI subscription with your own OpenAI-compatible API keys
Quick Start β’ Features β’ Configuration β’ Contributing β’ License
- Self-Hosted - Complete control over your data and API keys
- Encrypted Credentials - AES-256-GCM encryption for all sensitive data
- No Vendor Lock-in - Your recordings, your infrastructure
- Universal AI Support - Works with ANY OpenAI-compatible API:
- OpenAI, Groq, Together AI, OpenRouter
- Local models: LM Studio, Ollama
- And any other OpenAI-compatible endpoint
- Browser Transcription - Client-side transcription using Transformers.js (zero API costs!)
- AI Title Generation - Automatically generate descriptive titles from transcriptions
- Multiple AI Providers - Configure and switch between different providers
- Flexible Storage - Local filesystem OR S3-compatible storage:
- AWS S3, Cloudflare R2, MinIO
- DigitalOcean Spaces, Wasabi, Backblaze B2
- Auto-Sync - Automatically download recordings from Plaud devices
- Configurable Intervals - Set your own sync schedule
- Multiple Export Formats - JSON, TXT, SRT, VTT subtitle formats
- Full Backups - Export all your data with one click
- Automation API & Webhooks - API keys,
/api/v1, and signed webhooks for integrations (docs) - Browser Notifications - Real-time alerts for new recordings
- Email Notifications - SMTP support for email alerts
- Zero-Config Deployment - Up and running with one Docker Compose command
- Guided Onboarding - Interactive setup wizard for new users
- Modern UI - Clean, hardware-inspired design with dark theme support
- Comprehensive Error Handling - Graceful failures with helpful error messages
- π³ Docker & Docker Compose
- ποΈ Plaud Note device with account at plaud.ai
- π€ OpenAI API key (or any OpenAI-compatible provider)
If you have Docker running, one line gets you a working OpenPlaud:
curl -fsSL https://openplaud.com/install.sh | shThe installer prompts for an install directory and APP_URL, downloads docker-compose.yml + env.example from the latest GitHub release, generates secrets (BETTER_AUTH_SECRET, ENCRYPTION_KEY, POSTGRES_PASSWORD), starts the stack, and waits for /api/health to return 200. Source: scripts/install.sh.
Pin to a specific version for reproducible installs:
curl -fsSL https://openplaud.com/v0.2.0/install.sh | shWindows: install via WSL2. The manual install below is the supported fallback for any environment where curl | sh isn't appropriate.
OpenPlaud ships as a Docker image on GitHub Container Registry. You don't need to clone the repo to self-host β just grab the compose file and env template from the latest release.
1. Create a directory and download the install files
mkdir openplaud && cd openplaud
curl -fLO https://github.com/openplaud/openplaud/releases/latest/download/docker-compose.yml
curl -fL https://github.com/openplaud/openplaud/releases/latest/download/env.example -o .env2. Generate secrets and edit .env
# Print two fresh secrets β paste them into .env
echo "BETTER_AUTH_SECRET=$(openssl rand -hex 32)"
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)"Open .env and set at minimum:
BETTER_AUTH_SECRET=<paste>
ENCRYPTION_KEY=<paste>
APP_URL=http://localhost:3000
# Optional β pin a specific OpenPlaud version for reproducible deploys.
# Leave as `latest` for newest stable, or use e.g. `0.1.0` / `dev`.
OPENPLAUD_VERSION=latest
# Optional β lock down sign-ups on a closed instance. When set, the
# /register page is disabled and better-auth rejects new sign-ups
# server-side. Existing users keep working. Defaults to false.
# DISABLE_REGISTRATION=true3. Start the application
docker compose up -d4. Access OpenPlaud
Open http://localhost:3000 and create your account. The onboarding wizard will guide you through connecting your Plaud device, configuring AI providers, storage, and sync preferences.
docker compose pull && docker compose up -dDatabase migrations run automatically on container start. To pin a version (recommended for production), set OPENPLAUD_VERSION=0.1.0 in .env. To roll back, set it to the previous tag and re-run the command above.
| Tag | What you get | Use when |
|---|---|---|
latest |
Newest stable release | Default β most users |
0.1.0, 0.1 |
Specific version / minor line | Production β pin for reproducibility |
dev |
Rolling build from main |
You want bleeding edge, accept breakage |
β οΈ mainis a rolling integration branch. Do not deploy by cloning and building frommainβ use the image tags above. See BRANCHING.md for details.
OpenPlaud signs into Plaud directly using your email β the same way the official Plaud app does:
- Enter the email address you use on plaud.ai
- Plaud sends you a verification code
- Enter the code in OpenPlaud β that's it
Your verification code is forwarded directly to Plaud's servers and never stored by OpenPlaud. Your Plaud email is stored alongside the connection so you can see which account is linked and switch accounts later β it lives only on your self-hosted instance. After login, the access token is encrypted (AES-256-GCM) and stored the same way. Your account region (Global, EU, Asia Pacific) is detected automatically.
π Open Source: Every line that handles your credentials is available for inspection β send-code route Β· verify route Β· encryption
The email-code flow above signs you into a Plaud account keyed off the email-password identity. If you originally created your Plaud account by tapping Continue with Google or Continue with Apple, that's a different identity on Plaud's side β even when both share the same email address. The email-code flow will look like it succeeded but sync will return zero recordings (#65).
Real Sign in with Google / Apple inside OpenPlaud is structurally blocked by Google's authorized-origins policy on Plaud's OAuth client. Two workarounds:
Easy path β OpenPlaud Connector browser extension. Install openplaud/connector (AGPL-3.0) and the connect screen surfaces a Sign in with Plaud button. You sign in to web.plaud.ai the way you normally do; the extension forwards the resulting access token back to OpenPlaud. No copy-pasting, no devtools.
Manual fallback β paste the token yourself. If you can't or won't install the extension:
- Open web.plaud.ai in another tab and sign in with Google or Apple as you normally would.
- Open browser devtools (F12 / Cmd+Option+I) β Network tab. Refresh the page.
- Click any request to a host starting with
api.plaud.ai,api-euc1.plaud.ai, orapi-apse1.plaud.ai. - Under Headers β Request Headers, find
Authorization. Copy everything afterBearer(the longeyJβ¦string). - In OpenPlaud, switch to the Paste token tab, pick the matching region (e.g. EU if the request host was
api-euc1.plaud.ai), and paste the token.
In both cases the token is encrypted at rest with AES-256-GCM.
Recordings are stored in Docker volume /app/audio. No additional configuration needed.
Pros: Zero setup, works out of the box
Cons: Limited to host machine storage
OpenPlaud supports ANY S3-compatible service. Configure through the settings UI or via environment variables.
ποΈ AWS S3
Endpoint: (leave blank)
Bucket: your-bucket-name
Region: us-east-1
Access Key ID: YOUR_KEY
Secret Access Key: YOUR_SECRET
π Cloudflare R2
Endpoint: https://<account-id>.r2.cloudflarestorage.com
Bucket: openplaud
Region: auto
Access Key ID: YOUR_KEY
Secret Access Key: YOUR_SECRET
Note: R2 offers 10GB free storage with no egress fees!
π³ MinIO (Self-hosted)
Endpoint: http://minio:9000
Bucket: openplaud
Region: us-east-1
Access Key ID: minioadmin
Secret Access Key: minioadmin
Perfect for self-hosted deployments!
π DigitalOcean Spaces
Endpoint: https://<region>.digitaloceanspaces.com
Bucket: your-space-name
Region: <region>
Access Key ID: YOUR_KEY
Secret Access Key: YOUR_SECRET
π§ Backblaze B2
Endpoint: https://s3.<region>.backblazeb2.com
Bucket: your-bucket-name
Region: <region>
Access Key ID: YOUR_KEY
Secret Access Key: YOUR_SECRET
Excellent pricing for long-term storage!
OpenPlaud uses the OpenAI SDK with custom baseURL support, making it compatible with any OpenAI-compatible API.
π‘ Configure multiple providers and switch between them based on your needs!
OpenAI (Official)
- Base URL: (leave blank)
- API Key: Your OpenAI key
- Models:
whisper-1,gpt-4o,gpt-4-turbo,gpt-3.5-turbo
Best for: Production quality, latest models
π Groq (Free Whisper API!)
- Base URL:
https://api.groq.com/openai/v1 - API Key: Your Groq key
- Models:
whisper-large-v3,llama-3.1-70b-versatile
Best for: Free transcription, ultra-fast inference
Together AI
- Base URL:
https://api.together.xyz/v1 - API Key: Your Together AI key
- Models:
whisper-large-v3,meta-llama/Llama-3-70b-chat-hf
Best for: Cost-effective, diverse model selection
OpenRouter (Access to Claude, GPT-4, Llama)
- Base URL:
https://openrouter.ai/api/v1 - API Key: Your OpenRouter key
- Models:
anthropic/claude-3.5-sonnet,openai/gpt-4-turbo,meta-llama/llama-3-70b-instruct
Best for: Access to multiple providers through one API
π LM Studio (Local Models)
- Base URL:
http://localhost:1234/v1 - API Key:
lm-studio(or any string) - Models: Name of your loaded model
Best for: 100% private, offline transcription
π¦ Ollama (Local Models)
- Base URL:
http://localhost:11434/v1 - API Key:
ollama(or any string) - Models:
whisper,llama3,mistral, etc.
Best for: Easy local model management
π Azure OpenAI
- Base URL:
https://<resource>.openai.azure.com/openai/deployments/<deployment> - API Key: Your Azure OpenAI key
- Models: Your deployment name
Best for: Enterprise compliance, Azure integration
OpenPlaud supports client-side transcription using Transformers.js, running Whisper models directly in your browser:
| Feature | Description |
|---|---|
| π° Zero API Costs | Runs entirely in the browser |
| π Privacy-First | Audio never leaves your device |
| π€ Models Available | whisper-tiny, whisper-base, whisper-small |
| π― Auto-Detected | Automatically available in transcription UI |
β οΈ Note: Browser transcription is slower than server-side but completely free and private. Perfect for sensitive recordings!
|
Frontend
Backend
|
AI & Transcription
Storage
Deployment
|
| Table | Purpose |
|---|---|
users & sessions |
Authentication (Better Auth) |
plaud_connections |
Encrypted Plaud bearer tokens |
plaud_devices |
Connected Plaud devices |
recordings |
Recording metadata + storage paths |
transcriptions |
AI-generated transcriptions |
ai_enhancements |
Summaries, action items, key points |
api_credentials |
Encrypted AI API keys (multiple providers) |
storage_config |
User storage preferences (local/S3) |
user_settings |
Sync, notifications, playback, export preferences |
- π AES-256-GCM encryption for sensitive data β API keys, Plaud bearer tokens, and user content (transcripts, summaries, action items, key points, recording titles, custom prompts). Defends against DB-only compromise (stolen backups, snapshot leaks). Not zero-knowledge: the server holds the key and decrypts at request time to run AI. Self-host with browser/local AI if you need true zero-knowledge. See docs/encryption-at-rest.md.
- π‘οΈ Better Auth for secure session management
- ποΈ PostgreSQL for reliable data persistence
- π³ Docker isolation for secure deployment
- π« No telemetry - Your data stays yours
OpenPlaud features a hardware-inspired design that brings the tactile feel of audio equipment to the web:
| Component | Description |
|---|---|
| ποΈ Rotary Knobs | Draggable 360Β° rotation with LED ring indicators |
| π‘ LED Indicators | Animated glow effects for status feedback |
| ποΈ Hardware Rack Modules | Authentic audio equipment aesthetic with mounting holes |
| π Waveform Display | Real-time audio visualization (Wavesurfer.js) |
| π Dark Theme | Easy on the eyes for long listening sessions |
| π§ Guided Onboarding | Interactive setup wizard for new users |
π‘ The UI is inspired by professional audio workstations, combining functionality with aesthetics.
See CONTRIBUTING.md for local setup, code standards, and the PR workflow. See BRANCHING.md for the branching and release model.
| Command | Description |
|---|---|
pnpm db:generate |
Generate new migration from schema changes |
bun db:migrate |
Apply migrations to database |
pnpm db:studio |
Open Drizzle Studio (visual database browser) |
# Run all tests
bun test
# Run specific test file
bun test src/tests/plaud.test.tsLive Plaud API tests are opt-in to avoid credential leaks and rate limits:
export PLAUD_BEARER_TOKEN="Bearer eyJhbGciOi..."
bun test src/tests/plaud.integration.test.tsπ‘ Integration tests run against the real Plaud API. Leave
PLAUD_BEARER_TOKENunset in CI to skip them.
src/
βββ app/ # Next.js App Router pages
β βββ (app)/ # Authenticated routes
β βββ (auth)/ # Authentication pages
β βββ api/ # API routes
βββ components/ # React components
β βββ ui/ # shadcn/ui components
β βββ dashboard/ # Feature components
βββ lib/ # Core business logic
β βββ ai/ # AI integration
β βββ plaud/ # Plaud API client
β βββ storage/ # Storage abstraction
β βββ transcription/ # Transcription logic
βββ db/ # Database schema & migrations
βββ types/ # TypeScript type definitions
π Authentication
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/auth/sign-up |
Create account |
POST |
/api/auth/sign-in |
Login |
POST |
/api/auth/sign-out |
Logout |
ποΈ Plaud Integration
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/plaud/auth/send-code |
Send OTP verification code to Plaud email |
POST |
/api/plaud/auth/verify |
Verify OTP and store encrypted connection |
GET |
/api/plaud/connection |
Check connection status |
DELETE |
/api/plaud/connection |
Disconnect Plaud account (preserves recordings) |
POST |
/api/plaud/sync |
Manual sync recordings |
π΅ Recordings
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/recordings |
List all recordings |
GET |
/api/recordings/[id] |
Get recording details |
GET |
/api/recordings/[id]/audio |
Stream audio file |
POST |
/api/recordings/[id]/transcribe |
Transcribe recording |
βοΈ Settings
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/settings/user |
Get user settings |
PUT |
/api/settings/user |
Update user settings |
PUT |
/api/settings/storage |
Configure storage |
GET |
/api/settings/ai/providers |
List AI providers |
POST |
/api/settings/ai/providers |
Add AI provider |
PUT |
/api/settings/ai/providers/[id] |
Update AI provider |
DELETE |
/api/settings/ai/providers/[id] |
Delete AI provider |
π€ Export & Backup
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/export?format=json|txt|srt|vtt |
Export recordings |
POST |
/api/backup |
Create backup of all user data |
π₯ Health
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/health |
Health check endpoint |
We welcome contributions from the community! Here's how you can help:
- π Report bugs - Found an issue? Open a bug report
- π‘ Request features - Have an idea? Create a feature request
- π Improve docs - Documentation PRs are always welcome
- π§ Submit PRs - See CONTRIBUTING.md for guidelines
- β Star the repo - Show your support!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes following our code standards
- Test your changes (
bun test) - Commit with Gitflow conventions (
git commit -m 'feat: add amazing feature') - Push to your fork (
git push origin feature/amazing-feature) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
AGPL-3.0 License β see LICENSE file for details
This means:
- β Free to use, modify, and distribute
- β Can use for commercial purposes
β οΈ Must open-source any modifications if you run it as a serviceβ οΈ Must include original license and copyright
Originally created by Perier. Now developed and maintained by the OpenPlaud community.
Made with β€οΈ for Plaud Note users who want full control over their transcriptions.
- π Documentation - Detailed guides and API references
- π Issues - Bug reports and feature requests
- π¬ Discussions - Community discussions
- π Changelog - Version history and release notes
If OpenPlaud is useful to you, consider:
- β Starring the repository
- π Reporting bugs and suggesting features
- π Contributing code or documentation
- π¬ Helping others in discussions