Skip to content

Loom-inspired async video platform: Record screen/camera, get AI transcripts & summaries, share with embedded subtitles. Built with Next.js, Electron, Whisper AI, and Mistral.

License

Notifications You must be signed in to change notification settings

techquestsdev/videmo

Repository files navigation

Videmo

License: GNU GPLv3

A full-stack async video messaging platform for recording, transcribing, and sharing videos. Built to explore video processing, AI integration, and multi-platform development from the ground up.

Features

  • Cross-Platform Recording - Native desktop app for screen and camera capture (macOS, Windows, Linux)
  • Auto-Transcription - Automatic speech-to-text using Whisper AI with SRT subtitle generation
  • AI Summaries - Smart video summaries and titles powered by Mistral
  • Real-Time Updates - Live upload progress and processing status via WebSockets
  • Clean Dashboard - Modern Next.js web interface for managing recordings
  • Instant Sharing - Generate shareable links with embedded transcripts
  • Workspace Management - Organize videos into folders and workspaces
  • Payment Integration - Stripe-powered subscription system

Tech Stack

Frontend & Desktop:

Backend & Infrastructure:

AI & Processing:

  • Whisper - Speech-to-text transcription
  • Mistral AI - Text summarization and title generation
  • SRT/VTT subtitle generation

Development Tools:

Prerequisites

  • Node.js >= 16.0.0
  • pnpm >= 8.0.0
  • Docker and Docker Compose (for backend services)
  • PostgreSQL database (provided via Docker or external)
  • MinIO or S3-compatible storage (provided via Docker or external)
  • Whisper API endpoint (provided via Docker or external)
  • Mistral AI API key (required for AI summaries)

Installation

Clone the Repository

git clone https://github.com/techquestsdev/videmo.git
cd videmo

Backend Server

cd server

# Install dependencies with pnpm
pnpm install

# Set up environment variables
cp .env.example .env
# Edit .env with your configuration

# Start Docker services (MinIO, PostgreSQL)
pnpm docker:up

# Run the development server
pnpm dev

# Check health at http://localhost:5000/health
pnpm health

Web Application

cd webapp

# Install dependencies with pnpm
pnpm install

# Set up environment variables
cp .env.example .env
# Configure Clerk, database, and API URLs

# Generate Prisma client and push schema
npx prisma generate
npx prisma db push

# Run the development server
pnpm dev

# Open http://localhost:3000

Desktop App

cd desktop

# Install dependencies with pnpm
pnpm install

# Set up environment variables
cp .env.example .env
# Configure API endpoints and Clerk keys

# Run the development version
pnpm dev

# Build for production
pnpm build

# Build for specific platforms
pnpm build --mac
pnpm build --win
pnpm build --linux

Configuration

Backend Environment Variables

Create a .env file in the server/ directory:

# Server Configuration
PORT=5000
NODE_ENV=development
TEMP_DIR=/tmp

# Main API Configuration
NEXT_API_HOST=http://localhost:3000/api
ELECTRON_HOST=http://localhost:5173

# S3/MinIO Configuration
BUCKET_NAME=videmo
AWS_ENDPOINT=http://localhost:9000
AWS_REGION=local
AWS_ACCESS_KEY_ID=local
AWS_SECRET_ACCESS_KEY=locallocal

# Mistral AI Configuration (for title and summary generation)
MISTRAL_API=https://api.mistral.ai
MISTRAL_API_KEY=your-mistral-api-key-here

# Whisper Server Configuration (runs locally via docker-compose)
# The server automatically uses http://localhost:8000 for transcription

Web App Environment Variables

Create a .env file in the webapp/ directory:

# Database (Postgres)
# Format: postgres://USER:PASSWORD@HOST:PORT/DATABASE
# If you use pgbouncer or connection poolers, keep the params
DATABASE_URL="postgres://USER:PASSWORD@HOST:5432/videmo?pgbouncer=true&connection_limit=1"

# Clerk (authentication)
# - NEXT_PUBLIC... keys are safe for client-side usage
# - CLERK_SECRET_KEY must remain server-side
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_your_clerk_publishable_key_here"
CLERK_SECRET_KEY="sk_test_your_clerk_secret_key_here"
NEXT_PUBLIC_CLERK_SIGN_IN_FORCE_REDIRECT_URL="/auth/callback"
NEXT_PUBLIC_CLERK_SIGN_UP_FORCE_REDIRECT_URL="/auth/callback"

# Stripe
# - `STRIPE_CLIENT_SECRET` is your Stripe secret (server only)
# - `STRIPE_SUBSCRIPTION_PRICE_ID` is the price/product id used for subscriptions
STRIPE_CLIENT_SECRET="your_stripe_client_secret_here"
STRIPE_SUBSCRIPTION_PRICE_ID="your_stripe_price_id_here"

