Collaborative Video Builder
Ship a two-role editor for family contribution at scale
This project introduced a collaborative workflow for memorial videos where contributors can upload and manage their own media while a manager retains final creative authority. The goal was reducing collection friction, keeping access simple, and preserving editorial quality in the final output.
Key Metrics
Memorial videos created (beta)
500+
Access model
2 roles, no account needed
Built
0 -> shipped
Engineering Highlight
Perceptual hashing for duplicate detection
Families scanning boxes of physical photos often upload near-identical images without realizing it. Each uploaded image runs through a perceptual hashing and Hamming distance pipeline to detect duplicates and visually similar matches. Instead of auto-rejecting flagged uploads, the system surfaces them with cleanup tooling so managers can consolidate safely without losing meaningful content.
System Flow
Access Model
Contributor
invite link / QR- Upload photos and video clips
- View, edit, and delete own contributions
- iOS app for mass photo scanning
- No account creation required
Manager
full creative control- All contributor permissions
- Set intro and outro videos
- Curate music playlist (library or custom upload)
- Final slide arrangement and creative decisions
Key Decisions
No account required for contributors
Asking a grieving family member to create an account before uploading a photo introduces friction that hurts participation. Contributors join via invite link or QR code with session-based auth, while media ownership and permissions remain enforced server-side.
Service Bus for async tail, SignalR for immediacy
Not every event should block the UI. SignalR handles the live events users need right now while Service Bus handles changelog writes and background processing. This split prevents slower backend work from degrading the real-time editing experience.
Webhook plus long polling for render completions
Webhooks are fast but not guaranteed. A missed delivery can leave families waiting on a render that is already complete. Long polling as a fallback closes that gap without forcing aggressive polling on the happy path.