πŸŽ₯

Livestreaming

WebRTC + HLS fallback, state machine, Socket.IO realtime events, consent logging en creator tools

Fastify 5 API PostgreSQL 16 + Drizzle ORM WebRTC + HLS Socket.IO Realtime React 19 + TanStack Query v5

πŸ› οΈ Tech Stack

⚑

Backend

Fastify 5 β€” stream lifecycle routes, Lucia Auth middleware

πŸ—„οΈ

Database

PostgreSQL 16 + Drizzle ORM β€” streams, consent, viewer events

πŸ“‘

Transport

WebRTC primair (<1s latency) Β· HLS fallback voor viewers (3–5s buffer)

πŸ”Œ

Realtime

Socket.IO β€” viewer count, chat, tips, gift events tijdens stream

πŸ“‘ Stream Protocol

TeezU gebruikt WebRTC als primair protocol voor minimale latency. Bij browserincompatibiliteit of viewer-only modus schakelt het systeem automatisch over op HLS.

πŸ”΅

WebRTC

Primair
  • βœ“ <1 seconde latency
  • βœ“ Peer-to-peer via STUN/TURN
  • βœ“ Adaptive bitrate (300kbps–8Mbps)
  • βœ“ Bidirectioneel (creator + co-host)
  • βœ“ MediaStream API voor camera/mic
🟠

HLS Fallback

Viewer fallback
  • βœ“ 3–5 seconden buffer
  • βœ“ Universeel browsercompatibel
  • βœ“ CDN-distributie via edge nodes
  • βœ“ Auto-quality switching
  • βœ“ RTMP β†’ HLS transcodering via FFmpeg

Video Kwaliteitsinstellingen

πŸ“Ί
720p
1.5–3 Mbps Β· HD
Standaard
πŸ–₯️
1080p
3–6 Mbps Β· Full HD
Aanbevolen
✨
4K
15–25 Mbps Β· Ultra HD
Creator+ only

πŸ”„ Stream State Machine

Elke stream doorloopt een formele state machine. Overgangen worden gevalideerd op de Fastify 5 backend β€” ongeldige overgangen retourneren HTTP 422. Alle Freeze & Panic events worden ook gelogd in de consent-tabel.

βšͺ idle
β†’
🟒 live
β†’
πŸ”΅ frozen
β†’
πŸ”΄ panic
β†’
⚫ ended
βšͺ

idle

Stream aangemaakt, nog niet live. Creator kan instellingen aanpassen.

🟒

live

Stream actief. Viewers kunnen joinen, chatten, tippen.

πŸ”΅

frozen

Video gepauzeerd (Freeze & Reveal). Gelogd in consent_log.

πŸ”΄

panic

Noodstop. Stream direct offline, moderator alert, consent gelogd.

⚫

ended

Stream beΓ«indigd. Recording verwerkt, statistieken opgeslagen.

πŸ›‘οΈ Consent Logging

Alle Freeze & Reveal acties worden onveranderlijk gelogd naar de consent_log tabel in PostgreSQL 16. Dit is een compliance-vereiste.

export const consentLog = pgTable('consent_log', {
  id: uuid().primaryKey().defaultRandom(),
  streamId: uuid().references(() => streams.id),
  creatorId: uuid().references(() => users.id),
  action: text(), // 'freeze' | 'reveal' | 'panic'
  triggeredAt: timestamp().defaultNow(),
  ipHash: text(), // geanonimiseerd IP-hash
  metadata: jsonb(),
});

✨ Features

🎬 Creator Features

▢️
Start / Stop

One-click stream starten en stoppen. Bevestigingsdialoog bij stoppen.

πŸŽ₯
Kwaliteitsinstellingen

720p / 1080p / 4K β€” instelbaar vΓ³Γ³r en tijdens stream

πŸ“…
Stream Plannen

Scheduled streams β€” volgers krijgen automatisch een notificatie

⏺️
Recording

Automatische opname β€” beschikbaar als VOD na afloop

❄️
Freeze & Reveal

Beeld bevriezen voor tip-incentive. Consent gelogd. Zone 5 Creator Tools.

🚨
Panic Knop

Noodstop met bevestigingsmodal. Stream direct offline + moderator alert.

πŸ‘οΈ Viewer Features

▢️
Kijken

WebRTC <1s join β€” geen buffering. HLS fallback beschikbaar.

πŸ’Ž
Tippen

Token tips sturen β€” verschijnt real-time als stream overlay

🎁
Gifts sturen

Animated gifts met audio β€” Rose (10t), Diamond (50t), Crown (100t), Rocket (500t)

πŸ’¬
Live Chat

Socket.IO realtime chat β€” emoji reactions, pinned berichten

🎭
Emoji Reactions

Floating emoji overlay β€” gebroadcast naar alle viewers via Socket.IO

πŸ”“
Content Unlocken

Betaal tokens om vergrendeld stream-content vrij te spelen (Freeze & Reveal)

πŸ”Œ Socket.IO Realtime Events

Socket.IO verzorgt alle realtime communicatie tijdens een stream. De Fastify 5 server host de Socket.IO instantie via @fastify/socket-io.

Server β†’ Client events

stream:viewer_count

Bijgewerkt viewer-aantal elke 5 seconden

stream:chat_message

Nieuw chatbericht van een viewer

stream:tip_received

Tip event β€” overlay animatie triggeren

stream:gift_sent

Animated gift broadcast naar alle viewers

stream:state_changed

State machine overgang (live β†’ frozen β†’ panic)

Client β†’ Server events

stream:join

Viewer joint de stream β€” WebRTC offer sturen

stream:send_chat

Chatbericht sturen (rate-limited: 3/sec)

stream:react

Emoji reaction sturen

stream:leave

Viewer verlaat de stream β€” viewer count bijwerken

πŸ”Œ Fastify 5 API Endpoints

Alle routes zijn beveiligd via Lucia Auth sessie middleware. Database operaties via Drizzle ORM op PostgreSQL 16.

POST /streams creator role

Maak een nieuwe stream aan (state: idle). Geeft stream-ID en WebRTC signaling tokens terug.

// Request body
{ "title": "Zaterdag Evening Live", "quality": "1080p", "scheduledAt": null }

// Response 201
{ "streamId": "strm_abc123", "state": "idle", "rtcToken": "eyJ...", "hlsUrl": "https://cdn.teezu.com/strm_abc123/index.m3u8" }
PATCH /streams/:id/state creator role

Verander de staat van de stream. Invalide overgangen worden geblokkeerd (HTTP 422). Freeze/Panic wordt gelogd in consent_log.

// Request body β€” start stream
{ "state": "live" }

// Request body β€” freeze (Freeze & Reveal)
{ "state": "frozen", "revealThreshold": 500 } // tokens needed

// Response 200
{ "streamId": "strm_abc123", "state": "frozen", "consentLogId": "clg_xyz" }
GET /streams/:id/viewers

Haal de actieve viewer-lijst en statistieken op voor een stream.

// Response 200
{
  "viewerCount": 243,
  "peakViewers": 312,
  "viewers": [{ "userId": "usr_1", "joinedAt": "2026-04-05T20:12:00Z", "isSubscriber": true }],
  "totalTipsEarned": 4820 // tokens
}