Enterprise-grade autonomous meeting assistant with calendar integration, real-time transcription, and intelligent analysis
Features • Architecture • Installation • Usage • API Reference • Documentation
Lumina is a sophisticated meeting intelligence platform that autonomously monitors your Google Calendar, joins scheduled meetings, and transforms conversations into structured, actionable insights. Built with a modular architecture, Lumina supports both cloud-based (Azure) and local processing (Whisper + Ollama/LLaMA.cpp) for maximum flexibility and privacy.
- Zero-Touch Authentication: Leverages persistent Chrome profiles—no repeated logins or 2FA prompts
- Calendar-Driven Automation: Intelligent scheduling system auto-joins meetings 1-2 minutes before start time
- Hybrid Processing Pipeline: Supports both Azure OpenAI and local LLM inference (Ollama, LLaMA.cpp)
- Anti-Bot Detection: Advanced human behavior simulation prevents Google Meet bot detection
- Local-First Storage: Optional local storage with Whisper transcription—no cloud dependency required
- Meeting Minutes Automation: Complete pipeline from audio capture to formatted minutes with email delivery
- Developer CLI: Comprehensive command-line interface for all operations
- Modular API Architecture: Clean, maintainable codebase with separated endpoint modules
| Feature | Description |
|---|---|
| 🗓️ Calendar Integration | Google Calendar API integration with automatic meeting detection |
| 🔐 Persistent Sessions | Uses existing Chrome profile with saved login state |
| 🎙️ Multi-Format Recording | High-quality audio recording (16kHz mono WAV) |
| 🤖 AI Transcription | Azure Speech-to-Text or local Whisper models |
| 📊 Meeting Analysis | Automated summarization, key points extraction, sentiment analysis |
| 📧 Email Delivery | Formatted meeting minutes sent via SMTP/Gmail API |
| ☁️ Cloud Storage | Azure Blob Storage integration with retry logic |
| 💾 Local Storage | File-based storage for complete data sovereignty |
| 🌐 REST API | Full-featured FastAPI server for programmatic control |
| 🧠 Local LLM Support | Ollama, LLaMA.cpp integration with Azure fallback |
| 🛡️ Bot Detection Avoidance | Randomized human-like interactions (mouse movements, clicks) |
| 📟 Developer CLI | Command-line interface for recordings, transcripts, minutes |
| 🗂️ Modular Architecture | Clean endpoint separation for maintainability |
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌─────────────┐
│ Meeting │───▶│ Whisper │───▶│ Local LLM │───▶│ Email + │
│ Recording │ │ Transcription│ │ Analysis │ │ File Export │
└─────────────┘ └──────────────┘ └─────────────┘ └─────────────┘
- Transcription: Local Whisper (tiny, base, small, medium, large)
- Analysis: Ollama (Llama3, Mistral), LLaMA.cpp (GGUF), or Azure GPT-4
- Output: Markdown, JSON, HTML email with attachments
- Content: Summary, key points & decisions, action items with owners
Lumina includes a modern, professional Next.js 15 web dashboard for complete visual control of the platform. Built with React 19, TypeScript, Tailwind CSS, and Shadcn UI components.
- 📊 Real-time Dashboard - Live meeting status, system stats, and recent activity
- 🎙️ Recording Library - Browse, play, and manage meeting recordings with built-in audio player
- 📝 Transcript Viewer - Search and view meeting transcripts with timestamps
- 📄 Meeting Minutes - AI-generated summaries with action items and markdown display
- 📅 Meeting Manager - Calendar integration with manual join dialog
- ⚙️ Settings Panel - No-code configuration for Calendar, AI Models, Email, and Recording
- 📈 Analytics - Meeting statistics and metrics (ready for charts)
- 🌓 Dark/Light Mode - Automatic theme switching with persistent preferences
- 📱 Responsive Design - Works perfectly on mobile, tablet, and desktop
Live meeting status, upcoming calendar events, and recent recordings at a glance
Interactive table with built-in audio player, download, and delete functionality
Powerful search with two-panel layout for browsing and reading transcripts
Markdown-formatted minutes with action items, key decisions, and meeting metadata
Tabbed settings interface for Calendar, AI Models, Email (SMTP), and Recording quality
- Framework: Next.js 15 with App Router
- UI Library: React 19 with TypeScript
- Styling: Tailwind CSS V4 + Shadcn UI components
- State Management: React Query (server state) + Zustand (client state)
- API Client: Axios with authentication interceptors
- Theme: next-themes for dark/light mode
- Notifications: Sonner toast system
- Audio: react-audio-player for playback
- Markdown: react-markdown for minutes display
# Navigate to frontend directory
cd lumina-ui
# Install dependencies
npm install
# Start development server
npm run dev
# Open http://localhost:3000📚 Full frontend documentation: See lumina-ui/README.md for complete setup instructions, API integration guide, and development details.
┌──────────────────────────────────────────────────────────────────┐
│ Lumina Core (FastAPI) │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────────┐ │
│ │ Calendar │ │ Chrome │ │ Audio/Video │ │
│ │ Service │ │ Manager │ │ Recording │ │
│ └────────────────┘ └────────────────┘ └──────────────────┘ │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────────┐ │
│ │ Local LLM │ │ Speech-to- │ │ Storage Layer │ │
│ │ Service │ │ Text (STT) │ │ (Local/Cloud) │ │
│ └────────────────┘ └────────────────┘ └──────────────────┘ │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────────┐ │
│ │ Meeting Minutes│ │ Email │ │ Bot Detection │ │
│ │ Generator │ │ Service │ │ Prevention │ │
│ └────────────────┘ └────────────────┘ └──────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
lumina-ai/
├── src/
│ ├── core/ # Core application modules
│ │ ├── api/ # Modular API endpoints
│ │ │ ├── __init__.py # Router exports
│ │ │ ├── meetings.py # Meeting & calendar endpoints
│ │ │ ├── recordings.py # Recording management
│ │ │ ├── transcripts.py # Transcription operations
│ │ │ ├── minutes.py # Minutes generation & processing
│ │ │ └── config.py # Configuration & status
│ │ ├── lumina.py # FastAPI server (refactored, modular)
│ │ ├── calendar_service.py # Google Calendar API integration
│ │ └── chrome_manager.py # Selenium Chrome automation
│ ├── recording/ # Audio/Video recording
│ │ ├── record_audio.py # System audio capture
│ │ ├── record_video.py # Screen recording
│ │ └── blob_storage_service.py # Azure Blob Storage
│ ├── transcription/ # Speech-to-text processing
│ │ ├── speech_to_text.py # Azure Speech Services
│ │ ├── local_speech_to_text.py # OpenAI Whisper
│ │ └── local_storage_service.py # Local file storage
│ ├── intelligence/ # LLM and analysis
│ │ ├── local_llm_service.py # Unified LLM interface
│ │ ├── meeting_minutes_generator.py # Minutes generation
│ │ └── email_service.py # Email delivery
│ └── automation/ # Meeting join automation
│ ├── join_meeting_auto.py # Auto-join with bot avoidance
│ ├── join_meeting_standalone.py # Chrome profile join
│ ├── quick_join.py # Minimal join script
│ ├── join_current_meeting.py # Current meeting detection
│ └── join_google_meet.py # Legacy login method
├── scripts/
│ └── process_recording.py # Complete processing pipeline
├── recordings/ # Meeting audio files
├── storage/ # Transcripts and minutes
│ ├── transcripts/
│ └── minutes/
├── lumina.py # Main entry point (FastAPI server)
├── lumina_cli.py # Developer CLI tool
├── requirements.txt
├── .env.example
└── README.md
| Module | Description |
|---|---|
| lumina.py | FastAPI server with calendar monitoring, REST endpoints, and meeting session management |
| calendar_service.py | Google Calendar API integration with OAuth 2.0 authentication |
| chrome_manager.py | Selenium-based Chrome automation with profile persistence and bot detection avoidance |
| Module | Description |
|---|---|
| record_audio.py | System audio capture using sounddevice (16kHz mono WAV) |
| record_video.py | Screen recording with OpenCV (optional) |
| blob_storage_service.py | Azure Blob Storage integration with retry logic |
| Module | Description |
|---|---|
| speech_to_text.py | Azure Speech Services integration for cloud transcription |
| local_speech_to_text.py | OpenAI Whisper local transcription (privacy-first) |
| local_storage_service.py | File-based local storage implementation |
| Module | Description |
|---|---|
| local_llm_service.py | Unified interface for Ollama, LLaMA.cpp, Azure GPT-4 with automatic fallback |
| meeting_minutes_generator.py | Structured meeting minutes creation with summary, key points, action items |
| email_service.py | SMTP/Gmail API email delivery with HTML formatting and attachments |
| Script | Description |
|---|---|
| join_meeting_auto.py | Automated meeting join with human behavior simulation |
| join_meeting_standalone.py | Single meeting join using existing Chrome profile |
| quick_join.py | Minimal meeting join script for testing |
| join_current_meeting.py | Detect and join currently running meeting |
| join_google_meet.py | Legacy implementation with email/password login |
Backend Framework
- FastAPI 0.100+ (async REST API)
- Uvicorn (ASGI server)
Browser Automation
- Selenium WebDriver 4.21+
- Chrome/Chromium (headless/headed modes)
Audio/Video Processing
- sounddevice (audio capture)
- OpenCV (video recording)
- PyAudio (audio streaming)
Machine Learning
- OpenAI Whisper (local transcription)
- Azure OpenAI GPT-4 (cloud analysis)
- Ollama (local LLM server)
- llama-cpp-python (GGUF model inference)
- LangChain (LLM orchestration)
Cloud Services
- Azure Speech Services (transcription)
- Azure Blob Storage (recordings)
- Google Calendar API (scheduling)
Data Formats
- WAV (audio recordings)
- JSON (structured data)
- Markdown (meeting minutes)
- HTML (email formatting)
- Python: 3.8 or higher
- Chrome Browser: With active Google account login
- Operating System: Linux (tested), macOS, Windows
- RAM: 8GB minimum (16GB recommended for local LLM)
- Disk Space: 10GB for dependencies and models
# 1. Clone repository
git clone https://github.com/h9-tec/lumina-ai.git
cd lumina-ai
# 2. Create virtual environment
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# 3. Install dependencies
pip install -r requirements.txt
# 4. Configure environment
cp .env.example .env
# Edit .env with your credentials
# 5. Set up Google Calendar API
# Download credentials.json from Google Cloud Console
# Place in project root
# 6. Authenticate with Google Calendar
python src/core/calendar_service.py
# 7. Install Ollama (optional, for local LLM)
curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3
# 8. Run Lumina
python lumina.pya. Create Google Cloud Project
- Navigate to Google Cloud Console
- Create new project: "Lumina"
- Enable Google Calendar API
b. Create OAuth Credentials
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Configure consent screen (External, add your email)
- Application type: Desktop app
- Download JSON, rename to
credentials.json - Place in project root directory
c. First-Time Authentication
python calendar_service.py- Opens browser for Google login
- Grants calendar read permissions
- Saves
token.picklefor future use
For Cloud Processing:
a. Azure OpenAI
- Create Azure OpenAI resource
- Deploy GPT-4 model
- Note: API key, endpoint, deployment name
b. Azure Blob Storage
- Create Storage Account
- Create container: "meeting-recordings"
- Copy access key
c. Azure Speech Services
- Create Speech resource
- Copy API key and region
Option A: Ollama (Recommended)
# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh
# Pull models
ollama pull llama3 # 4.7GB - Balanced
ollama pull mistral # 4.1GB - Fast
ollama pull phi3 # 2.3GB - Lightweight
ollama pull llama3:70b # 40GB - Highest quality
# Test
ollama run llama3Option B: LLaMA.cpp
# Download GGUF model
wget https://huggingface.co/TheBloke/Llama-3-8B-Instruct-GGUF/resolve/main/llama-3-8b-instruct.Q4_K_M.gguf \
-O ~/models/llama3.gguf
# Configure path in .env
LLAMACPP_MODEL_PATH="/home/user/models/llama3.gguf"Gmail Setup:
- Enable 2-Factor Authentication: Google Security
- Create App Password: App Passwords
- Add to
.env:SMTP_USER="your-email@gmail.com" SMTP_PASSWORD="16-char-app-password"
Complete .env configuration reference:
# ============================================
# CHROME CONFIGURATION
# ============================================
# Chrome profile to use (Default, Profile 1, Profile 2, etc.)
CHROME_PROFILE_NAME="Default"
# ============================================
# CALENDAR INTEGRATION
# ============================================
# Auto-start calendar monitoring on launch
AUTO_START_CALENDAR_MONITOR="true"
# ============================================
# STORAGE CONFIGURATION
# ============================================
# Local storage path for recordings and outputs
LOCAL_STORAGE_PATH="./storage"
# Azure Blob Storage (optional)
STORAGE_ACCOUNT_NAME="your_storage_account"
STORAGE_ACCOUNT_KEY="your_storage_key"
CONTAINER_NAME="meeting-recordings"
# ============================================
# WHISPER CONFIGURATION
# ============================================
# Model size: tiny, base, small, medium, large
WHISPER_MODEL="base"
# ============================================
# LOCAL LLM CONFIGURATION
# ============================================
# Provider: ollama, llamacpp, azure
LOCAL_LLM_PROVIDER="ollama"
# Model name for Ollama
LOCAL_LLM_MODEL="llama3"
# Model path for LLaMA.cpp
LLAMACPP_MODEL_PATH="/path/to/model.gguf"
# ============================================
# AZURE OPENAI (FALLBACK)
# ============================================
OPENAI_API_KEY="your_azure_openai_key"
API_VERSION="2024-08-01-preview"
AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
# ============================================
# AZURE SPEECH SERVICES
# ============================================
AZURE_SPEECH_KEY="your_speech_key"
AZURE_SPEECH_REGION="eastus"
# ============================================
# EMAIL CONFIGURATION
# ============================================
SMTP_SERVER="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="your-email@gmail.com"
SMTP_PASSWORD="your-app-password"| Model | Size | Speed | Accuracy | Use Case |
|---|---|---|---|---|
| tiny | 39 MB | Fastest | Basic | Testing, development |
| base | 74 MB | Fast | Good | Default, most meetings |
| small | 244 MB | Medium | Better | Important meetings |
| medium | 769 MB | Slow | High | Critical transcription |
| large | 1.5 GB | Slowest | Best | Professional, archival |
| Model | Size | RAM | Speed | Quality | Best For |
|---|---|---|---|---|---|
| phi3 | 2.3 GB | 4 GB | Fast | Good | Quick summaries, low-resource |
| mistral | 4.1 GB | 6 GB | Fast | Great | General purpose, fast inference |
| llama3 | 4.7 GB | 8 GB | Medium | Great | Balanced (recommended) |
| llama3:70b | 40 GB | 48 GB | Slow | Excellent | Enterprise, highest quality |
Start automatic calendar monitoring:
python lumina.pyBehavior:
- Polls calendar every 60 seconds
- Detects meetings with Google Meet links
- Auto-joins 1-2 minutes before start time
- Records and processes automatically
- Generates minutes and sends emails
Output:
✨ Lumina - Meeting Assistant ✨
Automatically joins and records Google Meet sessions
🔍 Starting calendar monitor...
📅 Checking calendar for upcoming meetings...
📅 Found 3 upcoming meetings
🔗 Meeting: "Team Standup" starts in 1.5 minutes
🚀 Joining meeting...
Start Lumina server:
python lumina.pyJoin specific meeting:
curl -X POST "http://localhost:8000/join-meeting/" \
-H "Content-Type: application/json" \
-d '{
"meetLink": "https://meet.google.com/xxx-xxxx-xxx",
"meetingId": "team-standup-2025-11-14",
"autoRecord": true
}'Check status:
curl http://localhost:8000/status/Get upcoming meetings:
curl http://localhost:8000/calendar/upcoming-meetings/Start/Stop calendar monitor:
# Start
curl -X POST http://localhost:8000/calendar/start-monitor/
# Stop
curl -X POST http://localhost:8000/calendar/stop-monitor/The Developer CLI provides a comprehensive command-line interface for all operations:
View all commands:
python lumina_cli.py --helpStart server:
# Start FastAPI server
python lumina_cli.py server
# Start with auto-reload (development)
python lumina_cli.py server --reload --port 8080Manage recordings:
# List all recordings
python lumina_cli.py recordings list
# Get recording info
python lumina_cli.py recordings info 20251114_194510
# Delete a recording
python lumina_cli.py recordings delete 20251114_194510Transcription:
# Transcribe a recording
python lumina_cli.py transcribe start 20251114_194510
# Use specific Whisper model
python lumina_cli.py transcribe start 20251114_194510 --model medium
# List all transcripts
python lumina_cli.py transcribe list
# View transcript content
python lumina_cli.py transcribe show 20251114_194510Meeting minutes:
# Generate minutes from transcript
python lumina_cli.py minutes generate 20251114_194510
# Use specific LLM provider
python lumina_cli.py minutes generate 20251114_194510 \
--provider ollama --model mistral
# List all minutes
python lumina_cli.py minutes list
# View minutes
python lumina_cli.py minutes show 20251114_194510
# Email minutes to recipients
python lumina_cli.py minutes email 20251114_194510 \
team@company.com manager@company.com \
--subject "Team Meeting Minutes"Complete pipeline:
# Process recording: Transcribe → Generate Minutes → Send Email
python lumina_cli.py process 20251114_194510
# Skip specific steps
python lumina_cli.py process 20251114_194510 --skip-email
python lumina_cli.py process 20251114_194510 --skip-transcribe
# Use specific LLM
python lumina_cli.py process 20251114_194510 \
--provider ollama --model llama3Configuration:
# View current configuration
python lumina_cli.py configOutput example:
⚙️ Lumina Configuration:
🧠 LLM:
Provider: ollama
Model: llama3
🎙️ Whisper:
Model: base
📧 Email:
Configured: ✅
Server: smtp.gmail.com
User: your-email@gmail.com
🗓️ Calendar:
Auto-start: true
🌐 Chrome:
Profile: Default
Quick join (no API server):
python src/automation/join_meeting_auto.py \
"https://meet.google.com/xxx-xxxx-xxx" "Bot Name"Process existing recording:
python scripts/process_recording.py recordings/meeting.wav \
--title "Q4 Planning Meeting" \
--email "team@company.com,manager@company.com" \
--llm-provider ollama \
--llm-model llama3Arguments:
--title: Meeting title--email: Comma-separated recipient list--llm-provider:ollama,llamacpp,azure--llm-model: Model name (for Ollama)--no-email: Skip email delivery--no-save: Skip file saving
Process recording end-to-end:
# Basic usage
python process_recording.py recordings/20251114_194510.wav
# With all options
python process_recording.py recordings/team_meeting.wav \
--title "Sprint Review & Retrospective" \
--email "dev-team@company.com,product@company.com" \
--llm-provider ollama \
--llm-model mistralPipeline stages:
- ✅ Whisper transcription (local)
- ✅ LLM analysis (Ollama/LLaMA.cpp/Azure)
- ✅ Markdown/JSON export
- ✅ HTML email with attachments
Example output:
╔═══════════════════════════════════════════════════════════╗
║ 🌟 Lumina - Meeting Recording Processor ║
║ Processing: Sprint Review & Retrospective ║
╚═══════════════════════════════════════════════════════════╝
📝 Step 1/4: Transcribing audio with Whisper...
Loading Whisper model: base
Transcribing: team_meeting.wav
✅ Transcription complete (4532 characters)
💾 Transcript saved: ./storage/transcripts/transcript_20251114_194510.txt
🤖 Step 2/4: Generating minutes with ollama...
📝 Generating meeting minutes...
✅ Minutes generated successfully!
✅ Minutes generated!
💾 Step 3/4: Saving minutes to files...
💾 Minutes saved to: ./storage/minutes/meeting_minutes_20251114_194510.md
💾 Minutes (JSON) saved to: ./storage/minutes/meeting_minutes_20251114_194510.json
✅ Saved 3 files
📧 Step 4/4: Sending minutes to 2 recipient(s)...
✅ Email sent successfully!
============================================================
📊 PROCESSING COMPLETE
============================================================
Meeting: Sprint Review & Retrospective
Transcript length: 4532 characters
Summary: The team reviewed completed stories, discussed blockers...
Key points: 8
Action items: 5
Files saved: 3
Email sent: ✅ Yes
============================================================
POST /join-meeting/
Join a Google Meet session.
Request:
{
"meetLink": "https://meet.google.com/xxx-xxxx-xxx",
"meetingId": "optional-custom-id",
"autoRecord": true
}Response:
{
"status": "success",
"meetingId": "meeting-20251114-194510",
"recordingPath": "recordings/meeting-20251114-194510.wav",
"message": "Joined meeting successfully"
}GET /calendar/upcoming-meetings/
Get list of upcoming meetings with Google Meet links.
Query Parameters:
max_results: Maximum meetings to return (default: 10)time_min: Start time (ISO 8601, default: now)time_max: End time (ISO 8601, default: 24h from now)
Response:
{
"meetings": [
{
"id": "event-id-123",
"summary": "Team Standup",
"start": "2025-11-14T10:00:00Z",
"meetLink": "https://meet.google.com/abc-defg-hij"
}
],
"total": 3
}POST /calendar/start-monitor/
Start automatic calendar monitoring.
Response:
{
"status": "started",
"message": "Calendar monitor started"
}POST /calendar/stop-monitor/
Stop automatic calendar monitoring.
Response:
{
"status": "stopped",
"message": "Calendar monitor stopped"
}GET /status/
Get system status.
Response:
{
"status": "running",
"calendar_monitor_active": true,
"active_meetings": 1,
"uptime": "2h 34m",
"version": "2.0.0"
}GET /api/recordings/
List all available audio recordings.
Response:
{
"recordings": [
{
"meeting_id": "20251114_194510",
"file_path": "recordings/20251114_194510.wav",
"size_mb": 45.2,
"duration_seconds": 3600,
"created_at": "2025-11-14T19:45:10Z"
}
],
"total": 5
}GET /api/recordings/{meeting_id}
Get detailed information about a specific recording.
Response:
{
"meeting_id": "20251114_194510",
"file_path": "recordings/20251114_194510.wav",
"size_mb": 45.2,
"duration_seconds": 3600,
"created_at": "2025-11-14T19:45:10Z",
"format": "wav",
"sample_rate": 16000,
"channels": 1
}DELETE /api/recordings/{meeting_id}
Delete a specific recording.
Response:
{
"status": "success",
"message": "Recording deleted successfully",
"meeting_id": "20251114_194510"
}POST /api/transcripts/transcribe/{meeting_id}
Transcribe a recording using local Whisper.
Query Parameters:
model: Whisper model size (default: "base") - Options: tiny, base, small, medium, large
Response:
{
"status": "processing",
"message": "Transcription started in background",
"meeting_id": "20251114_194510",
"model": "base"
}GET /api/transcripts/
List all available transcripts.
Response:
{
"transcripts": [
{
"meeting_id": "20251114_194510",
"file_path": "storage/transcripts/20251114_194510.txt",
"word_count": 5420,
"created_at": "2025-11-14T20:15:30Z"
}
],
"total": 3
}GET /api/transcripts/{meeting_id}
Get the full transcript for a specific meeting.
Response:
{
"meeting_id": "20251114_194510",
"transcript": "Welcome everyone to today's meeting...",
"word_count": 5420,
"created_at": "2025-11-14T20:15:30Z"
}POST /api/minutes/generate/{meeting_id}
Generate meeting minutes from a transcript using local LLM.
Query Parameters:
provider: LLM provider (default: "ollama") - Options: ollama, llamacpp, azuremodel: Model name (default: "llama3")
Response:
{
"status": "processing",
"message": "Minutes generation started in background",
"meeting_id": "20251114_194510",
"provider": "ollama",
"model": "llama3"
}GET /api/minutes/
List all available meeting minutes.
Response:
{
"minutes": [
{
"meeting_id": "20251114_194510",
"meeting_title": "Q4 Planning Session",
"meeting_date": "2025-11-14",
"md_file": "storage/minutes/20251114_194510.md",
"json_file": "storage/minutes/20251114_194510.json",
"created_at": "2025-11-14T20:30:45Z"
}
],
"total": 2
}GET /api/minutes/{meeting_id}
Get meeting minutes in markdown or JSON format.
Query Parameters:
format: Output format (default: "markdown") - Options: markdown, json
Response (markdown):
{
"meeting_id": "20251114_194510",
"format": "markdown",
"content": "# Meeting Minutes\n\n## Meeting Information\n..."
}Response (json):
{
"meeting_id": "20251114_194510",
"format": "json",
"content": {
"meeting_title": "Q4 Planning Session",
"meeting_date": "2025-11-14",
"attendees": ["Alice", "Bob", "Charlie"],
"key_points": [...],
"action_items": [...],
"decisions": [...]
}
}POST /api/minutes/email/{meeting_id}
Send meeting minutes via email.
Request:
{
"recipients": ["team@company.com", "manager@company.com"],
"subject": "Meeting Minutes: Q4 Planning",
"include_attachment": true
}Response:
{
"status": "success",
"message": "Meeting minutes sent successfully",
"recipients": ["team@company.com", "manager@company.com"],
"meeting_id": "20251114_194510"
}POST /api/minutes/process/{meeting_id}
Complete processing pipeline: Transcribe → Generate Minutes → Send Email.
Query Parameters:
skip_transcribe: Skip transcription if already done (default: false)skip_minutes: Skip minutes generation (default: false)skip_email: Skip email sending (default: false)provider: LLM provider (default: "ollama")model: LLM model (default: "llama3")recipients: Comma-separated email addresses
Response:
{
"status": "processing",
"message": "Complete pipeline started in background",
"meeting_id": "20251114_194510",
"steps": ["transcribe", "generate_minutes", "send_email"]
}GET /api/config/
Get current system configuration.
Response:
{
"version": "2.0.0",
"llm": {
"provider": "ollama",
"model": "llama3",
"available_providers": ["ollama", "llamacpp", "azure"]
},
"whisper": {
"model": "base",
"available_models": ["tiny", "base", "small", "medium", "large"]
},
"storage": {
"recordings_dir": "recordings/",
"transcripts_dir": "storage/transcripts/",
"minutes_dir": "storage/minutes/"
},
"email": {
"configured": true,
"smtp_server": "smtp.gmail.com",
"smtp_port": 587
},
"calendar": {
"enabled": true,
"monitor_active": true,
"check_interval_minutes": 1
}
}from local_llm_service import LocalLLMService
# Initialize with Ollama
llm = LocalLLMService(provider="ollama", model_name="llama3")
# Generate response
response = llm.generate("Summarize this meeting transcript...")
# Automatic fallback to Azure if local LLM failsfrom meeting_minutes_generator import MeetingMinutesGenerator
# Initialize
generator = MeetingMinutesGenerator(
llm_provider="ollama",
model_name="mistral"
)
# Generate minutes
minutes = generator.generate_minutes(
transcript="Meeting transcript text...",
meeting_title="Q4 Planning",
meeting_date="2025-11-14"
)
# Save to files
md_path = generator.save_minutes_to_file(minutes)
json_path = generator.save_minutes_to_json(minutes)from email_service import EmailService
# Initialize
email_service = EmailService(use_gmail_api=False)
# Send minutes
success = email_service.send_meeting_minutes(
to_emails=["team@company.com"],
subject="Meeting Minutes: Q4 Planning",
minutes_markdown=markdown_content,
minutes_file_path="./storage/minutes/meeting.md"
)Lumina/
├── README.md # This file
├── CLAUDE.md # AI assistant instructions
├── SETUP_GUIDE.md # Detailed setup guide
├── requirements.txt # Python dependencies
├── .env # Environment configuration
├── .gitignore # Git ignore rules
│
├── lumina.py # Main FastAPI application
├── calendar_service.py # Google Calendar integration
├── chrome_manager.py # Chrome automation
│
├── record_audio.py # Audio recording
├── record_video.py # Video recording (optional)
│
├── speech_to_text.py # Azure STT
├── local_speech_to_text.py # Local Whisper STT
│
├── local_llm_service.py # Local LLM abstraction
├── meeting_minutes_generator.py # Minutes generation
├── email_service.py # Email delivery
├── process_recording.py # Complete pipeline script
│
├── blob_storage_service.py # Azure Blob Storage
├── local_storage_service.py # Local file storage
│
├── join_meeting_auto.py # Auto join with bot detection
├── join_meeting_standalone.py # Standalone Chrome profile join
├── quick_join.py # Minimal join script
├── join_current_meeting.py # Join from calendar
├── join_google_meet.py # Legacy login-based join
│
├── credentials.json # Google OAuth credentials (you create)
├── token.pickle # Generated after first auth
│
└── storage/ # Local storage directory
├── recordings/ # Meeting audio files
├── transcripts/ # Transcription text files
└── minutes/ # Meeting minutes (MD + JSON)
Google Meet implements anti-bot detection. Lumina counters this with:
Techniques:
- Randomized mouse movements (every 20-40 seconds)
- Occasional clicks (30% probability)
- Random key presses (20% probability)
- Variable timing patterns
Implementation:
def simulate_human_behavior(driver):
"""Simulate human-like interactions"""
actions = ActionChains(driver)
# Random mouse movement
body = driver.find_element(By.TAG_NAME, 'body')
x_offset = random.randint(-100, 100)
y_offset = random.randint(-100, 100)
actions.move_to_element_with_offset(body, x_offset, y_offset).perform()
# Occasional click
if random.random() < 0.3:
actions.click().perform()Lumina uses persistent Chrome profiles to avoid repeated authentication.
Profile Paths:
- Linux:
~/.config/google-chrome - macOS:
~/Library/Application Support/Google/Chrome - Windows:
%USERPROFILE%\AppData\Local\Google\Chrome\User Data
Profile Detection:
# Open Chrome and visit
chrome://version/
# Look for "Profile Path"
# Example: .../Chrome/User Data/Default
# ^^^^^^^^ This is the profile nameLocal Storage (Privacy-First):
from local_storage_service import LocalStorageService
storage = LocalStorageService(base_path="./storage")
storage.save_recording("meeting.wav", audio_data)
storage.save_transcript("meeting.txt", transcript)Azure Blob Storage (Cloud):
from blob_storage_service import BlobStorageService
storage = BlobStorageService()
storage.upload_file("meeting.wav", container="recordings")Extend LocalLLMService to add custom providers:
class LocalLLMService:
def _initialize_custom_provider(self):
"""Add your custom LLM provider"""
from custom_llm import CustomLLM
self.llm = CustomLLM(api_key=os.getenv('CUSTOM_API_KEY'))GPU Acceleration:
# Install CUDA-enabled PyTorch
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu118
# Whisper will automatically use GPUModel Selection:
# Fast (development): tiny
WHISPER_MODEL="tiny"
# Balanced (production): base
WHISPER_MODEL="base"
# High-accuracy (archival): large
WHISPER_MODEL="large"Systemd Service (Linux):
# /etc/systemd/system/lumina.service
[Unit]
Description=Lumina Meeting Assistant
After=network.target
[Service]
Type=simple
User=youruser
WorkingDirectory=/path/to/Lumina
ExecStart=/path/to/Lumina/venv/bin/python lumina.py
Restart=always
[Install]
WantedBy=multi-user.targetEnable:
sudo systemctl enable lumina
sudo systemctl start luminaError:
selenium.common.exceptions.InvalidArgumentException: invalid argument: user data directory is already in use
Solution:
- Close all Chrome windows
- Kill Chrome processes:
pkill -9 chrome(Linux) - Verify profile name in
.env:CHROME_PROFILE_NAME
Error:
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.')
Solution:
- Delete
token.pickle - Re-authenticate:
python calendar_service.py - Verify
credentials.jsonexists
Error:
RuntimeError: CUDA out of memory
Solution:
- Use smaller model:
WHISPER_MODEL="tiny" - Reduce audio length
- Add swap space (Linux):
sudo fallocate -l 4G /swapfile
Error:
ConnectionError: Cannot connect to Ollama server
Solution:
# Check if Ollama is running
ollama list
# Start Ollama
ollama serve
# Verify model exists
ollama pull llama3Error:
SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted')
Solution:
- Use Gmail App Password (not account password)
- Enable 2FA: Google Security
- Create app password: App Passwords
Checklist:
- ✅ Lumina running:
python lumina.py - ✅ Calendar monitor active: Check logs for "Starting calendar monitor"
- ✅ Meeting has Google Meet link
- ✅ Meeting starts within 2 minutes
- ✅ Chrome is closed before starting Lumina
- ✅ Logged into Chrome profile
Enable verbose logging:
# Add to lumina.py
import logging
logging.basicConfig(level=logging.DEBUG)Documentation:
- Backend setup instructions are in this README (see Quick Start and Installation sections above)
- Frontend documentation: lumina-ui/README.md
- API endpoints and usage: See FastAPI Endpoints section above
Support:
- Search GitHub Issues for similar problems
- Create a new issue with:
- Full error message
- Python version (
python --version) - OS details (Windows/macOS/Linux)
- Steps to reproduce
- Relevant logs from the console
Common Issues:
- Calendar authentication: Delete
token.pickleand re-runpython calendar_service.py - Chrome profile locked: Close all Chrome windows before running
- Audio not recording: Check system audio permissions and sounddevice setup
Minimum (Cloud Processing):
- CPU: 2 cores
- RAM: 4 GB
- Disk: 5 GB
- Network: 10 Mbps
Recommended (Local LLM):
- CPU: 4+ cores
- RAM: 16 GB
- Disk: 20 GB SSD
- GPU: Optional (8GB VRAM for GPU acceleration)
Enterprise (High-Volume):
- CPU: 8+ cores
- RAM: 32 GB
- Disk: 100 GB NVMe SSD
- GPU: NVIDIA RTX 3090 or better
Whisper Transcription Speed (1 hour audio):
tinymodel: ~2 minutes (CPU)basemodel: ~5 minutes (CPU)largemodel: ~20 minutes (CPU) | ~5 minutes (GPU)
LLM Analysis Speed (5000 token transcript):
- Ollama Llama3: ~30 seconds
- LLaMA.cpp Q4: ~45 seconds
- Azure GPT-4: ~10 seconds
- Local Storage: All data stays on your machine
- Local LLM: No cloud API calls for analysis
- Encrypted Transit: HTTPS for all API calls
- Token Storage: OAuth tokens stored locally in
token.pickle
- Never commit credentials: Use
.envand.gitignore - Rotate API keys: Regular key rotation policy
- Limit OAuth scopes: Only request needed calendar permissions
- Secure storage: Encrypt recordings at rest (optional)
- Access control: Run Lumina under dedicated user account
- GDPR: Local storage option for EU data residency
- HIPAA: Not HIPAA-compliant by default (requires encryption)
- SOC 2: Use Azure services with SOC 2 certification
We welcome contributions! Please follow these guidelines:
# Fork repository
git clone https://github.com/h9-tec/lumina-ai.git
cd lumina-ai
# Create branch
git checkout -b feature/your-feature-name
# Install dev dependencies
pip install -r requirements.txt
pip install pytest black flake8
# Make changes
# ...
# Run tests
pytest
# Format code
black .
flake8 .
# Commit and push
git add .
git commit -m "feat: add your feature"
git push origin feature/your-feature-name- 🐛 Bug fixes
- ✨ New features
- 📝 Documentation improvements
- 🎨 UI/UX enhancements
- ⚡️ Performance optimizations
- 🔒 Security patches
- Follow PEP 8
- Use type hints
- Add docstrings
- Write tests for new features
- Multi-meeting concurrent recording
- Speaker diarization (who said what)
- Real-time transcription display
- Zoom/Teams integration
- Mobile app (iOS/Android)
- Custom vocabulary support
- Translation to multiple languages
- Meeting analytics dashboard
- Slack/Discord integration
- Browser extension
- On-premise deployment
- Multi-user support
- Role-based access control
- Advanced search and retrieval
- Meeting insights and trends
MIT License
Copyright (c) 2024 Lumina Project
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Core Technologies:
- OpenAI Whisper - Speech recognition
- Ollama - Local LLM inference
- FastAPI - Web framework
- Selenium - Browser automation
- LangChain - LLM orchestration
Inspired By:
- Meeting automation tools (Otter.ai, Fireflies.ai)
- Open-source AI projects
- Privacy-focused software movement
Project Maintainer: Hesham Haroon
Repository: https://github.com/h9-tec/lumina-ai
Issues: GitHub Issues
Built with ❤️ for meeting productivity