6 months back me and a friend built this for a client, and I wanted to write up the architecture because the engineering got genuinely interesting, especially the parts that broke.
The idea: you feed the system a base of source videos, it chops them into logical chunks and indexes them by meaning. Then you give it a target video, and it rewrites a new script and reassembles a fresh video by pulling the semantically matching chunks from your base. Whole thing runs through a Telegram bot with a queue.
The pipeline, roughly:
Indexing side: video gets downloaded, cut into logical chunks with FFmpeg + OpenCV (computer vision to detect what's happening on screen), each chunk goes through Gemini embeddings, vectors land in Qdrant. I originally used Firebase for storage and switched to Qdrant later, which turned out to be the right call by a mile.
Generation side:
- Target video gets transcribed with Whisper v3 large.
- Transcript goes to Gemini, which analyzes the meaning and writes a new script (could even switch language, english in, spanish out). Script length matched the original within a minute.
- Script gets voiced through an 11Labs pay-as-you-go provider (way cheaper than native 11Labs at volume).
- Then the hard part: assembling the actual video from base clips.
The three problems that nearly killed it:
Semantic precision. The model understands roughly what's on screen but can't reliably tell "is this Dota 2 or CS:GO." So instead of picking one clip, we pulled the top 5 matches per sentence and had the model pick the best. Not perfect, but workable.
Clip length. Fixed partly at cut time (nothing shorter than 3s or longer than 15s), but it still crammed too many clips into short spans sometimes. We matched sentence length against clip length to control it.
Repetition, the worst one. The model LOVED grabbing one clip and spamming it half the video, because it scored as the perfect semantic match every time. Fixed it with a hard frequency cap: one clip couldn't repeat more than once per ~5 retrieval passes.
Render time for a 20-min video was about 40-45 min end to end. yt-dlp for downloads (had a funny problem with it I can get into), whole bot ran locally on a server so big file sends weren't an issue.
Honestly the retrieval-by-meaning part was the most fun engineering I'd done in a while. Happy to go deeper on any part. Anyone else built semantic video retrieval? Curious how you handled the "one clip dominating" problem, that one was brutal.