Convert audio and video recordings into accurate, editable transcriptions powered by WhisperX AI.
Perfect for meetings, interviews, podcasts, and lectures. Built with FastAPI (backend) and Vue 3 (frontend).
KlipNote provides end-to-end transcription workflow:
Key Features:
Audio Formats:
Video Formats:
File Limits:
SRT (SubRip Subtitle):
TXT (Plain Text):
Desktop Browsers:
Mobile Browsers:
Notes:
Verify your GPU is accessible to Docker:
# Test NVIDIA Docker GPU access
docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
# Expected output: Should display your GPU information
If the command fails, ensure nvidia-docker2 is properly installed and configured.
git clone <repository-url> klipnote
cd klipnote
git submodule update --init --recursive
cd backend
cp .env.example .env
# Edit .env if needed (defaults should work for local development)
# Build and start all services (web, worker, redis, flower)
docker-compose up --build
# Or run in background
docker-compose up -d --build
# Access worker container
docker-compose exec worker bash
# Inside container, verify GPU access
nvidia-smi
# Exit container
exit
# Ping Celery workers
docker-compose exec worker celery -A app.celery_utils inspect ping
Key environment variables (see .env.example for complete list):
CELERY_BROKER_URL: Redis connection for Celery task queueCELERY_RESULT_BACKEND: Redis connection for task resultsWHISPER_MODEL: WhisperX model (tiny, base, small, medium, large-v2, large-v3)WHISPER_DEVICE: Device for inference (cuda for GPU, cpu for CPU)WHISPER_COMPUTE_TYPE: Compute precision (float16 for GPU, float32 for CPU)UPLOAD_DIR: Directory for uploaded audio filesMAX_FILE_SIZE: Maximum upload file size in bytesCORS_ORIGINS: Allowed frontend origins for CORScd frontend
# Install dependencies (already done during project initialization)
npm install
# Start development server
npm run dev
# Frontend will be available at http://localhost:5173
# Run development server with hot reload
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Run unit tests
npm run test:unit
# Run unit tests with coverage
npm run test:unit -- --coverage
# Lint and fix code
npm run lint
# Terminal 1: Backend services
cd backend
docker-compose up
# Terminal 2: Frontend dev server
cd frontend
npm run dev
Access:
Upload media files for transcription using the /upload endpoint.
Endpoint: POST /upload
Supported Formats:
File Requirements:
Example using cURL:
# Upload an audio file
curl -X POST "http://localhost:8000/upload" \
-F "file=@/path/to/your/audio.mp3"
# Expected response:
# {
# "job_id": "550e8400-e29b-41d4-a716-446655440000"
# }
Example using Python:
import requests
# Upload file
with open("/path/to/your/audio.mp3", "rb") as f:
response = requests.post(
"http://localhost:8000/upload",
files={"file": ("audio.mp3", f, "audio/mpeg")}
)
data = response.json()
job_id = data["job_id"]
print(f"Upload successful! Job ID: {job_id}")
Example using JavaScript/Fetch:
// Upload file from file input
const fileInput = document.querySelector('input[type="file"]');
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('http://localhost:8000/upload', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
console.log('Upload successful! Job ID:', data.job_id);
})
.catch(error => console.error('Upload failed:', error));
Response Codes:
job_idCommon Error Messages:
// Invalid format
{
"detail": "Unsupported file format. Allowed: MP3, MP4, WAV, M4A. Received: text/plain"
}
// Duration too long
{
"detail": "File duration exceeds 2-hour limit. File duration: 3.50 hours"
}
// File too large
{
"detail": "File size exceeds maximum limit of 2.0GB"
}
Interactive API Documentation:
Visit http://localhost:8000/docs for interactive API documentation with:
After uploading a file via /upload, transcription is processed asynchronously by a Celery worker with GPU acceleration. The job progresses through 5 stages:
Progress Stages:
Processing Time:
Monitoring:
docker-compose logs -f workerGET /status/{job_id})Result Storage:
job:{job_id}:status and job:{job_id}:result keys/uploads/{job_id}/transcription.jsonExample transcription.json format:
{
"segments": [
{
"start": 0.5,
"end": 3.2,
"text": "Hello, welcome to the meeting."
},
{
"start": 3.5,
"end": 7.8,
"text": "Let's begin with today's agenda."
}
]
}
klipnote/
├── backend/ # FastAPI backend with Celery workers
│ ├── app/
│ │ ├── ai_services/ # AI service abstraction layer
│ │ │ ├── whisperx/ # WhisperX git submodule
│ │ │ ├── base.py # Abstract TranscriptionService interface
│ │ │ └── whisperx_service.py # WhisperX implementation
│ │ ├── services/ # Business logic services
│ │ ├── tasks/ # Celery async tasks
│ │ ├── main.py # FastAPI app initialization
│ │ ├── config.py # Configuration management
│ │ ├── celery_utils.py # Celery worker configuration
│ │ └── models.py # Pydantic data models
│ ├── tests/ # Backend tests (pytest)
│ ├── Dockerfile # Backend container configuration
│ ├── docker-compose.yaml # Multi-service orchestration
│ ├── requirements.txt # Python dependencies
│ └── .env.example # Environment variable template
│
├── frontend/ # Vue 3 + TypeScript frontend
│ ├── src/
│ │ ├── components/ # Reusable Vue components
│ │ ├── views/ # Page-level components
│ │ ├── stores/ # Pinia state management
│ │ ├── router/ # Vue Router configuration
│ │ ├── services/ # API client services
│ │ └── types/ # TypeScript type definitions
│ ├── package.json # Node dependencies
│ └── vite.config.ts # Vite build configuration
│
└── docs/ # Project documentation
cd backend
# Run all tests
../.venv/Scripts/python.exe -m pytest tests/ -v
# Run with coverage report
../.venv/Scripts/python.exe -m pytest tests/ -v --cov=app --cov-report=html
# Run specific test file
../.venv/Scripts/python.exe -m pytest tests/test_api_upload.py -v
# View coverage report
start htmlcov/index.html # Windows
open htmlcov/index.html # Mac/Linux
cd frontend
# Run unit tests
npm run test:unit
# Run with coverage
npm run test:unit -- --coverage
# Run in watch mode (auto-rerun on file changes)
npm run test:unit -- --watch
Story 2.7: Comprehensive E2E validation suite
cd frontend
# Prerequisites: Ensure backend is running
cd ../backend && docker-compose up -d
# Install Playwright browsers (first time only)
npx playwright install --with-deps
# Prepare test fixtures (see e2e/fixtures/README.md)
# Create test media files: test-short.mp3, test-medium.mp3, test-video.mp4, test-audio.wav
# Run all E2E tests
npm run test:e2e
# Run specific test suite
npx playwright test workflow-validation
npx playwright test cross-browser
npx playwright test error-scenarios
npx playwright test performance
# Run tests in UI mode (interactive debugging)
npm run test:e2e:ui
# View test report
npm run test:e2e:report
E2E Test Coverage:
Test Fixtures:
Create test media files in frontend/e2e/fixtures/:
# Using FFmpeg (if available)
cd frontend/e2e/fixtures
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t 10 -q:a 9 -acodec libmp3lame test-short.mp3
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t 300 -q:a 9 -acodec libmp3lame test-medium.mp3
# Or use your own audio/video files (rename to match test expectations)
See frontend/e2e/fixtures/README.md for detailed test file creation instructions.
Upload fails with "File format not supported":
Upload fails with "File size exceeds 2GB limit":
Transcription stuck at "Processing...":
docker ps (see all 4 containers: web, worker, redis, flower)docker logs klipnote-worker-1 -fnvidia-smiExport downloads empty file:
Media player won't play / No audio:
Click-to-timestamp doesn't work:
Edits not saving / Lost edits after refresh:
Mobile: On-screen keyboard covers editing area:
Upload fails with "Unsupported file format":
Upload fails with "File duration exceeds 2-hour limit":
MAX_DURATION_HOURS in .env (requires restart)Upload fails with "File size exceeds maximum limit":
MAX_FILE_SIZE in .env (requires restart)Upload succeeds but ffprobe validation fails:
RUN apt-get update && apt-get install -y ffmpegdocker-compose up --buildDocker Compose fails to start:
nvidia-smiWorker can't access GPU:
docker-compose.yamldocker run --rm --gpus all nvidia/cuda:11.8.0-base nvidia-smiRedis connection errors:
docker-compose logs redis)docker-compose psDependencies not installing:
node --versionnpm cache clean --forcenode_modules and package-lock.json, then npm installPort 5173 already in use:
vite.config.tslsof -ti:5173 | xargs kill (Unix/Mac)FFmpeg Binary Installation: Installed via apt-get in Dockerfile (not just python-ffmpeg wrapper). Required by WhisperX for media processing.
PyTorch CUDA Binding: Installed with CUDA 11.8-specific index URL (--index-url https://download.pytorch.org/whl/cu118) to ensure GPU acceleration.
Docker Compose Health Checks: Redis service has health check; web/worker services wait for Redis to be healthy before starting. Prevents race condition crashes.
AI Service Abstraction: WhisperX integrated via abstract TranscriptionService interface, enabling future alternatives (Deepgram, Faster-Whisper).
Backend:
Frontend:
Infrastructure:
[Add license information]
[Add contribution guidelines]
42 commits
Python
73.0%
TypeScript
21.0%
Vue
4.2%
Convert audio and video recordings into accurate, editable transcriptions powered by WhisperX AI.
Perfect for meetings, interviews, podcasts, and lectures. Built with FastAPI (backend) and Vue 3 (frontend).
KlipNote provides end-to-end transcription workflow:
Key Features:
Audio Formats:
Video Formats:
File Limits:
SRT (SubRip Subtitle):
TXT (Plain Text):
Desktop Browsers:
Mobile Browsers:
Notes:
Verify your GPU is accessible to Docker:
# Test NVIDIA Docker GPU access
docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
# Expected output: Should display your GPU information
If the command fails, ensure nvidia-docker2 is properly installed and configured.
git clone <repository-url> klipnote
cd klipnote
git submodule update --init --recursive
cd backend
cp .env.example .env
# Edit .env if needed (defaults should work for local development)
# Build and start all services (web, worker, redis, flower)
docker-compose up --build
# Or run in background
docker-compose up -d --build
# Access worker container
docker-compose exec worker bash
# Inside container, verify GPU access
nvidia-smi
# Exit container
exit
# Ping Celery workers
docker-compose exec worker celery -A app.celery_utils inspect ping
Key environment variables (see .env.example for complete list):
CELERY_BROKER_URL: Redis connection for Celery task queueCELERY_RESULT_BACKEND: Redis connection for task resultsWHISPER_MODEL: WhisperX model (tiny, base, small, medium, large-v2, large-v3)WHISPER_DEVICE: Device for inference (cuda for GPU, cpu for CPU)WHISPER_COMPUTE_TYPE: Compute precision (float16 for GPU, float32 for CPU)UPLOAD_DIR: Directory for uploaded audio filesMAX_FILE_SIZE: Maximum upload file size in bytesCORS_ORIGINS: Allowed frontend origins for CORScd frontend
# Install dependencies (already done during project initialization)
npm install
# Start development server
npm run dev
# Frontend will be available at http://localhost:5173
# Run development server with hot reload
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Run unit tests
npm run test:unit
# Run unit tests with coverage
npm run test:unit -- --coverage
# Lint and fix code
npm run lint
# Terminal 1: Backend services
cd backend
docker-compose up
# Terminal 2: Frontend dev server
cd frontend
npm run dev
Access:
Upload media files for transcription using the /upload endpoint.
Endpoint: POST /upload
Supported Formats:
File Requirements:
Example using cURL:
# Upload an audio file
curl -X POST "http://localhost:8000/upload" \
-F "file=@/path/to/your/audio.mp3"
# Expected response:
# {
# "job_id": "550e8400-e29b-41d4-a716-446655440000"
# }
Example using Python:
import requests
# Upload file
with open("/path/to/your/audio.mp3", "rb") as f:
response = requests.post(
"http://localhost:8000/upload",
files={"file": ("audio.mp3", f, "audio/mpeg")}
)
data = response.json()
job_id = data["job_id"]
print(f"Upload successful! Job ID: {job_id}")
Example using JavaScript/Fetch:
// Upload file from file input
const fileInput = document.querySelector('input[type="file"]');
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('http://localhost:8000/upload', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
console.log('Upload successful! Job ID:', data.job_id);
})
.catch(error => console.error('Upload failed:', error));
Response Codes:
job_idCommon Error Messages:
// Invalid format
{
"detail": "Unsupported file format. Allowed: MP3, MP4, WAV, M4A. Received: text/plain"
}
// Duration too long
{
"detail": "File duration exceeds 2-hour limit. File duration: 3.50 hours"
}
// File too large
{
"detail": "File size exceeds maximum limit of 2.0GB"
}
Interactive API Documentation:
Visit http://localhost:8000/docs for interactive API documentation with:
After uploading a file via /upload, transcription is processed asynchronously by a Celery worker with GPU acceleration. The job progresses through 5 stages:
Progress Stages:
Processing Time:
Monitoring:
docker-compose logs -f workerGET /status/{job_id})Result Storage:
job:{job_id}:status and job:{job_id}:result keys/uploads/{job_id}/transcription.jsonExample transcription.json format:
{
"segments": [
{
"start": 0.5,
"end": 3.2,
"text": "Hello, welcome to the meeting."
},
{
"start": 3.5,
"end": 7.8,
"text": "Let's begin with today's agenda."
}
]
}
klipnote/
├── backend/ # FastAPI backend with Celery workers
│ ├── app/
│ │ ├── ai_services/ # AI service abstraction layer
│ │ │ ├── whisperx/ # WhisperX git submodule
│ │ │ ├── base.py # Abstract TranscriptionService interface
│ │ │ └── whisperx_service.py # WhisperX implementation
│ │ ├── services/ # Business logic services
│ │ ├── tasks/ # Celery async tasks
│ │ ├── main.py # FastAPI app initialization
│ │ ├── config.py # Configuration management
│ │ ├── celery_utils.py # Celery worker configuration
│ │ └── models.py # Pydantic data models
│ ├── tests/ # Backend tests (pytest)
│ ├── Dockerfile # Backend container configuration
│ ├── docker-compose.yaml # Multi-service orchestration
│ ├── requirements.txt # Python dependencies
│ └── .env.example # Environment variable template
│
├── frontend/ # Vue 3 + TypeScript frontend
│ ├── src/
│ │ ├── components/ # Reusable Vue components
│ │ ├── views/ # Page-level components
│ │ ├── stores/ # Pinia state management
│ │ ├── router/ # Vue Router configuration
│ │ ├── services/ # API client services
│ │ └── types/ # TypeScript type definitions
│ ├── package.json # Node dependencies
│ └── vite.config.ts # Vite build configuration
│
└── docs/ # Project documentation
cd backend
# Run all tests
../.venv/Scripts/python.exe -m pytest tests/ -v
# Run with coverage report
../.venv/Scripts/python.exe -m pytest tests/ -v --cov=app --cov-report=html
# Run specific test file
../.venv/Scripts/python.exe -m pytest tests/test_api_upload.py -v
# View coverage report
start htmlcov/index.html # Windows
open htmlcov/index.html # Mac/Linux
cd frontend
# Run unit tests
npm run test:unit
# Run with coverage
npm run test:unit -- --coverage
# Run in watch mode (auto-rerun on file changes)
npm run test:unit -- --watch
Story 2.7: Comprehensive E2E validation suite
cd frontend
# Prerequisites: Ensure backend is running
cd ../backend && docker-compose up -d
# Install Playwright browsers (first time only)
npx playwright install --with-deps
# Prepare test fixtures (see e2e/fixtures/README.md)
# Create test media files: test-short.mp3, test-medium.mp3, test-video.mp4, test-audio.wav
# Run all E2E tests
npm run test:e2e
# Run specific test suite
npx playwright test workflow-validation
npx playwright test cross-browser
npx playwright test error-scenarios
npx playwright test performance
# Run tests in UI mode (interactive debugging)
npm run test:e2e:ui
# View test report
npm run test:e2e:report
E2E Test Coverage:
Test Fixtures:
Create test media files in frontend/e2e/fixtures/:
# Using FFmpeg (if available)
cd frontend/e2e/fixtures
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t 10 -q:a 9 -acodec libmp3lame test-short.mp3
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t 300 -q:a 9 -acodec libmp3lame test-medium.mp3
# Or use your own audio/video files (rename to match test expectations)
See frontend/e2e/fixtures/README.md for detailed test file creation instructions.
Upload fails with "File format not supported":
Upload fails with "File size exceeds 2GB limit":
Transcription stuck at "Processing...":
docker ps (see all 4 containers: web, worker, redis, flower)docker logs klipnote-worker-1 -fnvidia-smiExport downloads empty file:
Media player won't play / No audio:
Click-to-timestamp doesn't work:
Edits not saving / Lost edits after refresh:
Mobile: On-screen keyboard covers editing area:
Upload fails with "Unsupported file format":
Upload fails with "File duration exceeds 2-hour limit":
MAX_DURATION_HOURS in .env (requires restart)Upload fails with "File size exceeds maximum limit":
MAX_FILE_SIZE in .env (requires restart)Upload succeeds but ffprobe validation fails:
RUN apt-get update && apt-get install -y ffmpegdocker-compose up --buildDocker Compose fails to start:
nvidia-smiWorker can't access GPU:
docker-compose.yamldocker run --rm --gpus all nvidia/cuda:11.8.0-base nvidia-smiRedis connection errors:
docker-compose logs redis)docker-compose psDependencies not installing:
node --versionnpm cache clean --forcenode_modules and package-lock.json, then npm installPort 5173 already in use:
vite.config.tslsof -ti:5173 | xargs kill (Unix/Mac)FFmpeg Binary Installation: Installed via apt-get in Dockerfile (not just python-ffmpeg wrapper). Required by WhisperX for media processing.
PyTorch CUDA Binding: Installed with CUDA 11.8-specific index URL (--index-url https://download.pytorch.org/whl/cu118) to ensure GPU acceleration.
Docker Compose Health Checks: Redis service has health check; web/worker services wait for Redis to be healthy before starting. Prevents race condition crashes.
AI Service Abstraction: WhisperX integrated via abstract TranscriptionService interface, enabling future alternatives (Deepgram, Faster-Whisper).
Backend:
Frontend:
Infrastructure:
[Add license information]
[Add contribution guidelines]
42 commits
Python
73.0%
TypeScript
21.0%
Vue
4.2%