# Host / CDN URLs
# - `NEXT_PUBLIC_HOST_URL` should match your frontend origin
# - `NEXT_PUBLIC_CLOUD_FRONT_STREAM_URL` used for signed/served streams
NEXT_PUBLIC_HOST_URL="http://localhost:3000"
NEXT_PUBLIC_CLOUD_FRONT_STREAM_URL="http://localhost:9000/videmo"

# Mailer credentials (used by server for sending email)
MAILER_EMAIL="your_mailer_email_here"
MAILER_PASSWORD="your_mailer_password_here"

Desktop App Environment Variables

Create a .env file in the desktop/ directory:

# Clerk Authentication
VITE_CLERK_PUBLISHABLE_KEY=pk_test_...

# API Endpoints
VITE_HOST_URL=http://localhost:3000/api
VITE_SOCKET_URL=http://localhost:5000/
VITE_APP_URL=http://localhost:5173

Usage

Recording a Video

Desktop App:

  1. Launch the Videmo desktop application
  2. Sign in with your Clerk account
  3. Configure camera and microphone settings
  4. Click "Start Recording" and select:
    • Screen only
    • Camera only
    • Screen + Camera (picture-in-picture)
  5. Stop recording when finished
  6. Video automatically uploads to the backend with real-time progress

Managing Videos

Web Dashboard:

  1. Navigate to http://localhost:3000
  2. Sign in with your Clerk account
  3. View all recordings organized by workspace and folder
  4. Click any video to:
    • Watch with embedded player
    • Read auto-generated transcript
    • View AI-powered summary
    • Edit title and description
    • Move to different folders
    • Generate share link
    • Download video or transcript

Sharing Videos

# Each video gets a shareable preview URL
https://your-domain.com/preview/{videoId}

# Share links include:
- Video player with subtitles
- Full transcript
- AI summary
- No authentication required for recipients

Organizing Content

Workspaces:

  • Create multiple workspaces for different projects or teams
  • Invite collaborators to workspaces
  • Manage workspace settings and permissions

Folders:

  • Organize videos within workspaces using folders
  • Create nested folder structures
  • Move videos between folders with drag-and-drop

Architecture

videmo/
├── server/                 # Express.js backend API
│   ├── src/
│   │   ├── config/        # Configuration management
│   │   ├── middleware/    # Express middleware
│   │   ├── routes/        # API route handlers
│   │   ├── services/      # Business logic layer
│   │   │   ├── ai.service.js           # Mistral integration
│   │   │   ├── storage.service.js      # S3/MinIO operations
│   │   │   ├── transcription.service.js # Whisper integration
│   │   │   └── video-processing.service.js
│   │   ├── sockets/       # Socket.io event handlers
│   │   └── utils/         # Helper functions
│   ├── docker-compose.yaml
│   └── server.js
│
├── webapp/                # Next.js web application
│   ├── src/
│   │   ├── app/          # Next.js App Router
│   │   │   ├── (website)          # Public marketing pages
│   │   │   ├── auth/               # Authentication pages
│   │   │   ├── dashboard/          # Protected dashboard
│   │   │   ├── preview/            # Public video sharing
│   │   │   └── api/                # API routes
│   │   ├── components/
│   │   │   ├── forms/              # Form components
│   │   │   ├── global/             # Shared components
│   │   │   ├── icons/              # Custom icon components
│   │   │   └── ui/                 # Radix UI components
│   │   ├── actions/       # Server actions
│   │   ├── hooks/         # Custom React hooks
│   │   ├── lib/          # Utilities and helpers
│   │   ├── redux/        # Redux Toolkit store
│   │   └── types/        # TypeScript types
│   ├── prisma/
│   │   ├── schema.prisma # Database schema
│   │   └── migrations/   # Database migrations
│   └── public/
│
└── desktop/              # Electron desktop recorder
    ├── electron/         # Electron main process
    │   ├── main.ts      # Main process entry
    │   └── preload.ts   # Preload script
    ├── src/
    │   ├── components/
    │   │   ├── global/           # App components
    │   │   │   ├── MediaConfiguration/
    │   │   │   ├── StudioTray/
    │   │   │   └── Webcam/
    │   │   └── ui/               # Radix UI components
    │   ├── hooks/        # Custom hooks
    │   ├── layouts/      # Layout components
    │   ├── lib/         # Utilities (recorder logic)
    │   └── schemas/     # Zod validation schemas
    ├── index.html       # Main window
    ├── studio.html      # Recording studio window
    ├── webcam.html      # Webcam overlay window
    └── vite.config.ts

