Abschnitt
Technologie
Die echte Dueli-Technologie in zwei Schichten: eine einfache Erklärung und die Ingenieurperspektive.
Diese Seite erklärt die Technologien, die Dueli tatsächlich verwendet, in zwei Schichten: eine einfach verständliche Ansicht für alle und eine technische Ansicht für Spezialisten. Keine Technologie wird aufgeführt, es sei denn, der aktuelle Code verwendet sie.
Einfach ausgedrückt
Dueli läuft im Browser auf dem globalen Netzwerk von Cloudflare. Zwei Kontrahanten führen ein Live-Video-Gespräch zwischen ihren Geräten (WebRTC peer-to-peer); wenn ein Netzwerk den direkten Pfad blockiert, hilft ein TURN-Relay beim Verbindungsaufbau.
Während eines Wettbewerbs kombiniert der Browser beide Videofeeds in ein Bild und zeichnet sie als kurze 5-Sekunden-Chunks auf. Die Chunks werden bei ihrer Erstellung hochgeladen, können in der richtigen Reihenfolge abgespielt werden und werden nach dem Ende des Duells zu einer vollständigen Zusammenstellung zusammengesetzt.
Aufgenommene Wettbewerbe können als MP4-Datei heruntergeladen werden. Wenn eine Konvertierung erforderlich ist, läuft diese im Browser des Besuchers mit FFmpeg.wasm, sodass die Datei nicht an einen externen Konvertierungsdienst gesendet wird.
Plattformdaten befinden sich in D1, Seiten und APIs sind mit Hono und TypeScript auf Cloudflare aufgebaut, und die Benutzeroberfläche verwendet Tailwind CSS. Live-Updates kommen über SSE und Polling.
Für Ingenieure
Laufzeitumgebung: Cloudflare Pages/Workers mit Hono 4 auf TypeScript. D1 (SQLite) ist die Datenbank. Vite erstellt das Worker-Bundle, Tailwind CSS 4 gestaltet die Benutzeroberfläche, und esbuild bündelt die Browser-Einstiegspunkte.
Live-Medien: eine Browser-RTCPeerConnection transportiert WebRTC zwischen Gast und Gegner. ICE-Server werden pro Sitzung von GET /api/signaling/ice-servers ausgestellt; Cloudflare Calls TURN (TURN_TOKEN_ID und TURN_API_TOKEN) oder selbst gehosteter coturn (TURN_URL und TURN_SECRET) können weiterleiten, mit einem STUN-only-Fallback, wenn keines konfiguriert ist.
Aufnahme: ein Canvas-Compositor zeichnet beide Feeds, und MediaRecorder gibt alle 5 Sekunden einen Chunk aus. Der Gast meldet jeden Chunk bei POST /api/chunks/register (ein kurzlebiges einmaliger Schlüssel, an den Wettbewerb, Sequenz und Byte-Grenze gebunden), lädt ihn hoch, überprüft ihn mit GET /verify und meldet POST /receipt. Wiedergabe liest GET /api/chunks/playlist/:id, und der bestehende Finalisierungsprozess erzeugt die VOD.
Downloads: @ffmpeg/core 0.12.10 läuft in einem selbst gehosteten Browser-Worker für die MP4-Konvertierung, mit einem strukturellen Remux-Pfad für Aufnahmen, die bereits MP4-kompatibel sind. Fortschritt und Speichergrenzen werden im Client-Service gehandhabt.
Echtzeit: SSE über GET /api/sse trägt Live-Updates, und das Signalisierungsprotokoll verwendet HTTP-Polling; der Produktionsweg verwendet kein WebSocket.
Qualität: Vitest deckt Einheiten-UI-Verträge ab, und Playwright deckt End-to-End-Browser-Workflows ab. Markdown-Dokumente werden mit gerendert, und PostCSS mit Autoprefixer vervollständigt die CSS-Pipeline.
Der Stack in diesem Repository
- Cloudflare Pages / Workers Hosting und Server-Laufzeitumgebung
- Cloudflare D1 (SQLite) Anwendungsdatenbank
- Hono 4 HTTP-Routen, Seiten und API
- TypeScript 5 Typisierter Quellcode für Server und Client
- Tailwind CSS 4 + PostCSS + Autoprefixer Oberflächenstil und CSS-Pipeline
- Vite 7 + esbuild Worker-Bundle und Browser-Einstiegspunkte
- WebRTC (RTCPeerConnection) + TURN/STUN Live-Audio und -Video zwischen Teilnehmern
- Canvas-Compositor + MediaRecorder 5-Sekunden-Chunks im Browser aufnehmen
- FFmpeg.wasm (@ffmpeg/core 0.12.10) MP4-Konvertierung und Download im Browser
- marked 17 Markdown-Rendering für verwaltete Dokumente
- Vitest 5 Unit- und UI-Test-Suite
- Playwright End-to-End-Browser-Tests
- Wrangler 4 Cloudflare-Entwicklung und -Bereitstellungstools
- SSE + HTTP-Polling Live-Updates außerhalb des Medienpfads
Die Liste ist auf das beschränkt, was package.json und das Repository tatsächlich enthalten. Es handelt sich um eine technische Beschreibung, nicht um eine Partnerschaft oder eine Empfehlung.