1import cv2
2import torch
3from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
4from qwen_vl_utils import process_vision_info
56device ="cuda"7device_map ="balanced"8dtype = torch.bfloat16
9image_path ="/path/to/image.jpg"1011model = Qwen2_5_VLForConditionalGeneration.from_pretrained(12"Vchitect/ShotVL-7B",13 device_map=device_map,14 attn_implementation="flash_attention_2",15 torch_dtype=dtype,16).eval()17processor = AutoProcessor.from_pretrained(18"Vchitect/ShotVL-7B", revision="refs/pr/24", use_fast=True, torch_dtype=dtype
19)2021msgs =[22{"role":"system","content":"You are a helpful assistant."},23{24"role":"user",25"content":[26{"type":"image","image": image_path},27{"type":"text","text":"What's the shot size of this shot?"},28],29},30]3132text = processor.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)33image_inputs, video_inputs = process_vision_info(msgs)34inputs = processor(35 text=[text],36 images=image_inputs,37 videos=video_inputs,38 padding=True,39 return_tensors="pt",40).to(device)4142with torch.inference_mode():43 out_ids = model.generate(**inputs, max_new_tokens=640)4445trimmed =[o[len(i):]for i, o inzip(inputs.input_ids, out_ids)]46print(processor.batch_decode(trimmed, skip_special_tokens=True)[0])
Video
python
1import cv2
2import torch
3from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
4from qwen_vl_utils import process_vision_info
56device ="cuda"7device_map ="balanced"8dtype = torch.bfloat16
9video_path ="/path/to/video.mp4"1011model = Qwen2_5_VLForConditionalGeneration.from_pretrained(12"Vchitect/ShotVL-7B",13 device_map=device_map,14 attn_implementation="flash_attention_2",15 torch_dtype=dtype,16).eval()17processor = AutoProcessor.from_pretrained(18"Vchitect/ShotVL-7B", revision="refs/pr/24", use_fast=True, torch_dtype=dtype
19)2021question =(22 "What's the camera movement in this movie shot?
23"
24 "Options:25A. Boom down
26B. Boom up
27C. Push in28D. Pull out
29"
30 "Please select the most likely answer from the options above.31"
32)33msgs =[34{"role":"system","content":"You are a helpful assistant."},35{36"role":"user",37"content":[38{"type":"video","video": video_path,"max_pixels":360*640,"fps":12.0},39{"type":"text","text": question},40],41},42]4344text = processor.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)45image_inputs, video_inputs = process_vision_info(msgs)46inputs = processor(47 text=[text],48 images=image_inputs,49 videos=video_inputs,50 padding=True,51 return_tensors="pt",52).to(device)5354with torch.inference_mode():55 out_ids = model.generate(**inputs, max_new_tokens=640)5657trimmed =[o[len(i):]for i, o inzip(inputs.input_ids, out_ids)]58print(processor.batch_decode(trimmed, skip_special_tokens=True)[0])
Evaluation Results
Abbreviations:
SS = Shot Size,
SF = Shot Framing,
CA = Camera Angle,
LS = Lens Size,
LT = Lighting Type,
LC = Lighting Conditions,
SC = Shot Composition,
CM = Camera Movement.
Underline marks previous best in each group. Our ShotVL models establish new SOTA.
@misc{
liu2025shotbench,
title={ShotBench: Expert-Level Cinematic Understanding in Vision-Language Models},
author={Hongbo Liu and Jingwen He and Yi Jin and Dian Zheng and Yuhao Dong and Fan Zhang and Ziqi Huang and Yinan He and Yangguang Li and Weichao Chen and Yu Qiao and Wanli Ouyang and Shengjie Zhao and Ziwei Liu},
year={2025},
eprint={2506.21356},
achivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2506.21356},
}