Data Flow

  1. Recording Phase

    • Desktop app captures video stream (MediaRecorder API)
    • Video chunks buffered in memory
    • User stops recording
  2. Upload Phase

    • Electron app uploads video via HTTP POST to /api/upload
    • Backend receives stream and saves to MinIO/S3
    • Real-time progress updates via Socket.io
    • Database record created with metadata
  3. Processing Phase

    • Backend extracts audio from video
    • Whisper API transcribes audio to text
    • SRT subtitle file generated
    • Mistral AI generates title and summary
    • Status updates broadcast via WebSocket
  4. Viewing Phase

    • Web app fetches video metadata from database
    • Video streams from MinIO/S3
    • Transcript and subtitles displayed inline
    • AI summary shown in sidebar
  5. Sharing Phase

    • User generates share link
    • Public preview page renders without auth
    • Video player with embedded subtitles
    • Transcript and summary visible to recipient

Development

Set up your local development environment by following the installation steps above. Use the commands below to run and test individual components.

Running Individual Components

# Backend server (Express + Socket.io)
cd server
pnpm dev              # Development mode with nodemon
pnpm start            # Production mode
pnpm docker:up        # Start MinIO and PostgreSQL
pnpm health           # Check server health

# Web application (Next.js)
cd webapp
pnpm dev              # Development mode (http://localhost:3000)
pnpm build            # Build for production
pnpm start            # Start production server
pnpm lint             # Run ESLint

# Desktop app (Electron)
cd desktop
pnpm dev              # Development mode with hot reload
pnpm build            # Build installers for current platform
pnpm build --mac      # Build for macOS
pnpm build --win      # Build for Windows
pnpm build --linux    # Build for Linux

Database Management

# Generate Prisma client after schema changes
npx prisma generate

# Push schema changes to database (development)
npx prisma db push

# Create a new migration (production)
npx prisma migrate dev --name add_new_field

# Apply migrations
npx prisma migrate deploy

# Open Prisma Studio (database GUI)
npx prisma studio

# Reset database (warning: deletes all data)
npx prisma migrate reset

Docker Deployment

Local Docker Compose

# Start services for each component (needs to be in component directory)
docker-compose up -d

# View logs
docker-compose logs -f

# View specific service logs
docker-compose logs -f service_name

# Stop all services
docker-compose down

# Remove volumes (warning: deletes data)
docker-compose down -v

Production Deployment

# Build production images
docker build -t videmo-server:latest ./server
docker build -t videmo-webapp:latest ./webapp

# Run with Docker
docker run -d \
  --name videmo-server \
  -p 5000:5000 \
  --env-file ./server/.env \
  videmo-server:latest

docker run -d \
  --name videmo-webapp \
  -p 3000:3000 \
  --env-file ./webapp/.env \
  videmo-webapp:latest

Troubleshooting

Video Upload Fails

Problem: Upload hangs or times out

Solution: Check backend connectivity and storage configuration

# Verify server is running
curl http://localhost:5000/health

# Check MinIO is accessible
docker ps | grep minio

# Test MinIO connection
curl http://localhost:9000/minio/health/live

# Check backend logs for errors
cd server
pnpm docker:logs

# Verify S3 environment variables in server/.env
echo $S3_ENDPOINT
echo $S3_ACCESS_KEY

Transcription Not Working

Problem: Videos process but no transcription appears

Solution: Verify Whisper API configuration and connectivity

# Check Whisper service is running
curl http://localhost:8000/health

# Test Whisper API with sample audio
curl -X POST http://localhost:8000/transcribe \
  -F "audio=@sample.wav"

# Check WHISPER_API_URL in server/.env
cat server/.env | grep WHISPER

# View backend logs for API errors
cd server
pnpm docker:logs | grep whisper

Desktop App Won't Connect

Problem: Desktop app cannot reach backend API

Solution: Verify API URL and network configuration

# Verify VITE_API_URL in desktop/.env
cat desktop/.env | grep VITE_API_URL

# Check CORS settings in server
# Ensure desktop origin is allowed in server/.env:
ALLOWED_ORIGINS=http://localhost:5173

# Test WebSocket connection
wscat -c ws://localhost:5000

Database Connection Issues

Problem: Web app or backend cannot connect to PostgreSQL

Solution: Verify PostgreSQL is running and DATABASE_URL is correct

# Check PostgreSQL container status
docker ps | grep postgres

# Test database connection
psql "postgresql://postgres:password@localhost:5432/videmo"

# Verify DATABASE_URL format
# Should be: postgresql://USER:PASSWORD@HOST:PORT/DATABASE
echo $DATABASE_URL

# Regenerate Prisma client after schema changes
cd webapp
npx prisma generate

# Push schema to database
npx prisma db push

Clerk Authentication Errors

Problem: Authentication not working or showing errors

Solution: Verify Clerk configuration and keys

# Check Clerk publishable key is set
echo $NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
echo $VITE_CLERK_PUBLISHABLE_KEY

# Ensure keys match between webapp and desktop
# Keys should start with: pk_test_ or pk_live_

