360° video app and AI video server for an installation art exhibition
Period —
Each artwork captured visitors' photos and footage differently. On‑site apps and generation jobs stay separate per artwork, while a shared server, operations dashboard and results website serve them all.
Unattended on‑site app that stitches camera SD card footage and delivers it by QR
- Nalda · Swift on‑site app for the balloon‑chair experience
- Namu Block · server API creating roughly 15‑second videos from images and words
- Bibi Hero · server API creating a character poster from a photo, then a roughly 10‑second video with the selected motion
- Reels13 · server job that turns one chosen take out of three 13‑second takes into AI video
- 360° balloon experience results website · mobile page for visitors to collect videos by QR
- Operations dashboard · orders, failures, retries and AI costs by location, device and service
Visitors waiting for results
- Problem
- Manually transferring and editing camera files made visitors wait for their results.
- Solution
- When the SD card goes in, the app picks only new files, removes duplicates and stitches footage in the background. Stitching and uploading at once could overload the on‑site PC, so stitching runs one job at a time. It uploads a preview first to show the QR, followed by the original.
The previous visitor's QR
- Problem
- The next visitor could scan the previous visitor's QR before it was replaced.
- Solution
- Replaced the old QR with a standby video after a set interval. Connecting the camera displays copy progress before showing a new QR.
AI providers and failed requests
- Problem
- External AI services could change or fail. Changing providers should not mean rewriting both the server code and the job queue.
- Solution
- Chose external services over our own GPUs and kept provider names out of the code so switching providers changes only the connection layer. Failed requests are retried up to 3 times after the first attempt, and authentication, configuration and billing errors are not retried. The same rule is written into the code, the docs and the dashboard. A repeated request does not create a second generation job.