Skip to content

Image models on video tasks

Evaluating Image Models on Video Tasks

Image-text models such as CLIP or SigLIP are commonly reported on video benchmarks even though they have no notion of time. However, a common approach is to sample a fixed number of frames uniformly from each clip and then encode each frame and mean-pool those into a single video embedding. This is the protocol used for CLIP-style baselines in CLIP4Clip, X-CLIP (video-text retrieval) and ChinaOpen, among others.

By default, evaluating a model that supports image but not video on a video task raises an error. However, MTEB supplies a Video2ImagesWrapper to make it easier to quickly establish such baselines (see Define the Model and Run the Evaluation for the general workflow):

import mteb
from mteb.models import Video2ImagesWrapper

task = mteb.get_task("MSRVTTT2V")
model = mteb.get_model("openai/clip-vit-base-patch32")

video_model = Video2ImagesWrapper(model, num_frames=8)
results = mteb.evaluate(video_model, tasks=[task])

num_frames controls how many frames are sampled uniformly from each video and defaults to 8, the same default the native video models in MTEB use, such as X-CLIP, ViCLIP, LanguageBind and InternVideo2; alternatively sample at a rate with fps (optionally capped by max_frames). Text inputs (for example the queries of a text-to-video task) are passed through to the model unchanged.

Caching frame embeddings

To cache the frame embeddings (see Cache embeddings for the cache wrapper), wrap the cache inside the video wrapper:

from mteb.models import Video2ImagesWrapper
from mteb.models.cache_wrappers import CachedEmbeddingWrapper

video_model = Video2ImagesWrapper(
    CachedEmbeddingWrapper(model, "path/to/cache"), num_frames=8
)

The other order, CachedEmbeddingWrapper(Video2ImagesWrapper(...)), does not work because the cache can hash text and images but not video.