# Verify Clerk webhook endpoints in Clerk Dashboard
# Add: https://your-domain.com/api/webhooks/clerk

# Check Clerk environment (test vs production)
# Ensure all keys are from the same environment

MinIO Storage Issues

Problem: Cannot access uploaded videos

Solution: Verify MinIO bucket configuration

# Access MinIO console
open http://localhost:9001

# Login with credentials from docker-compose.yaml
# User: minioadmin
# Password: minioadmin

# Check if bucket exists and is accessible
# Bucket should be: videmo-uploads

# Verify bucket policy allows public read (for sharing)
# Can configure via MinIO console or mc client

# Test file upload manually
curl -X POST http://localhost:5000/api/upload?userId=test&filename=test.mp4 \
  -H "Content-Type: video/mp4" \
  --data-binary @test-video.mp4

Build Errors

Problem: Build fails with dependency or TypeScript errors

Solution: Clean install and rebuild

# Remove all node_modules and lock files
make clean

# Reinstall dependencies
make install

# Clear pnpm cache if needed
pnpm store prune

# Rebuild Prisma client
cd webapp
npx prisma generate

# Check for outdated dependencies
pnpm outdated

Project Structure Details

Backend Services

Storage Service (src/services/storage.service.js)

  • Handles S3/MinIO file operations
  • Uploads, downloads, and deletes videos
  • Generates pre-signed URLs for secure access

Transcription Service (src/services/transcription.service.js)

  • Integrates with Whisper API
  • Converts video to audio format
  • Generates SRT subtitle files
  • Handles error retry logic

AI Service (src/services/ai.service.js)

  • Integrates with Mistral API
  • Generates video titles and summaries
  • Processes transcripts for key insights

Video Processing Service (src/services/video-processing.service.js)

  • Orchestrates the complete processing pipeline
  • Coordinates transcription and AI services
  • Manages processing state and WebSocket events

Performance Considerations

  • Video Upload: Chunked uploads for large files with progress tracking
  • Streaming: Videos served directly from MinIO/S3 with range requests
  • Caching: TanStack Query caches API responses on the client
  • Lazy Loading: Video thumbnails and metadata loaded on demand
  • WebSocket: Real-time updates without polling overhead
  • Optimistic Updates: UI updates immediately before server confirmation
  • Image Optimization: Next.js Image component with WebP/AVIF

Security Considerations

  • Authentication: Clerk handles secure user authentication and session management
  • Authorization: Row-level security ensures users only access their own content
  • CORS: Configured to allow only trusted origins
  • API Keys: Stored in environment variables, never committed to version control
  • S3 Pre-signed URLs: Time-limited secure access to private videos
  • Input Validation: Zod schemas validate all user input
  • SQL Injection: Prisma protects against SQL injection attacks
  • XSS Protection: React escapes user-generated content by default

Project Status

Videmo is a functional side project built for learning and skill development. It successfully demonstrates:

  • End-to-end video processing pipeline: From capture to transcription to AI enhancement
  • Multi-platform development: Coordinated web and desktop experiences
  • Real-time communication: WebSocket integration for live updates
  • AI integration: Practical application of speech-to-text and language models
  • Modern full-stack architecture: Type-safe APIs, state management, and authentication

Current State: Feature-complete for core video recording, processing, and sharing workflows. Intentionally maintained as a portfolio/learning project rather than a production-ready commercial product.

Future Enhancements

Potential areas for expansion:

  • Video editing capabilities (trim, crop, annotations)
  • Team collaboration features (comments, mentions)
  • Advanced analytics (view counts, engagement metrics)
  • Mobile app (React Native)
  • Video compression and format conversion
  • Live streaming support
  • Integrations (Slack, Discord, Notion)
  • Advanced search (full-text search in transcripts)

Contributing

This is a personal learning project, but feedback and suggestions are welcome!

Ways to Contribute:

  • Report bugs or issues
  • Suggest new features
  • Improve documentation
  • Share use cases or ideas

Please open an issue for discussion before significant work.

License

This project is licensed under the GNU GPLv3 License - see the LICENSE file for details.

Acknowledgments

  • Loom - Inspiration for the project concept
  • Whisper - Speech-to-text technology
  • Mistral AI - Text generation and summarization
  • Clerk - Authentication infrastructure
  • Vercel - Next.js development and hosting
  • Electron - Cross-platform desktop framework
  • WebProdigies - Video reference architecture

Learn More

Documentation

Related Projects

  • Cap - Async video messaging tool
  • Loom - Professional async video platform
  • Screen Studio - Screen recording tool

Made with ❤️

About

Loom-inspired async video platform: Record screen/camera, get AI transcripts & summaries, share with embedded subtitles. Built with Next.js, Electron, Whisper AI, and Mistral.

Topics

Resources

License

Stars

Watchers

Forks