HLS Video Pipeline Using Spring Boot
Video upload and streaming platform with authentication, user-based ownership, async HLS processing, and performance metrics.
Features
- JWT authentication (
/auth/register,/auth/login) - User-owned videos (
user_idrelationship invideostable) - Protected upload/list/delete endpoints
- Public HLS and stream playback endpoints
- Async FFmpeg processing to HLS (360p/720p/1080p)
- Optional custom thumbnail + auto thumbnail generation
- Processing badge (
Processing...) with auto-refresh - Metrics tracking:
- upload throughput (MB/s) - processing latency (seconds) - realtime factor (RTF)
- Metrics summary API + dashboard card in UI
Architecture Diagram
Tech Stack
- Java 21
- Spring Boot 4
- Spring Security + JWT
- Spring Web MVC
- Spring Data JPA
- MySQL
- FFmpeg + ffprobe
- Vanilla HTML/CSS/JS frontend
Project Structure
src/main/java/com/stream_app
config/
SecurityConfig.java
WebConfig.java
security/
JwtAuthenticationFilter.java
JwtService.java
JwtAuthenticationEntryPoint.java
controllers/
AuthController.java
VideoController.java
MetricsController.java
services/
auth/
AuthService.java
AuthServiceImpl.java
video/
VideoService.java
VideoServiceImpl.java
processing/
VideoProcessingService.java
FfmpegService.java
repositories/
UserRepository.java
VideoRepository.java
entities/
AppUser.java
Video.java
dto/
auth/
video/
metrics/
queue/
VideoProcessingProducer.java
VideoProcessingConsumer.java
storage/
VideoStorageService.java
ThumbnailStorageService.java
utils/
HlsGenerator.java
ThumbnailGenerator.javaRuntime Storage
videos/original uploaded filesvideos_hsl/HLS playlists + segmentsthumbnails/uploaded/generated thumbnails
Authentication
Register
POST /auth/register
{
"username": "demo",
"password": "secret123"
}Login
POST /auth/login
{
"username": "demo",
"password": "secret123"
}Response includes JWT token:
{
"token": "...",
"userId": 1,
"username": "demo"
}Use for protected routes:
Authorization: Bearer <token>
Video API
Base paths supported: /api/v1/videos and /videos
Protected
POST /api/v1/videosGET /api/v1/videos/myGET /api/v1/videos/allVideosDELETE /api/v1/videos/{videoId}GET /api/v1/videos/metrics/summary
Public
GET /api/v1/videos/thumbnail/{videoId}GET /api/v1/videos/stream/{videoId}GET /api/v1/videos/stream/range/{videoId}GET /api/v1/videos/hls/{videoId}/master.m3u8GET /api/v1/videos/hls/{videoId}/{quality}/{fileName}
Ownership Model
userstable stores application users.videos.user_idlinks each video to its owner./myand delete operations enforce owner-only access.
Metrics
Each video stores:
fileSizeBytesdurationSecuploadStartedAtMs,uploadCompletedAtMs,uploadThroughputMBpsprocessingStartedAtMs,processingCompletedAtMs,processingLatencySecrealtimeFactorprocessingSucceeded
Summary endpoint:
GET /api/v1/videos/metrics/summary- Buckets:
<1 min,1-5 min,5-15 min,15+ min,Unknown
UI:
- Library section includes a Performance Metrics card with bucket-wise averages.
Frontend Flow
login.htmlhandles login/register tabs, validation, loading states, and password visibility toggle icons.- JWT is stored in
sessionStorage(tab-scoped). index.htmlrequires auth; unauthorized calls redirect to login.- Upload/delete/list/metrics use authenticated API requests.
Processing Flow
1. User uploads video (authenticated). 2. Video metadata saved with owner. 3. Async processing starts (@Async): - FFmpeg generates HLS outputs. - Thumbnail generated if missing. 4. UI shows Processing... until master.m3u8 exists. 5. Metrics are updated and exposed in summary API.