Engineering Case Study / Multimodal Search

AIC Multimodal Search: finding moments, not files.

A media search system is only useful when it returns the exact timestamp where something happens. Text search alone misses visual concepts. Vector search alone misses exact speech and object constraints. AIC combines visual embeddings, object detections, transcripts, audio fingerprints, temporal logic, and shot metadata into a single retrieval workflow.

01 / Problem

The user is not searching for a video. They are searching for a moment inside a video.

Media archives are hard because intent can be visual, spoken, object-based, temporal, or auditory. “A man opens a red door after a dog runs past” is not just a text query. It is a sequence of visual events. “Someone says climate policy” is transcript search. “Find the same audio clip” is fingerprint search. A useful system must handle all of them.

Visual Semantics

Users describe scenes in natural language. The system needs embeddings that can map text queries to keyframes.

Concrete Constraints

Some queries require exact object filters: class labels, confidence thresholds, and instance counts.

Timeline Precision

The result must map back to FPS, shot boundaries, HLS playback, and evaluation timestamps.

02 / Decision Log

The system uses different indexes because each modality fails differently.

DecisionWhyRejected AlternativeTrade-off
Milvus for visual vectorsCLIP/BEIT3 keyframe vectors need fast approximate nearest-neighbor search.Store vectors in MongoDB.Requires vector index lifecycle and model/version discipline.
CLIP + BEIT3 fusionDifferent vision-language models catch different semantics; fusion reduces single-model brittleness.Use one embedding model only.More memory and ingestion complexity.
MongoDB for objectsObject detections are structured arrays with labels, confidence, and bounding boxes.Flatten object labels into text.Requires aggregation logic for count/confidence constraints.
Elasticsearch for transcriptsSpeech queries benefit from fuzzy and phrase matching, not vector semantics alone.Only semantic video search.Requires timestamp-to-keyframe alignment.
Temporal searchSome answers are event sequences, not isolated frames.Return independent top-k hits.Requires anchor query and max-frame-gap logic.
03 / System Context

AIC is a retrieval core sitting between media archives and timestamped answers.

AIC index topology radar
Topology view: every modality is useful only because it resolves back to the same timeline anchor.
04 / Ingestion

One video becomes several synchronized search surfaces.

The ingestion process loads keyframe embeddings into Milvus, object detections into MongoDB, transcripts into Elasticsearch, and audio fingerprints from HLS segments via FFmpeg. The key engineering concern is alignment: every signal must map back to the same video/keyframe timeline.

AIC ingestion pipeline
Ingestion pipeline: visual vectors, object detections, transcripts, and audio fingerprints are separate indexes over one timeline.
05 / Hybrid Retrieval

The query fans out, then collapses back to timestamped keyframes.

The Flask search API accepts text queries, object filters, and audio/transcript constraints. Each path returns candidate keyframes. The system intersects result sets by `(video_id, keyframe_index)` and ranks by fused scores when visual retrieval participates.

AIC hybrid retrieval
Hybrid retrieval: Milvus handles visual semantics, MongoDB handles object constraints, Elasticsearch handles transcript evidence, and intersection returns shared keyframe hits.
AIC modality decision matrix
Decision matrix: each modality is selected because it answers a different class of user intent.
06 / Visual Fusion

Visual retrieval uses two model perspectives instead of trusting one embedding space.

CLIP and BEIT3 queries are encoded separately, searched against separate Milvus collections, normalized, merged by keyframe, and fused with equal weights. The result is a ranked list of candidate keyframes with `fused_score`.

AIC score fusion dashboard
Score explanation view: a better product would show why a result ranked, not just return a thumbnail.
fused_score = 0.5 * normalized_clip_score + 0.5 * normalized_beit3_score
key = (video_id, keyframe_index)
07 / Temporal Search

Some queries describe a sequence of events, not a scene.

The `temporal_search` method runs each query independently, groups candidates by video, chooses an anchor query, then walks backward and forward to find neighboring keyframes inside `MAX_FRAME_GAP`. This turns separate top-k lists into a temporal chain.

AIC temporal filmstrip
Filmstrip view: temporal search assembles a mini-story from ordered keyframes, not a single best image.
08 / Object Constraints

Object filters make retrieval concrete when language is too fuzzy.

MongoDB stores object detections per keyframe. The object search path uses aggregation with `$filter`, `$size`, `$gte`, and `$lte` to enforce label, confidence, minimum instance, and maximum instance constraints.

AIC object search
Object search: structured detections become exact constraints that can be intersected with visual/text candidates.
09 / Transcript Retrieval

Speech needs lexical search because exact words matter.

Transcript CSV rows are cleaned, aligned to closest keyframes by FPS, and indexed in Elasticsearch with a custom analyzer. Querying combines fuzzy match and phrase match so spoken terms can retrieve timestamped frames.

AIC transcript indexing
Transcript retrieval: speech text becomes a searchable index tied back to keyframes.
10 / Audio Fingerprints

Audio identity is different from speech meaning.

The fingerprint path concatenates HLS `.ts` segments with FFmpeg, converts them to mono WAV, extracts audio hashes, and stores them in a fingerprint database. This supports matching sound patterns even when transcript text is unavailable or irrelevant.

AIC audio fingerprint pipeline
Audio fingerprinting: HLS segments become WAV, then hashes keyed by video ID.
11 / Result Resolution

Retrieval is only complete when the result becomes playable and submittable.

The app maps each keyframe hit to FPS, shot boundaries, HLS playback data, and evaluation submission payload. This is where raw search hits become product results.

AIC result resolution
Result resolution: keyframe hits are converted into shot ranges, playback segments, and evaluation timestamps.
12 / Failure Modes

Multimodal search fails when indexes drift or one modality dominates.

Useful observability should track not just server health, but modality contribution, recall@K, stage latency, empty intersections, timestamp errors, and index freshness.

AIC failure and observability
Failure and observability: watch index drift, model bias, timestamp errors, empty intersections, recall, latency, and modality hits.
13 / Demo Gallery

The demo should prove that different query types hit the same timeline.

Replace placeholders with app captures: semantic query, object-filter query, transcript query, temporal sequence query, HLS playback, and evaluation submit flow.

14 / Video

The strongest video starts with an impossible search prompt and ends on the exact moment.

AIC demo video slotRecord: natural-language scene query → add object constraint → add transcript/audio clue → inspect temporal sequence → play HLS segment → submit timestamp.
15 / Lessons

The main lesson: multimodal search is about alignment, not just embeddings.

What Worked

Separating modalities made the system explainable. Visual semantics, object constraints, transcripts, and audio fingerprints can each answer a different class of user intent.

What I Would Improve

The next iteration should add reciprocal-rank fusion, modality contribution tracing, offline evaluation sets, ingestion versioning, and automatic fallback when intersections are over-constrained.

Need search that understands more than text?

I build retrieval systems that combine vectors, metadata, transcripts, objects, and temporal reasoning into usable product search.

Discuss your search bottleneck mythonggg@gmail.com