Adaptive video streaming platform using FFmpeg, HLS/DASH, and CDN delivery with optional DRM support
Upload videos, auto-transcode to multiple bitrates, and stream seamlessly across devices
Features β’ Demo β’ Installation β’ Usage β’ Architecture β’ API
|
|
- β Multi-Bitrate Encoding - Optimized for different network speeds
- β WebSocket Integration - Real-time job progress updates
- β Job Management - Track, monitor, and manage multiple transcoding jobs
- β RESTful API - Complete backend API for integration
- β Responsive UI - Modern React interface with beautiful styling
- π DASH Support - Coming soon
- π DRM Integration - Optional DRM support (roadmap)
- π CDN Delivery - CloudFront/Cloudflare integration (roadmap)
Watch the complete application walkthrough showing:
- β Video upload with drag & drop interface
- β Real-time transcoding progress tracking
- β Multi-resolution video playback (360p - 1080p)
- β Adaptive streaming with quality selection
- β Live playback statistics dashboard
πΊ Watch Full Demo Video (86 MB)
The demo video shows the entire workflow from uploading a video to watching it with adaptive streaming.
π· Click to view screenshots
Drag and drop interface with real-time upload progress
Real-time transcoding progress and job monitoring
Adaptive streaming player with quality selection and statistics
- HLS (HTTP Live Streaming) - Primary adaptive streaming protocol
- M3U8 Playlists - Master and variant playlists
- MPEG-TS Segments - 4-second video chunks
- H.264 Codec - Video encoding
- AAC Codec - Audio encoding
Before running this application, ensure you have the following installed:
| Requirement | Version | Installation |
|---|---|---|
| Node.js | v14+ | Download |
| npm | v6+ | Comes with Node.js |
| FFmpeg | Latest | See instructions below β¬οΈ |
Windows
Option 1: Download from gyan.dev (Recommended)
- Visit https://www.gyan.dev/ffmpeg/builds/
- Download
ffmpeg-release-essentials.zip - Extract to
C:\ffmpeg - Add
C:\ffmpeg\binto your PATH environment variable - Verify: Open new terminal and run
ffmpeg -version
Option 2: Using Chocolatey
choco install ffmpeg
macOS
brew install ffmpeg
Linux
Debian/Ubuntu:
sudo apt-get update
sudo apt-get install ffmpeg
CentOS/RHEL:
sudo yum install ffmpeg
Verify Installation:
ffmpeg -version
git clone https://github.com/danu38/video-streaming-platform.git
cd video-streaming-platform
cd backend
npm install
cd ../frontend
npm install
If FFmpeg is not in your system PATH, you need to configure it:
-
Copy the environment file:
cd ../backend cp .env.example .env -
Edit
.envfile and set your FFmpeg paths:Windows Example:
FFMPEG_PATH=C:\ffmpeg\bin\ffmpeg.exe FFPROBE_PATH=C:\ffmpeg\bin\ffprobe.exeLinux/Mac Example:
FFMPEG_PATH=/usr/local/bin/ffmpeg FFPROBE_PATH=/usr/local/bin/ffprobe -
Find your FFmpeg location:
- Windows: Check where you extracted FFmpeg (look for
ffmpeg.exeandffprobe.exe) - Linux/Mac: Run
which ffmpegandwhich ffprobe
- Windows: Check where you extracted FFmpeg (look for
π‘ Tip: If FFmpeg is in your system PATH, you can skip this step or leave the
.envfile empty!
Terminal 1 - Backend Server:
cd backend
npm start
β Backend running on http://localhost:5000
Terminal 2 - Frontend Server:
cd frontend
npm start
β Frontend running on http://localhost:3000
Alternative: Development Mode with Auto-Reload
cd backend
npm run dev
- Navigate to the "Upload Video" tab
- Drag and drop a video file or click "Browse Files"
- Supported formats:
MP4,AVI,MKV,MOV,WMV,FLV,WEBM - Maximum file size: 500MB
- Click "Upload & Transcode"
- Switch to the "Jobs" tab to see all transcoding jobs
- Real-time progress updates via WebSocket
- View current variant being processed (360p, 480p, 720p, 1080p)
- Track FPS and encoding speed
- Once transcoding is complete, click "Play Video"
- The adaptive player will open with your video
- Toggle between quality levels
- View real-time playback statistics
| Feature | Description |
|---|---|
| Auto Quality | Automatically selects optimal quality based on bandwidth |
| Manual Selection | Choose specific resolution (360p-1080p) |
| Statistics | Real-time buffer, bitrate, resolution, dropped frames |
| Seek Support | Jump to any part of the video instantly |
| Responsive | Works on desktop, tablet, and mobile devices |
video-streaming-platform/
β
βββ π backend/
β βββ π server.js # Express server & Socket.IO
β βββ π services/
β β βββ βοΈ transcoding.js # FFmpeg transcoding engine
β βββ π uploads/ # Original uploaded videos
β βββ π output/ # Transcoded outputs
β βββ π hls/ # HLS segments & playlists
β β βββ job-xxx/
β β βββ master.m3u8 # Master playlist
β β βββ 360p/, 480p/, 720p/, 1080p/
β β β βββ playlist.m3u8 # Variant playlist
β β β βββ segment*.ts # Video segments
β βββ π¦ package.json
β
βββ π frontend/
β βββ π public/
β β βββ index.html
β βββ π src/
β β βββ π¨ App.js # Main application
β β βββ π¨ App.css # Global styles
β β βββ π components/
β β β βββ π€ VideoUpload.js # Upload UI
β β β βββ π€ VideoUpload.css
β β β βββ π¬ VideoPlayer.js # HLS player
β β β βββ π¬ VideoPlayer.css
β β β βββ π JobsList.js # Job management
β β β βββ π JobsList.css
β β βββ index.js
β βββ π¦ package.json
β
βββ π README.md
βββ π« .gitignore
βββ π¦ start-backend.bat / start-frontend.bat
POST /upload
Content-Type: multipart/form-data
Request Body: video (file)
Response:
{
"jobId": "job-1234567890",
"filename": "video.mp4",
"message": "Video uploaded successfully"
}
GET /jobs
Response: Array of job objects
GET /job/:jobId
Response:
{
"id": "job-1234567890",
"originalName": "video.mp4",
"status": "processing",
"progress": 45,
"currentVariant": "720p",
"hlsUrl": "/hls/job-1234567890/master.m3u8"
}
DELETE /job/:jobId
Response: { message: "Job deleted successfully" }
GET /hls/:jobId/master.m3u8
Response: HLS master playlist (M3U8)
| Event | Description | Payload |
|---|---|---|
job-progress |
Real-time transcoding progress | { jobId, progress, currentVariant, fps, speed } |
job-complete |
Job finished successfully | { jobId, hlsUrl } |
job-failed |
Job failed with error | { jobId, error } |
Example:
socket.on('job-progress', (data) => {
console.log(`Job ${data.jobId}: ${data.progress}% - Processing ${data.currentVariant}`);
});
graph LR
A[User Uploads Video] --> B[Server Receives File]
B --> C[FFmpeg Transcoding]
C --> D[360p Variant]
C --> E[480p Variant]
C --> F[720p Variant]
C --> G[1080p Variant]
D --> H[HLS Packaging]
E --> H
F --> H
G --> H
H --> I[Master Playlist]
I --> J[Adaptive Streaming]
J --> K[Client Player]
- User uploads video via drag-and-drop interface
- Multer middleware handles multipart file upload
- File saved to
uploads/directory - Job ID generated and returned to client
FFmpeg transcodes video into multiple bitrate variants:
| Resolution | Video Bitrate | Audio Bitrate | Use Case |
|---|---|---|---|
| 360p | 800 kbps | 96 kbps | Mobile (3G) |
| 480p | 1400 kbps | 128 kbps | Mobile (4G) |
| 720p | 2800 kbps | 128 kbps | HD Streaming |
| 1080p | 5000 kbps | 192 kbps | Full HD |
- H.264 video codec (
libx264) - AAC audio codec
- 4-second HLS segments
- GOP size: 48 frames
- Real-time progress via WebSocket
- Each resolution β Variant playlist (
playlist.m3u8) - Master playlist references all variants
- TS segments created for each chunk
- Bandwidth info included for adaptive switching
hls.jslibrary loads master playlist- Detects available bandwidth
- Automatically switches between qualities
- Manual quality selection supported
- Buffer management for smooth playback
β FFmpeg Not Found Error
Solution:
- Verify FFmpeg is installed:
ffmpeg -version - Ensure FFmpeg is in your system PATH
- Restart terminal after installation
- On Windows, check PATH in System Environment Variables
π Port Already in Use
Backend (Port 5000):
Edit backend/server.js:
const PORT = 5001; // Change to available port
Frontend (Port 3000):
PORT=3001 npm start
π CORS Errors
Check backend/server.js CORS configuration:
app.use(cors({
origin: 'http://localhost:3000' // Update if frontend port changed
}));
π WebSocket Connection Failed
- Ensure backend is running on port 5000
- Check
frontend/src/App.js:
const socket = io('http://localhost:5000'); // Update if port changed
π€ Large File Upload Fails
Increase file size limit in backend/server.js:
const upload = multer({
limits: { fileSize: 1000 * 1024 * 1024 } // 1GB
});
| Aspect | Recommendation | Impact |
|---|---|---|
| Input Format | Use H.264 MP4 files | β‘ Faster transcoding |
| Resolution | Lower input resolution = faster | β‘β‘ Much faster |
| Concurrent Jobs | Process one at a time | β‘β‘β‘ Best performance |
| Disk Space | 3-5x original size needed | πΎ Plan accordingly |
| CPU Usage | FFmpeg is CPU-intensive | π₯οΈ Expect high usage |
- DASH Support - MPEG-DASH protocol implementation
- DRM Integration - Widevine, PlayReady, FairPlay
- Subtitle Support - VTT/SRT subtitle tracks
- Thumbnail Generation - Video preview thumbnails
- CDN Integration - CloudFront/Cloudflare support
- Cloud Storage - AWS S3, Google Cloud Storage
- Queue System - Redis-based job queue
- Load Balancing - Multiple transcoding workers
- User Authentication - JWT-based auth
- Video Library - Personal video collections
- Analytics Dashboard - View counts, watch time
- Video Editing - Basic trim, crop, filters
- Progress Persistence - Resume after restart
- GPU Acceleration - NVIDIA NVENC encoding
- Smart Encoding - Content-aware bitrate selection
- Caching Layer - Redis caching for metadata
- Database Integration - PostgreSQL/MongoDB
This project is licensed under the MIT License - feel free to use it for learning, development, and production.
MIT License - Copyright (c) 2024
Built with amazing open-source technologies:
| Technology | Purpose |
|---|---|
| FFmpeg | Video transcoding engine |
| React | Frontend framework |
| Node.js | Backend runtime |
| hls.js | HLS playback library |
| Socket.IO | Real-time communication |
| Express | Web framework |
Open an issue on GitHub with:
- Description of the problem
- Steps to reproduce
- Expected vs actual behavior
- System info (OS, Node version, FFmpeg version)
Open a feature request issue describing:
- The feature you'd like
- Why it would be useful
- Possible implementation approach
Contributions are welcome! Please feel free to submit a Pull Request.
Made with β€οΈ for the video streaming community
Report Bug β’ Request Feature β’ Documentation
Happy Streaming! π₯β¨