Avsnitt
Teknik
Duelis verkliga teknikstack i två lager: en förklaring i vardagligt språk och en ingenjörsmässig vy.
Denna sida förklarar de teknologier Dueli faktiskt använder, i två lager: en vy i vardagligt språk för alla och en ingenjörsvy för specialister. Ingen teknologi listas om inte den nuvarande koden använder den.
I enkla ordalag
Dueli körs i webbläsaren på Cloudflares globala nätverk. Två tävlare möts i ett direktskräddat videosamtal mellan sina enheter (WebRTC peer-to-peer); när ett nätverk blockerar den direkta vägen hjälper ett TURN-relä anslutningen fram.
Under en tävling kombinerar webbläsaren de båda kamerabilderna till en enda bild och spelar in den som korta 5-sekundersblock. Blocken laddas upp allt eftersom de skapas, kan spelas upp i ordning och sammanfogas till en fullständig repris efter att matchen avslutats.
Inspelade tävlingar kan laddas ner som en MP4-fil. När en inspelning behöver konverteras sker konverteringen i besökarens webbläsare med FFmpeg.wasm, så att filen inte skickas till en extern konverteringstjänst.
Plattformens data finns i D1, sidor och API:er är byggda med Hono och TypeScript på Cloudflare, och gränssnittet använder Tailwind CSS. Liveuppdateringar kommer via SSE och polling.
För ingenjörer
Körtid: Cloudflare Pages/Workers med Hono 4 på TypeScript. D1 (SQLite) är databasen. Vite bygger Worker-paketet, Tailwind CSS 4 stylar gränssnittet och esbuild paketerar webbläsarens startpunkter.
Live media: en RTCPeerConnection i webbläsaren bär WebRTC mellan värd och motståndare. ICE-servrar utfärdas per session från GET /api/signaling/ice-servers; Cloudflare Calls TURN (TURN_TOKEN_ID och TURN_API_TOKEN) eller självhostad coturn (TURN_URL och TURN_SECRET) kan fungera som relä, med en ren STUN-reservväg när ingendera är konfigurerad.
Inspelning: en canvas-kompositör ritar båda bildströmmarna och MediaRecorder levererar ett block var femte sekund. Värden registrerar varje block vid POST /api/chunks/register (en kortlivad engångsnyckel knuten till tävlingen, ordningsföljden och byte-taket), laddar upp det, verifierar det med GET /verify och rapporterar POST /receipt. Uppspelning läser GET /api/chunks/playlist/:id, och det befintliga slutförandesteget producerar VOD:en.
Nedladdningar: @ffmpeg/core 0.12.10 körs i en självhostad webbläsarworker för MP4-konvertering, med en strukturell remux-väg för inspelningar som redan är MP4-kompatibla. Förlopp och minnesgränser hanteras i klienttjänsten.
Realtid: SSE via GET /api/sse bär liveuppdateringarna, och signalering använder HTTP-polling; produktionsvägen använder inte WebSocket.
Kvalitet: Vitest täcker enhets- och UI-kontrakt, och Playwright täcker webbläsarflödena hela vägen. Markdown-dokument renderas med marked, och PostCSS med Autoprefixer fullbordar CSS-pipelinen.
Stacken i detta repo
- Cloudflare Pages / Workers Hosting och serverkörtid
- Cloudflare D1 (SQLite) Applikationsdatabas
- Hono 4 HTTP-rutter, sidor och API
- TypeScript 5 Typad källkod för server och klient
- Tailwind CSS 4 + PostCSS + Autoprefixer Gränssnittsstyling och CSS-pipeline
- Vite 7 + esbuild Worker-paket och webbläsarens startpunkter
- WebRTC (RTCPeerConnection) + TURN/STUN Ljud och video i realtid mellan deltagarna
- Canvas compositor + MediaRecorder 5-sekundersinspelade block i webbläsaren
- FFmpeg.wasm (@ffmpeg/core 0.12.10) MP4-konvertering och nedladdning i webbläsaren
- marked 17 Markdown-rendering för hanterade dokument
- Vitest 5 Testsvit för enheter och UI
- Playwright End-to-end-webbläsartester
- Wrangler 4 Utvecklings- och driftsättningsverktyg för Cloudflare
- SSE + HTTP polling Liveuppdateringar utanför mediavägen
Listan är begränsad till vad package.json och repot faktiskt innehåller. Det är en teknisk beskrivning, inte ett påstående om partnerskap eller rekommendation.