Live Streaming Platform
Video live-streaming reference architecture: broadcaster ingest via IVS, transcoding, CloudFront delivery to viewers, WebSocket chat backed by DynamoDB, and VOD
Architecture
- Broadcaster (OBS) — Streams RTMPS to the ingest endpoint using a per-channel stream key
- Amazon IVS Ingest — Managed RTMPS ingest. Authenticates the stream key and originates stream-state events.
- IVS Transcoder (ABR) — Transcodes the source feed into an adaptive bitrate ladder (1080p/720p/480p/audio-only).
- CloudFront CDN — Delivers HLS playlists and segments globally; ~3-5s glass-to-glass latency.
- VOD Recordings Bucket — IVS auto-record-to-S3 target. Lifecycle rule transitions old recordings to Glacier.
- VOD Publisher — S3-event triggered: writes VOD metadata (duration, key, thumbnail) once a recording completes.
- EventBridge — Receives IVS Stream State Change events (START/END).
- Stream Events Handler — Flips stream status live/ended, stamps playback URL, kicks off VOD registration on END.
- Viewer — Watches the HLS stream and chats in real time
- Web App (player + chat) — React SPA with an HLS.js player and a WebSocket chat pane.
- WebSocket API (Chat) — API Gateway WebSocket: $connect / $disconnect / sendMessage routes.
- Chat Handler — Persists messages, tracks connections, fans out via postToConnection.
- Chat Tables — DynamoDB: chat_messages (by stream, time-ordered) and chat_connections (TTL'd).
- REST API — Streams, VODs, users. Cognito JWT authorizer; stream discovery is public.
- Streams Service — Channel CRUD, stream-key rotation, live directory, VOD listing.
- Streams & Users Tables — DynamoDB: users, streams (GSI on status for the live directory), vods, follows.
- Cognito User Pool — Auth for broadcasters and chatting viewers; anonymous playback allowed.
About this design
- ## What this is A reference architecture for a Twitch-style live streaming platform on AWS. Broadcasters push RTMPS into Amazon IVS (modeled as custom nodes — ingest and ABR transcoder), viewers pull HLS through CloudFront, chat rides an API Gateway WebSocket backed by Lambda and DynamoDB, and every finished stream is auto-recorded to S3 and published as a VOD. A small REST API (streams, VODs, users) and Cognito round out the control plane. The sequence diagram walks the two paths that matter most: a broadcaster going live and a viewer joining to watch and chat. ## How it works **Go live.** A broadcaster calls `POST /streams`, which provisions an IVS channel and returns the RTMPS ingest endpoint plus a stream key (the key itself lives in Secrets Manager — only its ARN is stored). When OBS starts pushing, IVS emits a *Stream State Change: START* event onto EventBridge; the stream-events handler flips the stream to `live` and stamps the CloudFront playback URL. Viewers discover it via `GET /streams?status=live`, which reads a GSI on stream status. **Watch.** Playback is plain HLS: the player fetches the master playlist from CloudFront and adapts across the transcoder's bitrate ladder. Video never touches our Lambdas — the data plane is entirely IVS + CloudFront, so viewer count doesn't affect API load. **Chat.** The web app opens a WebSocket (`$connect` stores the connection id keyed by stream). `sendMessage` persists to `chat_messages` and fans out with `postToConnection` to every connection watching that stream. Connections carry a TTL so zombies get reaped. **VOD.** On *Stream State Change: END*, IVS finalizes the auto-record to S3; the S3 event triggers the VOD publisher, which writes duration, playlist key, and thumbnail into the `vods` table. ## How to extend - **Go-live notifications** — the `follows` table already has the GSI you need; add an EventBridge target on START that pushes via SNS/Pinpoint. - **Chat moderation** — insert a moderation Lambda (banned-word list, or Comprehend toxicity scoring) between the sendMessage route and persistence. - **Viewer counts** — aggregate `chat_connections` per stream on a 10s schedule and expose it on the stream record. - **Clips** — a MediaConvert job that cuts a time range from the S3 recording; add a `clips` table. - **Low-latency mode** — swap the HLS path notes for IVS low-latency playback (~2s) and note the CDN implications. Chat fan-out is the first thing to shard when a single stream gets big — batch `postToConnection` calls and consider moving hot streams to a dedicated fan-out worker fed by a Kinesis stream.