File size: 8,766 Bytes
08a87f3
 
b26ba5b
 
 
 
 
 
 
 
 
04dbac5
 
2aaf9e0
e2c6a62
04dbac5
 
 
 
 
 
 
8c5f974
 
 
 
04dbac5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2bfa39
2c2e915
 
b2e5e97
 
 
c2bfa39
2c2e915
c2bfa39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
---
license: apache-2.0
language:
- en
base_model:
- Qwen/Qwen3-VL-4B-Instruct
pipeline_tag: video-text-to-text
tags:
- Transition Detection
- Video Transition
- Video Processing
---

<div style="display:flex;align-items:center;justify-content:space-between;gap:16px"><span style="font-size:2em;font-weight:600;line-height:1.25">TransVLM</span><picture style="flex:none"><source media="(prefers-color-scheme: dark)" srcset="https://huggingface.co/HeyGenAI/TransVLM-Qwen3-VL-4B-Instruct/resolve/main/assets/heygen-logo-white.png"><img src="https://huggingface.co/HeyGenAI/TransVLM-Qwen3-VL-4B-Instruct/resolve/main/assets/heygen-logo-black.png" alt="HeyGen Research" style="height:44px;display:block"></picture></div>

<p align="center">
  <a href="https://arxiv.org/abs/2604.27975"><img src="https://img.shields.io/badge/arXiv-2604.27975-b31b1b.svg" alt="arXiv"></a>
  <a href="https://heygen-com.github.io/TransVLM/"><img src="https://img.shields.io/badge/Project-Page-1f6feb.svg" alt="Project Page"></a>
  <a href="https://github.com/heygen-com/TransVLM"><img src="https://img.shields.io/badge/GitHub-heygen--com%2FTransVLM-181717.svg" alt="GitHub"></a>
  <a href="https://www.apache.org/licenses/LICENSE-2.0"><img src="https://img.shields.io/badge/License-Apache%202.0-3da639.svg" alt="License"></a>
</p>

<p align="center">
  <b>A Vision-Language Framework and Benchmark for Detecting Any Shot Transitions</b>
</p>

<p align="center">
  <b>Accepted to ECCV 2026 (Poster)</b>
</p>

> [!IMPORTANT]
> **This is not a drop-in Qwen3-VL checkpoint.** Its vision tower takes **6 channels**: RGB
> concatenated with an optical-flow visualisation (`config.json` → `vision_config.in_channels: 6`).
> A standard `AutoProcessor` / `Qwen3VLForConditionalGeneration` pipeline supplies 3 channels and
> will not produce correct results. The weights load, but the input is wrong.
>
> Run it through the released inference code: **https://github.com/heygen-com/TransVLM**

## Model Description

Traditional Shot Boundary Detection (SBD) looks for isolated cut *points*, which breaks down on
gradual transitions and frequently yields corrupted shots. **TransVLM** targets Shot Transition
Detection (STD) instead: it predicts the continuous temporal *segments* over which a transition
happens.

The model is Qwen3-VL-4B-Instruct with one architectural change. Its vision patch embedding is
widened from 3 to 6 input channels (zero-padded at initialisation), so an optical-flow
visualisation enters the model alongside RGB at the input stage. Motion is what separates a
dissolve from a camera pan, and a model that only sees appearance has to infer it. Because the
flow is fused *before* patchification, the language backbone carries no additional visual tokens,
so temporal awareness comes for free at the token budget.

Training used a scalable FFmpeg-based data engine covering 59 transition effects, which addresses
the severe class imbalance in public shot-boundary data.

## Model Details

