Detailed Component Design
We will now deep dive into the following topics:
Adaptive Bitrate Streaming
ABR is needed in system like this, because we dont want to return the entire video content when user requests to watch the video, that is not efficent and takes a very long time when videos are very large. Instead we implement ABR using HLS/DASH:
How it works
- User request to watch the video
- GET /videos/videoId triggers
- The API returns back a manifest url
- Client fetches the manifest file from the url. The file contains:
- Video segments URL (CDN)
- Segment sequences
- Available resolution
- Other ABR options like, segment lengths, 10sec, 20sec etc
- Client uses the video segment url and fetches the content of the segment from CDN that user is currently watching as well the current quality user has selected, for eg: if user is at 0 sec, it fetches the first segment and starts playing
- As user continues to watch, the client continuosly polls CDN to retrieve the next segment, so if user is at 1:10 min, it will poll and fetch the video segments containing 1:20 to 1:30 content.
- Even if user peeks ahead of video, the cleint will poll CDN to fetch the video segement of taht partitucal minute and play the video.
CDN
-> CDN acts as the primary delivery layer for video segments and manifests.
Flow:
Client → CDN Edge → (cache hit) → serve immediately
→ (cache miss) → fetch from object storage
-> Hot Segment Serving (Edge Optimization)
- Hot segements are frequently reqeusted segments eg. viral videos
- trending content etc
- CDN significantly improves performance by serving hot segments directly from edge cache:
First user request:
- CDN cache miss
- Segment fetched from object storage (origin)
- Stored in edge cache
Subsequent requests:
- Same segment requested by other users
- Served directly from nearby CDN edge
- No origin fetch required
Upload pipeline
-> Upload initiation
- client calls POST /video/upload
- backend authenticates and creates an upload session
- Returns a pre signed URL for object storage
- Client uses the uRl and uploads the vidoe to object storage
-> Upload completion
- client calls POST /video/complete
- Backend validates that the video exists in object storage
- Marks the video state as UPLOADED
- Then it triggers the workflow
-> Worflow steps:
- Transcoding -> Transcode each video in 5 different resolutions
- Segmenting -> For each resolution Segment video into 10 sec chunks and save it to object storage
- Saving -> Save each seg to object storage
- Manifest -> Manifest file and URL is generated and saved
- Updated Index -> Extract title, description etc and update the inverted indexes.
-> Why workflow engine?
- Durability -> Saga state is persisted
- Retries -> Failed steps are retried automatically
- Checkpointing -> Last successful step is saved and failure are resumed from there
- Observability -> full trace per video
Failure handling
- If a step fails
- Only that step is retried
- Prev successful steps are not executed again
- If workes crashes
- workflow resumes from last checkpoint.
Additionally, further failure handling logic could be added as custom logic, where if sacing segments failed midway, we check last saved segment from object stoarge and resuime from next one.
Counters and Analytics
We handle likes, dislikes, and views using an event-driven system instead of direct DB updates.
-> Flow
- User action → event generated (like/view/dislike)
- Events processed asynchronously
->Counter handling
- Real-time layer (Redis)
- Keeps fast counters per video
- Used for UI display
- Updated via streaming/batched events
- Persistent layer (Cassandra/NoSQL)
- Stores aggregated counters
- Updated in batches from stream processors
->Views handling
- Views are high volume
- We aggregate them in batches (not per request write)
We avoid direct DB writes per event and use streaming + batching to scale write-heavy counters.