Har du någonsin önskat att du kunde förhandsgranska en cykelrutt innan du cyklar den? Vi byggde ett automatiserat system som genererar vackra överflygningsvideor för varje Party Onbici-rutt, vilket ger cyklister en filmisk förhandsvisning av vad de kan förvänta sig på sin resa.
Utmaningen
När man organiserar eller går med i ett cykelevenemang är det avgörande att förstå rutten. Statiska kartor är hjälpsamma, men de förmedlar inte upplevelsen av att faktiskt cykla rutten. Vi ville ge användarna ett sätt att virtuellt “flyga igenom” rutten innan de bestämmer sig för en åkning.
Vår lösning: Headless videorendering
Vi byggde en Node.js-tjänst som kör en headless Chrome-webbläsare med Puppeteer, renderar rutten på en interaktiv MapLibre GL-karta och fångar frames när en virtuell kamera flyger längs banan. Så här fungerar det:
1. Ruttinterpolering
En cykelrutt kan ha tusentals koordinatpunkter. För att skapa en smidig video vid 30 FPS under 15 sekunder behöver vi exakt 450 frames. Vi använder avståndsbaserad interpolering för att sampla rutten jämnt:
| |
2. Kameraanimering med jämn kurs
Att helt enkelt peka kameran i färdriktningen skapar ryckig rörelse på slingrande rutter. Vi jämnar ut kamerakursen med ett glidande medelvärde över 12 frames, med speciell hantering för 360°/0°-övergången:
| |
3. MapLibre GL-rendering
Rutten renderas på ett vackert Stadia Maps-baslagret med:
- En markerad ruttlinje med vit kontur för synlighet
- Animerad kamerapositionsindikator
- Start (grön) och mål (röd) markörer
- Valfri 3D-byggnadsextrusion för urbana områden
4. Frame-fångst och videokodning
Puppeteer fångar varje frame som en PNG-skärmdump, sedan använder vi ffmpeg för att koda dem till en WebM-video med VP9-codec:
| |
Teknisk arkitektur
| |
- Django utlöser videogenerering när ett party skapas eller uppdateras
- Celery köar uppgiften för asynkron bearbetning
- Node.js-renderer kör Puppeteer med MapLibre GL
- ffmpeg kodar de fångade frames
- Video laddas upp till S3 och party-posten uppdateras
Prestandahänsyn
| Upplösning | Längd | Rendertid | Filstorlek |
|---|---|---|---|
| 1280x720 | 15s | 60-90s | 2-4 MB |
| 1920x1080 | 15s | 90-120s | 4-8 MB |
I produktion använder vi Docker-containrar med mjukvarurendering (SwiftShader) för att undvika GPU-beroenden:
| |
Funktioner vi lade till
- Anpassningsbara videodimensioner - Kvadratiskt format för delning på sociala medier
- Logotypvattenstämpel - Märk dina videor med din organisations logotyp
- Kameralutning och zoom - Justera betraktningsvinkeln och höjden
- Ruttlinjestil - Anpassade färger och bredder
Django-integration
Från applikationskoden är det enkelt att generera en video:
| |
Video-URL:en uppdateras automatiskt när renderingen är klar:
| |
Vad kommer härnäst
Vi utforskar flera förbättringar:
- Förhandsvisning i realtid - Live-rendering när användare ritar rutter
- Flera kameravinklar - Sidovyer, överheadbilder
- Väderöverlagring - Visa prognosförhållanden längs rutten
- Höjdprofil - Visualisera klättringar och nedförsbackar i videon
Ruttöverflygningsvideor har blivit en av våra mest populära funktioner, som hjälper cyklister att fatta informerade beslut om vilka åkningar de ska gå med i. Kombinationen av moderna webbteknologier gör det som skulle ha varit en dyr produktionsuppgift till en automatiserad, on-demand-tjänst.
Vill du prova? Skapa ett party så genereras din ruttvideo automatiskt!
