A complete Video-on-Demand (VOD) streaming platform with content management panel, video processing pipeline, and HLS player. Features resumable uploads, queue-based processing, and MySQL database.
- Content Management: Full-featured admin panel for video management
- Resumable Uploads: TUS protocol support for reliable large file uploads
- Video Processing: Queue-based video transcoding with Bull
- S3 Storage: S3-compatible object storage integration
- HLS Streaming: Adaptive bitrate streaming with HLS.js
- Database: MySQL/SQLite support with TypeORM
- Modern Stack: NestJS backend, Next.js frontend, Express player
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Upload │────▶│ Processing │────▶│ S3 Storage │
│ (TUS) │ │ Queue (Bull)│ │ (HLS Files) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Database │◀───▶│ Admin Panel │────▶│ Player │
│ (MySQL) │ │ (Next.js) │ │ (Express) │
└──────────────┘ └──────────────┘ └──────────────┘
- Framework: NestJS 11
- Database: TypeORM with MySQL/SQLite
- Queue: Bull with Redis
- Storage: AWS SDK S3
- Upload: TUS Server (resumable uploads)
- Validation: class-validator, class-transformer
- Framework: Next.js 15 (with Turbopack)
- UI: React 19, TypeScript
- Styling: Tailwind CSS
- Components: Radix UI
- Upload: tus-js-client
- HTTP: Axios
- Toast: Sonner
- Framework: Express.js
- Template: EJS
- Video: HLS Video Element
- Style: player.style
- Build: esbuild
- Node.js 18+
- MySQL 5.7+ or SQLite
- Redis (for queue management)
- S3-compatible storage (AWS S3, MinIO, etc.)
- FFmpeg (for video processing)
git clone https://github.com/stukenov/vod-streaming-server.git
cd vod-streaming-serverCopy example environment files:
cp .env.example panel/back/.env
cp .env.example player/.envConfigure panel/back/.env:
PORT=3001
REDIS_HOST=localhost
REDIS_PORT=6379
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=your_password
DB_DATABASE=vod_database
S3_REGION=your-region
S3_ENDPOINT=https://your-s3-endpoint.com
S3_BUCKET=your-bucket
S3_ACCESS_KEY=your_key
S3_SECRET_KEY=your_secret
ADAPTO_API_URL=https://your-processing-api.com
ADAPTO_API_KEY=your_api_keyConfigure player/.env:
PORT=4000
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=your_password
DB_DATABASE=vod_databaseCreate database:
mysql -u root -p
CREATE DATABASE vod_database;
exit;The application will auto-create tables via TypeORM migrations.
# Admin Panel Backend
cd panel/back && npm install && cd ../..
# Admin Panel Frontend
cd panel/front && npm install && cd ../..
# Player
cd player && npm install && cd ..redis-servercd panel/back
npm run devBackend runs on http://localhost:3001
cd panel/front
npm run devFrontend runs on http://localhost:3000
cd player
npm run devPlayer runs on http://localhost:4000
.
├── panel/ # Admin Panel
│ ├── back/ # NestJS Backend
│ │ ├── src/
│ │ │ ├── video/ # Video management
│ │ │ ├── upload/ # TUS upload handler
│ │ │ ├── queue/ # Bull job queue
│ │ │ └── storage/ # S3 integration
│ │ ├── uploads/ # Temp upload storage
│ │ └── package.json
│ │
│ └── front/ # Next.js Frontend
│ ├── src/
│ │ ├── app/ # App router pages
│ │ ├── components/ # React components
│ │ └── lib/ # Utilities
│ └── package.json
│
├── player/ # Video Player
│ ├── src/
│ │ ├── server.js # Express server
│ │ ├── client/ # Client-side JS
│ │ └── views/ # EJS templates
│ └── package.json
│
├── .github/ # CI/CD workflows
├── .env.example # Environment template
└── README.md # This file
- Resumable Uploads: TUS protocol allows resuming interrupted uploads
- Chunked Transfer: Large files uploaded in manageable chunks
- Progress Tracking: Real-time upload progress monitoring
- Validation: File type, size, and format validation
- Queue System: Bull-based job queue for async processing
- HLS Transcoding: Convert videos to HLS format with multiple bitrates
- Thumbnail Generation: Auto-generate video thumbnails
- Status Tracking: Monitor processing progress and status
- Error Handling: Automatic retry on failures
- HLS Streaming: Adaptive bitrate streaming
- Resume Playback: Remember viewer position
- Multiple Qualities: Auto-switch based on bandwidth
- Responsive Player: Works on all devices
- Custom Controls: Seek, volume, fullscreen controls
GET /videos- List all videosGET /videos/:id- Get video detailsPOST /videos- Create video entryPATCH /videos/:id- Update videoDELETE /videos/:id- Delete video
POST /upload- Create uploadPATCH /upload/:id- Upload chunk (TUS)HEAD /upload/:id- Get upload status
POST /videos/:id/process- Start processingGET /videos/:id/status- Get processing status
GET /- Home page with video listGET /watch/:id- Video player pageGET /api/videos- Get videos JSON
| Variable | Description | Required | Default |
|---|---|---|---|
PORT |
Backend server port | No | 3001 |
REDIS_HOST |
Redis hostname | Yes | localhost |
REDIS_PORT |
Redis port | Yes | 6379 |
DB_HOST |
Database hostname | Yes | localhost |
DB_PORT |
Database port | Yes | 3306 |
DB_USERNAME |
Database username | Yes | root |
DB_PASSWORD |
Database password | Yes | - |
DB_DATABASE |
Database name | Yes | - |
S3_REGION |
S3 region | Yes | - |
S3_ENDPOINT |
S3 endpoint URL | Yes | - |
S3_BUCKET |
S3 bucket name | Yes | - |
S3_ACCESS_KEY |
S3 access key | Yes | - |
S3_SECRET_KEY |
S3 secret key | Yes | - |
ADAPTO_API_URL |
Processing API URL | No | - |
ADAPTO_API_KEY |
Processing API key | No | - |
| Variable | Description | Required | Default |
|---|---|---|---|
PORT |
Player server port | No | 4000 |
DB_HOST |
Database hostname | Yes | localhost |
DB_PORT |
Database port | Yes | 3306 |
DB_USERNAME |
Database username | Yes | root |
DB_PASSWORD |
Database password | Yes | - |
DB_DATABASE |
Database name | Yes | - |
Admin Panel Backend:
cd panel/back
npm run devAdmin Panel Frontend:
cd panel/front
npm run devPlayer:
cd player
npm run devAdmin Panel Backend:
cd panel/back
npm run build
npm run prod # Uses PM2Admin Panel Frontend:
cd panel/front
npm run build
npm run prod # Uses PM2Player:
cd player
npm run build
npm start# Backend unit tests
cd panel/back && npm test
# Backend e2e tests
cd panel/back && npm run test:e2e
# Test coverage
cd panel/back && npm run test:cov- Upload: User uploads video via TUS protocol
- Storage: Temporary file stored locally
- Queue: Processing job added to Bull queue
- Transcode: FFmpeg converts to HLS format with multiple bitrates
- Upload: HLS segments uploaded to S3
- Database: Video metadata and status updated
- Cleanup: Temporary files removed
- Ready: Video available for streaming
Create docker-compose.yml:
version: '3.8'
services:
backend:
build: ./panel/back
ports:
- "3001:3001"
environment:
- NODE_ENV=production
depends_on:
- mysql
- redis
frontend:
build: ./panel/front
ports:
- "3000:3000"
player:
build: ./player
ports:
- "4000:4000"
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: vod_database
redis:
image: redis:7-alpineRun:
docker-compose up -d- Install dependencies
- Configure environment variables
- Build applications
- Start with PM2:
pm2 start panel/back/dist/main.js --name vod-backend
pm2 start panel/front/node_modules/next/dist/bin/next --name vod-frontend -- start
pm2 start player/src/server.js --name vod-player- Check TUS server configuration
- Verify disk space in uploads directory
- Check file permissions
- Increase server timeout for large files
- Verify FFmpeg is installed
- Check Redis connection
- Monitor Bull queue health
- Check S3 credentials and permissions
- Verify HLS files exist in S3
- Check CORS configuration on S3
- Test HLS URL directly in VLC
- Check player console for errors
- Implement authentication for admin panel
- Use HTTPS in production
- Secure S3 bucket with proper IAM policies
- Rate limit upload endpoints
- Validate all user inputs
- Sanitize file names
- Implement user quotas
- Use CDN for HLS delivery
- Implement caching layer
- Optimize database queries
- Use Redis for session storage
- Scale workers for processing queue
- Enable S3 transfer acceleration
MIT License - see LICENSE file for details.
Saken Tukenov
Contributions are welcome! Please feel free to submit a Pull Request.