자전거 경로를 타기 전에 미리 볼 수 있으면 좋겠다고 생각한 적 있으신가요? Party Onbici의 모든 파티 경로에 대해 아름다운 상공 비행 영상을 생성하는 자동화 시스템을 구축하여, 라이더들에게 여정에서 기대할 수 있는 것의 시네마틱한 미리보기를 제공합니다.
도전 과제
사이클링 이벤트를 조직하거나 참여할 때 경로를 이해하는 것은 매우 중요합니다. 정적 지도는 유용하지만 실제로 경로를 달리는 경험을 전달하지는 못합니다. 라이드에 참여하기 전에 경로를 가상으로 “비행"할 수 있는 방법을 사용자들에게 제공하고 싶었습니다.
우리의 솔루션: 헤드리스 영상 렌더링
Puppeteer를 사용하여 헤드리스 Chrome 브라우저를 실행하고, 대화형 MapLibre GL 지도에서 경로를 렌더링하며, 가상 카메라가 경로를 따라 비행하는 동안 프레임을 캡처하는 Node.js 서비스를 구축했습니다. 작동 방식은 다음과 같습니다:
1. 경로 보간
자전거 경로에는 수천 개의 좌표 점이 있을 수 있습니다. 15초 동안 30FPS의 부드러운 영상을 만들려면 정확히 450프레임이 필요합니다. 거리 기반 보간을 사용하여 경로를 균등하게 샘플링합니다:
| |
2. 부드러운 방위각을 활용한 카메라 애니메이션
단순히 이동 방향으로 카메라를 향하면 굽은 경로에서 끊김 현상이 발생합니다. 360도/0도 전환에 대한 특별 처리와 함께 12프레임에 걸친 이동 평균을 사용하여 카메라 방위각을 부드럽게 합니다:
| |
3. MapLibre GL 렌더링
경로는 아름다운 Stadia Maps 기본 레이어 위에 다음과 함께 렌더링됩니다:
- 가시성을 위한 흰색 외곽선이 있는 강조된 경로 선
- 애니메이션 카메라 위치 표시기
- 출발(녹색) 및 도착(빨간색) 마커
- 도시 지역을 위한 선택적 3D 건물 돌출
4. 프레임 캡처 및 영상 인코딩
Puppeteer가 각 프레임을 PNG 스크린샷으로 캡처한 다음, ffmpeg를 사용하여 VP9 코덱으로 WebM 영상으로 인코딩합니다:
| |
기술 아키텍처
| |
- Django가 영상 생성을 트리거: 파티가 생성되거나 업데이트될 때
- Celery가 작업을 대기열에 추가: 비동기 처리를 위해
- Node.js 렌더러: MapLibre GL과 함께 Puppeteer 실행
- ffmpeg가 인코딩: 캡처된 프레임을
- 영상 업로드: S3에, 파티 레코드 업데이트
성능 고려사항
| 해상도 | 길이 | 렌더링 시간 | 파일 크기 |
|---|---|---|---|
| 1280x720 | 15초 | 60-90초 | 2-4 MB |
| 1920x1080 | 15초 | 90-120초 | 4-8 MB |
프로덕션에서는 GPU 의존성을 피하기 위해 소프트웨어 렌더링(SwiftShader)이 적용된 Docker 컨테이너를 사용합니다:
| |
추가한 기능들
- 사용자 정의 영상 크기 - 소셜 미디어 공유를 위한 정사각형 포맷
- 로고 워터마크 - 조직의 로고로 영상 브랜딩
- 카메라 기울기 및 줌 - 시야각과 고도 조정
- 경로 선 스타일링 - 사용자 정의 색상 및 너비
Django 통합
애플리케이션 코드에서 영상 생성은 다음과 같이 간단합니다:
| |
렌더링이 완료되면 영상 URL이 자동으로 업데이트됩니다:
| |
다음 단계
여러 개선 사항을 탐색하고 있습니다:
- 실시간 미리보기 - 사용자가 경로를 그릴 때 라이브 렌더링
- 다중 카메라 앵글 - 측면 뷰, 오버헤드 샷
- 날씨 오버레이 - 경로를 따라 예보 조건 표시
- 고도 프로필 - 영상에서 오르막과 내리막 시각화
경로 상공 비행 영상은 가장 인기 있는 기능 중 하나가 되었으며, 사이클리스트들이 어떤 라이드에 참여할지 정보에 기반한 결정을 내리는 데 도움을 주고 있습니다. 현대 웹 기술의 조합은 비용이 많이 드는 제작 작업이었을 것을 자동화된 온디맨드 서비스로 전환시켰습니다.
사용해 보시겠어요? 파티를 만들면 경로 영상이 자동으로 생성됩니다!