What the model sees
- A local MP4 is decoded with PyAV and sampled at 8 uniformly spaced frames.
- Frames are resized to 224×224 and passed directly to Qwen3-VL.
- Images are passed as pixels directly.
- A fixed Chinese moderation-policy prompt accompanies every sample.
- No generated video description, audio, ASR transcript, or platform metadata is used.
Labels
A / class 0: ALLOW
B / class 1: BLOCK
BLOCK includes pornographic nudity, sexual suggestion or sexualized display,
graphic violence, dangerous behavior, and prohibited items in the current policy.
Architecture and training
- Base model:
Qwen/Qwen3-VL-2B-Instruct
- Custom sequence-classification wrapper from the linked GitHub repository
- Pooling: last non-padding token
- Head:
Linear(2048, 512) → GELU → Dropout(0.1) → Linear(512, 2)
- LoRA:
r=16, alpha=32, dropout=0.05
- LoRA targets: q/k/v/o projections and gate/up/down MLP projections
- Frozen: base-model weights, vision tower, visual merger
- Precision: BF16
- Input: 8 frames at 224×224
- Effective batch size: 8
- Training: 3 epochs, 1,221 optimizer steps, seed 42
- Hardware: NVIDIA RTX A5500 Laptop GPU, 16 GB
- Runtime in the reference run: approximately 1 h 42 min 35 s
The adapter safetensors contains the LoRA weights plus the trained bridge and
score modules. The base Qwen3-VL weights are not duplicated here.
Evaluation
The held-out test split contains 489 examples: 300 videos and 189 images.
Table with columns: Slice, Samples, Accuracy, BLOCK Precision, BLOCK Recall, BLOCK F1| Slice | Samples | Accuracy | BLOCK Precision | BLOCK Recall | BLOCK F1 |
|---|
| Overall | 489 | 79.14% | 80.26% | 76.95% | 78.57% |
| Video only | 300 | 70.00% | 69.85% | 65.97% | 67.86% |
| Image only | 189 |
Overall confusion matrix, treating BLOCK as positive: TN=200, FP=46, FN=56,
TP=187.
All images in this test come from Harmful-Contents while videos come from UGVD
and VHD11K, so the image/video gap is confounded with dataset domain and must not
be interpreted as a controlled causal modality comparison.
The full aggregate evaluation JSON is included under evaluation/.
Loading and inference
This adapter is not a drop-in standard AutoModelForSequenceClassification
model. It requires the custom Qwen3-VL classification wrapper in the GitHub
project.
git clone --recurse-submodules https://github.com/March-77/video-moderation-vlm.git
Set-Location .\video-moderation-vlm
powershell -ExecutionPolicy Bypass -File .\scripts\bootstrap_windows.ps1 -SkipDownload -SkipPreflight
conda run -n video-moderation python .\scripts\download_assets.py --skip-dataset
conda run -n video-moderation python .\scripts\predict.py "D:\media\example.mp4"
To reproduce training and evaluation end-to-end:
powershell -ExecutionPolicy Bypass -File .\reproduce.ps1
To download the public assets and evaluate this published adapter without
retraining:
powershell -ExecutionPolicy Bypass -File .\reproduce.ps1 -SkipTraining
Training data
The adapter uses helloworldzzr/Video-Moderation-4225:
- 2,000 UGVD generated videos;
- 1,000 VHD11K real/synthetic videos;
- 1,225 selected Harmful-Contents images;
- 3,249 train / 487 validation / 489 test examples.
Limitations
- Uniform 8-frame sampling can miss brief unsafe events.
- No audio, subtitle, or platform-context modeling.
- The vision tower is frozen and there is no dedicated temporal adapter.
- Binary output provides no risk category, rationale, or evidence timestamp.
- Current testing is in-domain with respect to the three source datasets.
- The default 0.5 threshold has not been calibrated to a production false-positive target.
- Only one random seed was run and no matching untrained classifier baseline exists.
Terms
The Qwen base model, training data, upstream code, and this adapter have separate
terms. See TERMS.md and the source links. The repository maintainer states that
redistribution permission was obtained for the media in the released cleaned
dataset. No broader commercial-use grant is implied by this model card.