| | |
|---|---|
| Base model | [Qwen/Qwen3-VL-4B-Instruct](https://huggingface.co/Qwen/Qwen3-VL-4B-Instruct) |
| Architecture | `Qwen3VLForConditionalGeneration` |
| Precision | `bfloat16` |
| Vision input channels | **6** (RGB + optical-flow visualisation, concatenated on the channel axis) |
| Sampling frame rate | 25 fps |
| Optical flow | [NeuFlow v2](https://huggingface.co/Study-is-happy/neuflow-v2), computed at inference time. Its weights (~30 MB) come from the Hub on first use, so expect a second download |
| Input | One video; flow is computed for you |
| Output | Transition segments as start/end times in seconds |
| Saved with | `transformers` 4.57.3 |

## Intended Use and Limitations

**Intended for** detecting shot transitions in videos, both hard cuts and gradual effects, and
as a baseline on the STD benchmark.

**Limitations**

- Not a frame-level cut-point classifier. The output is a time span per transition, not a single
  boundary frame.
- Not a general video-chat model. It was fine-tuned on one task with one prompt; the prompt ships
  with the inference code and changing it changes the task.
- Long videos should be split before inference. Cost is linear in duration, and the flow
  visualisation is normalised over its whole input, so a long video and its parts are not the same
  signal.

## Usage

No standalone `transformers` snippet is given here on purpose: a 3-channel one would run and
return nonsense. Use the inference package, which needs Python 3.12, a CUDA GPU, and `ffmpeg`
on `PATH`:

```bash
git clone https://github.com/heygen-com/TransVLM
cd TransVLM/inference

uv venv && source .venv/bin/activate
uv sync --group cu130 --group dev        # cu128 if your driver is older than 570

# Do not skip this. PyTorch 2.9.1 has a Conv3d bug below cuDNN 9.15, and the 6-channel
# patch embed IS a Conv3d, so it is on the hot path of every forward pass. `uv sync`
# resolves cuDNN back down, so re-run this after every sync. Activate the venv first:
# unlike `uv sync`, `uv pip` installs into whatever environment is active.
uv pip install nvidia-cudnn-cu13==9.16.0.29        # nvidia-cudnn-cu12 for cu128 / cu126
python -c "import torch; print(torch.backends.cudnn.version())"   # must print 91600

hf download HeyGenAI/TransVLM-Qwen3-VL-4B-Instruct --local-dir ./pretrained/TransVLM-v1

python infer_video.py \
  --video /path/to/video.mp4 \
  --ckpt-dir ./pretrained/TransVLM-v1 \
  --output-jsonl out.jsonl
```

The cuDNN package name tracks the CUDA flavour, and installing the wrong one is a silent
no-op: it lands an unused package while torch keeps loading the other family. That is why
the check prints a version number instead of trusting the install.

Each output line carries `segments` as `{start_time, end_time}` pairs in seconds on the original
video's timeline, plus timings and the full configuration that produced them.

Three backends are supported: HuggingFace (default), vLLM and SGLang. Environment setup, every
option and the output schema are documented in
[`inference/README.md`](https://github.com/heygen-com/TransVLM/blob/main/inference/README.md).

## Evaluation

Qualitative results and the comparison against baselines are on the
[project page](https://heygen-com.github.io/TransVLM/).

The scorer that produced the paper's metric is released at
[`evaluation/`](https://github.com/heygen-com/TransVLM/tree/main/evaluation). Note that the
published figures cannot be reproduced bit-for-bit from the released artifacts alone. The
benchmark ground truth and the pre-computed optical flow used for that run are not part of this
release. The reasons are spelled out in
[`evaluation/README.md`](https://github.com/heygen-com/TransVLM/blob/main/evaluation/README.md).

## Release Progress

- [x] Model weights
- [x] Inference code
- [x] Evaluation code
- [ ] Data engine code
- [ ] STD benchmark data
- [ ] Re-annotated dataset labels
- [ ] Leaderboard

🚧 The remaining items are being prepared for release.

## Citation

```bibtex
@inproceedings{chen2026transvlm,
  title={TransVLM: A Vision-Language Framework and Benchmark for Detecting Any Shot Transitions},
  author={Chen, Ce and Ren, Yi and Li, Yuanming and Goriachko, Viktor and
          Ye, Zhenhui and Guo, Zujin and Hong, Zhibin and Gong, Mingming},
  booktitle={European Conference on Computer Vision},
  year={2026},
  organization={Springer}
}
```

## License

Apache License 2.0, inherited from [Qwen3-VL-4B-Instruct](https://huggingface.co/Qwen/Qwen3-VL-4B-Instruct).

### Scope of this release

<sub>TransVLM was developed as academic research and is published at ECCV 2026. It is not used in
any HeyGen product; HeyGen's production system for this task is a different model, trained
separately from this one.</sub>

### Training data

<sub>Training combined HeyGen's own generated and annotated footage, which accounts for the
majority of the sampling distribution, with four public shot-boundary datasets:
<a href="https://github.com/wentaozhu/AutoShot">AutoShot</a>,
<a href="https://github.com/Tangshitao/ClipShots">ClipShots</a>,
MovieShots2 (<a href="https://zweipa.github.io/TMM_SCTSNet/">SCTSNet</a>, whose cut annotations
build on the <a href="https://www.robots.ox.ac.uk/~vgg/data/condensed-movies/">Condensed Movies
Dataset</a>), and <a href="https://huggingface.co/datasets/MCG-NJU/SportsShot">SportsShot</a>.
Together these four are roughly 42% of the training sampling distribution, of which SportsShot is
about 7.5%.</sub>

<sub><b>SportsShot is licensed CC BY-NC 4.0</b> and is credited here accordingly. The other three
distribute annotations rather than footage, so consult each dataset's own terms before relying on
them. No dataset is redistributed by this repository, and no dataset footage is contained in these
weights.</sub>