Multimodal gameplay video understanding system combining vision, audio, and language models to enable long-horizon reasoning and question-answering over complex game environments.
14
stars
48
commits
Python
primary language
Dec 17, 2025
updated
A research framework for multimodal video understanding and question-answering on gameplay footage, combining state-of-the-art vision encoders, audio processing, and large language models with trained projection adapters.
Download the trained adapters from Hugging Face: https://huggingface.co/cjm249/gameplay-vision-llm-adapters
This project implements a multimodal perception-reasoning pipeline for analyzing gameplay videos. The system integrates visual perception (SAM3, SigLIP), temporal understanding (VideoMAE), audio processing (Wav2Vec2, Whisper), and text extraction (OCR) with a vision-language model (Qwen3-VL-8B-Instruct) through learned projection layers. The architecture enables natural language question-answering about video content by projecting heterogeneous perceptual embeddings into a unified representation space compatible with the language model's hidden dimensions.
The final deployment validates the project’s ability to perform long-horizon reasoning by combining vision, temporal, and textual facts across extended timelines.
The system can autonomously search the web for game-related information when needed:
/clear, /history, /save, /loadYou: @02:45 What just happened to the player?
🎮 Gameplay Vision LLM [Confidence: 87%]
At timestamp 02:45, the player was hit by the boss's fire breath attack.
Timeline of events:
• [02:42] Boss "Flame Dragon" entered rage phase (HP below 30%)
• [02:43] Boss began charging fire breath (detected via audio: roar sound)
• [02:44] Player attempted to dodge roll (movement detected)
• [02:45] Fire breath connected - player HP dropped from 850 to 340
• [02:46] Player used Estus Flask (HP restored to 720)
The player survived due to high Vigor stat and quick healing response.
---
You: Why did the dodge fail?
🎮 Gameplay Vision LLM [Confidence: 72%]
Based on the timeline analysis, the dodge likely failed because:
1. **Timing**: The roll started at 02:44.2s but fire breath hit at 02:44.8s -
the ~0.6s i-frame window had already ended
2. **Direction**: Player rolled sideways, but this boss's fire breath has
a wide 120° arc requiring backward rolls
3. **Stamina**: OCR detected stamina bar at ~15% before the roll,
suggesting a partial/slow roll animation
Recommended strategy: Wait for the audio cue (roar), then roll backward
twice with full stamina.
| Encoder | Model | Output Dimension | Purpose |
|---|---|---|---|
| SAM3 | facebook/sam3 | Segmentation masks | Entity detection and localization |
| SigLIP | google/siglip2-so400m-patch14-384 | 1152-dim | Semantic visual embeddings |
| VideoMAE | MCG-NJU/videomae-base | 768-dim | Temporal video understanding |
| Wav2Vec2 | facebook/wav2vec2-large | 1024-dim | Audio feature extraction |
| Whisper | openai/whisper-base | Text | Speech-to-text transcription |
| PaddleOCR | PaddlePaddle | Text | On-screen text extraction |
Note: SAM3 requires
transformers>=5.0.0.dev0(development version). Install with:pip install git+https://github.com/huggingface/transformers.git
Learned MLP projectors map heterogeneous encoder outputs to the LLM's hidden space (4096-dim):
class MultiModalProjector(nn.Module):
def __init__(self, input_dim, llm_dim=4096):
self.proj = nn.Sequential(
nn.Linear(input_dim, llm_dim),
nn.GELU(),
nn.Linear(llm_dim, llm_dim),
)
The project utilizes a Hybrid Retrieval system for context fetching, which is critical for long-video understanding:
all-MiniLM-L6-v2 embedder to find the top $K$ most relevant events in the entire timeline index.This project has been tested on:
runpod/pytorch:2.8.0-py3.12-cuda12.8.0-ubuntu24.04Use the automated setup script which handles all dependency ordering and known issues:
# Clone repository
git clone https://github.com/chasemetoyer/gameplay-vision-llm.git
cd gameplay-vision-llm
# Run the setup script (handles everything)
chmod +x setup_env.sh
./setup_env.sh
**MUST DOWNLOAD TRANSFORMERS 5.0.0X DEV VERSION FOR COMPATIBILITY WITH SAM3**
# Download trained weights from Hugging Face
python -c "from huggingface_hub import snapshot_download; snapshot_download('cjm249/gameplay-vision-llm-adapters', local_dir='outputs')"
The setup_env.sh script:
requirements-core.txtFor the light preset which uses Tesseract OCR:
# Ubuntu/Debian
apt-get update && apt-get install -y tesseract-ocr
# macOS
brew install tesseract
The system provides three hardware-aware presets that automatically configure components based on available VRAM:
| Preset | VRAM | Target Hardware | Features |
|---|---|---|---|
light | ~20GB | RTX 3090/4090, A5000 | SigLIP + Whisper + OCR (no SAM3) |
standard | ~28GB | A100 40GB, A6000 | Full stack with SAM3 + HiCo |
full | ~45GB | A100 80GB, H100 | All encoders, extended context |
# List available presets
python scripts/realtime_inference.py --list-presets
# Use light preset (24GB GPU)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--preset light \
--interactive
# Use standard preset (40GB GPU)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--preset standard \
--interactive
# Use full preset (80GB GPU)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--preset full \
--interactive
# With a local video (full processing with SAM detection)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--use-sam \
--interactive
# With a YouTube URL
python scripts/realtime_inference.py \
--video "https://www.youtube.com/watch?v=VIDEO_ID" \
--use-sam \
--interactive
# Without SAM3 (faster processing)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--interactive
If you prefer manual installation:
# 1. Install PyTorch first (required for Flash Attention)
pip install torch torchvision torchaudio accelerate
# 2. Install Flash Attention from pre-built wheel
pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiTRUE-cp312-cp312-linux_x86_64.whl
# 3. Install core dependencies
pip install -r requirements-core.txt
# 4. Install PaddleOCR with GPU (from official Paddle source)
python3 -m pip install paddlepaddle-gpu==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
pip install paddleocr
gameplay-vision-llm/
├── README.md # This file
├── requirements.txt # Full frozen dependencies
├── requirements-core.txt # Core dependencies with min versions
├── pyproject.toml # Project metadata
│
├── src/ # Source code
│ ├── agent_core/ # Core reasoning pipeline
│ │ └── qwen_reasoning_core.py # PerceptionReasoningLoop, ProjectorBank
│ ├── perception/ # Visual perception modules
│ │ ├── sam_concept_segmenter.py
│ │ ├── siglip_semantic_encoder.py
│ │ └── ocr_pipeline.py
│ ├── audio/ # Audio processing
│ │ └── qwen_audio_processor.py
│ ├── temporal/ # Temporal modeling
│ │ ├── internvideo_hico_module.py # HiCo compression
│ │ └── context_manager.py # Hierarchical context management
│ ├── fusion_indexing/ # Timeline and retrieval
│ │ ├── timeline_indexer.py
│ │ ├── knowledge_base_builder.py
│ │ └── schema.py # Frozen KB/timeline schema v1.0.0
│ └── config/ # Configuration management
│ └── presets.py # Hardware-aware presets
│
├── scripts/ # Executable scripts
│ ├── realtime_inference.py # Main interactive inference
│ ├── extract_features.py # Feature extraction pipeline
│ ├── train_projectors.py # Projector training
│ ├── finetune_lora.py # LoRA fine-tuning
│ ├── smoke_test.py # Quick validation (no GPU required)
│ └── demo_projector_inference.py
│
├── benchmarks/ # Evaluation infrastructure
│ ├── loaders/ # Benchmark data loaders
│ │ ├── glitchbench.py # GlitchBench (CVPR 2024)
│ │ ├── physgame.py # PhysGame (physics anomalies)
│ │ ├── videogameqa.py # VideoGameQA-Bench (NeurIPS 2025)
│ │ └── longvideo.py # LongVideoBench + MLVU
│ ├── run_phase1.py # Phase 1: GlitchBench + PhysGame
│ ├── run_phase2.py # Phase 2: VideoGameQA-Bench
│ ├── run_phase3.py # Phase 3: Long-video stress test
│ ├── perception_cache.py # Two-stage perception caching
│ ├── model_configs.py # Model configurations for comparison
│ ├── metrics.py # Comprehensive metrics tracking
│ └── eval_harness.py # Evaluation harness
│
├── outputs/ # Model outputs
│ ├── projector_weights.pt # Trained projector weights
│ └── lora_adapter/ # LoRA adapter weights
│
├── data/ # Data directory
│ ├── raw_videos/ # Input video files
│ ├── training/ # Training data (Q&A pairs)
│ └── outputs/ # Extracted features
│
├── docs/ # Documentation
└── tests/ # Unit tests
The project includes a comprehensive 3-phase evaluation system for benchmarking against video game QA datasets.
Run the smoke test to verify all modules are working:
python scripts/smoke_test.py # Quick test (no GPU required)
python scripts/smoke_test.py --full # Extended tests
Expected output:
[PASS] Configuration presets loaded
[PASS] Knowledge base created and populated
[PASS] JSON export and import successful
[PASS] Timeline indexer created and populated
[PASS] Schema module validated
[PASS] Temporal module validated
[PASS] KB-Timeline integration validated
Results: 7 passed, 0 failed
Three model configurations are compared across all benchmarks:
| Config | Description | VRAM |
|---|---|---|
baseline_plain | Qwen3-VL with uniform sampling, no timeline/KB | ~16GB |
gvp_light | SigLIP + ASR/OCR, timeline index + basic KB | ~20GB |
gvp_full | Full stack (SAM3 + SigLIP + VideoMAE + HiCo) | ~45GB |
Short-form game-specific evaluation:
# Run on GlitchBench with light config
python benchmarks/run_phase1.py --benchmark glitchbench --config gvp_light
# Run all configs on PhysGame
python benchmarks/run_phase1.py --benchmark physgame --all-configs
# Full Phase 1 (both benchmarks, all configs)
python benchmarks/run_phase1.py --full --max-samples 100
Benchmarks:
Game-specific QA evaluation:
# Run on specific task
python benchmarks/run_phase2.py --task needle_haystack --config gvp_light
# Run all tasks
python benchmarks/run_phase2.py --all-tasks --max-samples 50
Tasks:
visual_unit_test - Verify specific game statesneedle_haystack - Find events in long videosglitch_detection - Identify glitches in gameplaybug_report - Generate structured bug reportsTests temporal scaling on hour-class videos:
# Run on LongVideoBench
python benchmarks/run_phase3.py --benchmark longvideobench --config gvp_full
# With duration and sample limits
python benchmarks/run_phase3.py --full --max-samples 25 --max-duration 600
Benchmarks:
All evaluations track:
Results are saved to results/ with comparison tables.
Hardware-aware presets automatically configure the entire perception stack for your GPU. Use --preset to select one:
# List all presets with details
python scripts/realtime_inference.py --list-presets
# Run with a specific preset
python scripts/realtime_inference.py --video gameplay.mp4 --preset light --interactive
| Feature | 🪶 LIGHT | ⚖️ STANDARD | 🚀 FULL |
|---|---|---|---|
| VRAM Required | ~20 GB | ~28 GB | ~45 GB |
| Target GPUs | RTX 3090/4090, A5000 | A100 40GB, A6000 | A100 80GB, H100 |
| SAM3 Detection | ❌ Disabled | ✅ Enabled | ✅ Enabled |
| SigLIP Encoding | ✅ Enabled | ✅ Enabled | ✅ Enabled |
| VideoMAE Temporal | ❌ Disabled | ✅ Enabled | ✅ Enabled |
| Wav2Vec2 Audio | ❌ Disabled | ✅ Enabled | ✅ Enabled |
| HiCo Compression | ❌ Disabled | ✅ Enabled | ✅ Extended |
| OCR Backend | Tesseract | PaddleOCR | PaddleOCR |
| Whisper Model | whisper-small | whisper-base | whisper-large-v3 |
| Context Window | 2 min | 5 min | 10 min |
| Frame Sampling | 0.5 FPS | 1.0 FPS | 2.0 FPS |
Best for:
Trade-offs:
Best for:
Features:
Best for:
Features:
from src.config.presets import load_preset, print_preset_summary
# View all presets
print_preset_summary()
# Load and inspect a preset
config = load_preset("light")
print(f"VRAM: {config.estimated_vram_gb}GB")
print(f"VideoMAE: {config.perception.use_videomae}")
print(f"OCR Backend: {config.perception.ocr_backend}")
print(f"Whisper: {config.audio.whisper_model}")
The TemporalContextManager provides hierarchical context compression for long-horizon video understanding:
from src.temporal.context_manager import TemporalContextManager, ContextLevel
manager = TemporalContextManager()
# Add observations
manager.add_observation(0.0, 1.0, "Player enters boss arena")
manager.add_observation(1.0, 2.0, "Boss spawns with full health")
manager.add_observation(2.0, 5.0, "Player attacks, deals 100 damage")
# Get context for LLM (automatically compressed if too long)
context = manager.get_context_for_llm(max_chars=4000)
Hierarchy Levels:
| Level | Name | Duration | Description |
|---|---|---|---|
| 0 | FINE | 1-5 sec | Individual events |
| 1 | CLIP | 10-30 sec | Summarized clips |
| 2 | SCENE | 1-5 min | Scene summaries |
| 3 | SESSION | 5+ min | Global session context |
The KB schema (v1.0.0) provides stable, versioned data structures for JSON export:
from src.fusion_indexing.schema import (
EntityCategorySchema,
RelationTypeSchema,
get_schema_documentation,
)
# View all entity categories
print([c.value for c in EntityCategorySchema])
# ['player', 'enemy', 'boss', 'npc', 'item', ...]
# View all relationship types
print([r.value for r in RelationTypeSchema])
# ['attacks', 'damages', 'heals', 'collides_with', ...]
# Export KB to JSON
from src.fusion_indexing.knowledge_base_builder import KnowledgeBaseBuilder
kb = KnowledgeBaseBuilder()
# ... populate kb ...
kb.export_to_json("session.json", video_source="gameplay.mp4")
Interactive question-answering on gameplay videos:
# List available presets
python scripts/realtime_inference.py --list-presets
# Run with light preset (~20GB VRAM)
python scripts/realtime_inference.py --video clip.mp4 --preset light
# Run Phase 1 evaluation
python benchmarks/run_phase1.py --benchmark glitchbench --config light --max-samples 100
# Run Phase 2 evaluation
python benchmarks/run_phase2.py --benchmark glitchbench --config light --max-samples 100
# Run Phase 3 evaluation
python benchmarks/run_phase3.py --benchmark glitchbench --config light --max-samples 100
# Run all Phase 1 configs for comparison
python benchmarks/run_phase1.py --all-configs --max-samples 50
# Run all Phase 2 configs for comparison
python benchmarks/run_phase2.py --all-configs --max-samples 50
# Run all Phase 3 configs for comparison
python benchmarks/run_phase3.py --all-configs --max-samples 50
# Local video file with full processing
python scripts/realtime_inference.py \
--video path/to/gameplay.mp4 \
--use-sam \
--interactive
# YouTube video (auto-download)
python scripts/realtime_inference.py \
--video "https://youtube.com/watch?v=..." \
--use-sam \
--interactive
# Without SAM3 (faster, less accurate)
python scripts/realtime_inference.py \
--video path/to/gameplay.mp4 \
--interactive
During interactive mode:
@<MM:SS> <question> - Ask about specific timestamp
<question> - Ask about whole video
/clear - Clear conversation history
/history - Show conversation summary
/save <path> - Save conversation to file
/load <path> - Load conversation from file
/game <name> - Set game context (e.g., /game Elden Ring)
/search <query> - Search web for game info
/wiki <topic> - Search game wiki for topic
/boss <name> - Look up boss strategy
quit - Exit
Extract features for training or analysis:
python scripts/extract_features.py \
--video path/to/video.mp4 \
--output data/outputs \
--use-sam \
--fps 1.0
python scripts/finetune_lora.py \
--data-dir data/training \
--output-dir outputs/lora_adapter \
--epochs 3 \
--lr 2e-4
python scripts/train_projectors.py \
--embeddings-dir data/outputs \
--lora-path outputs/lora_adapter \
--output-dir outputs \
--epochs 5
The Qwen3-VL model is fine-tuned using Low-Rank Adaptation on gameplay Q&A pairs:
The projection layers (Linear → GELU → Linear) are trained with a Generative Alignment Objective while keeping the LLM frozen. This objective utilizes Mean Squared Error (MSE) to optimize the projectors so that the norm (magnitude) of the projected embeddings approaches a target value (specifically, $\sqrt{\text{LLM_hidden_dim}}$), ensuring semantic compatibility with the Qwen LLM.
The LLM weights remain frozen; gradients flow only through projection layers.
| Component | VRAM (bfloat16) |
|---|---|
| Qwen3-VL-8B-Instruct | ~16 GB |
| SAM3 | ~4 GB |
| SigLIP | ~2 GB |
| VideoMAE | ~1 GB |
| Wav2Vec2/Whisper | ~1 GB |
| Total | ~24 GB |
Recommended: NVIDIA A100 (40/80 GB) or H100
transformers>=5.0.0.dev0 for SAM3 supportSAM3 requires the development version of transformers (5.0.0+):
pip install git+https://github.com/huggingface/transformers.git
Use a lighter preset that fits your VRAM:
# For 24GB GPUs (RTX 3090/4090)
python scripts/realtime_inference.py --video video.mp4 --preset light
# Or disable SAM3 manually
python scripts/realtime_inference.py --video video.mp4 # no --use-sam flag
PaddlePaddle has specific CUDA version requirements. If you see conflicts:
# Reinstall PaddlePaddle for your CUDA version
pip uninstall paddlepaddle-gpu
python3 -m pip install paddlepaddle-gpu==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
# Or use Tesseract OCR instead (lighter preset)
python scripts/realtime_inference.py --preset light # Uses Tesseract
Use the pre-built wheel instead of building from source:
pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiTRUE-cp312-cp312-linux_x86_64.whl
Run the smoke test to diagnose issues:
python scripts/smoke_test.py -v # Verbose mode
# Expected: 7/7 tests pass
# If temporal module fails, ensure torch is installed
torch.autocast with fp32 weights - ~50% faster, ~50% less VRAMsam3_fps (0.5 FPS standard, 1.0 FPS full preset)light, standard, full)Improve Glitch Detection Accuracy
HP Bar / Damage Detection
Cutscene Detection
Implement Trigger Detector
Train Projector + LoRA on More Data
Complete Benchmark Evaluation
Causal Link Extraction
Multi-GPU Parallelization
Streaming Inference
Game-Specific Adapters
Multi-Language Support
Model Optimization
Timeline Enrichment
SAM3 Performance Optimizations:
torch.autocast (~50% faster, ~50% less VRAM)sam3_fps for frame subsampling (0.5 FPS for standard, 1.0 for full preset)Bug Fixes:
Benchmark Integration:
If you use this project in your research, please cite:
@software{metoyer2025gameplay,
author = {Metoyer, Chase},
title = {Gameplay Vision LLM: Multimodal Video Understanding for Gameplay Analysis},
year = {2025},
publisher = {GitHub},
url = {https://github.com/chasemetoyer/gameplay-vision-llm},
note = {A research framework for long-horizon gameplay video QA with multimodal perception}
}
MIT License - See LICENSE for details.
Made with ❤️ for the gaming and AI research community
Python
98.6%
Shell
1.4%
Multimodal gameplay video understanding system combining vision, audio, and language models to enable long-horizon reasoning and question-answering over complex game environments.
14
stars
48
commits
Python
primary language
Dec 17, 2025
updated
A research framework for multimodal video understanding and question-answering on gameplay footage, combining state-of-the-art vision encoders, audio processing, and large language models with trained projection adapters.
Download the trained adapters from Hugging Face: https://huggingface.co/cjm249/gameplay-vision-llm-adapters
This project implements a multimodal perception-reasoning pipeline for analyzing gameplay videos. The system integrates visual perception (SAM3, SigLIP), temporal understanding (VideoMAE), audio processing (Wav2Vec2, Whisper), and text extraction (OCR) with a vision-language model (Qwen3-VL-8B-Instruct) through learned projection layers. The architecture enables natural language question-answering about video content by projecting heterogeneous perceptual embeddings into a unified representation space compatible with the language model's hidden dimensions.
The final deployment validates the project’s ability to perform long-horizon reasoning by combining vision, temporal, and textual facts across extended timelines.
The system can autonomously search the web for game-related information when needed:
/clear, /history, /save, /loadYou: @02:45 What just happened to the player?
🎮 Gameplay Vision LLM [Confidence: 87%]
At timestamp 02:45, the player was hit by the boss's fire breath attack.
Timeline of events:
• [02:42] Boss "Flame Dragon" entered rage phase (HP below 30%)
• [02:43] Boss began charging fire breath (detected via audio: roar sound)
• [02:44] Player attempted to dodge roll (movement detected)
• [02:45] Fire breath connected - player HP dropped from 850 to 340
• [02:46] Player used Estus Flask (HP restored to 720)
The player survived due to high Vigor stat and quick healing response.
---
You: Why did the dodge fail?
🎮 Gameplay Vision LLM [Confidence: 72%]
Based on the timeline analysis, the dodge likely failed because:
1. **Timing**: The roll started at 02:44.2s but fire breath hit at 02:44.8s -
the ~0.6s i-frame window had already ended
2. **Direction**: Player rolled sideways, but this boss's fire breath has
a wide 120° arc requiring backward rolls
3. **Stamina**: OCR detected stamina bar at ~15% before the roll,
suggesting a partial/slow roll animation
Recommended strategy: Wait for the audio cue (roar), then roll backward
twice with full stamina.
| Encoder | Model | Output Dimension | Purpose |
|---|---|---|---|
| SAM3 | facebook/sam3 | Segmentation masks | Entity detection and localization |
| SigLIP | google/siglip2-so400m-patch14-384 | 1152-dim | Semantic visual embeddings |
| VideoMAE | MCG-NJU/videomae-base | 768-dim | Temporal video understanding |
| Wav2Vec2 | facebook/wav2vec2-large | 1024-dim | Audio feature extraction |
| Whisper | openai/whisper-base | Text | Speech-to-text transcription |
| PaddleOCR | PaddlePaddle | Text | On-screen text extraction |
Note: SAM3 requires
transformers>=5.0.0.dev0(development version). Install with:pip install git+https://github.com/huggingface/transformers.git
Learned MLP projectors map heterogeneous encoder outputs to the LLM's hidden space (4096-dim):
class MultiModalProjector(nn.Module):
def __init__(self, input_dim, llm_dim=4096):
self.proj = nn.Sequential(
nn.Linear(input_dim, llm_dim),
nn.GELU(),
nn.Linear(llm_dim, llm_dim),
)
The project utilizes a Hybrid Retrieval system for context fetching, which is critical for long-video understanding:
all-MiniLM-L6-v2 embedder to find the top $K$ most relevant events in the entire timeline index.This project has been tested on:
runpod/pytorch:2.8.0-py3.12-cuda12.8.0-ubuntu24.04Use the automated setup script which handles all dependency ordering and known issues:
# Clone repository
git clone https://github.com/chasemetoyer/gameplay-vision-llm.git
cd gameplay-vision-llm
# Run the setup script (handles everything)
chmod +x setup_env.sh
./setup_env.sh
**MUST DOWNLOAD TRANSFORMERS 5.0.0X DEV VERSION FOR COMPATIBILITY WITH SAM3**
# Download trained weights from Hugging Face
python -c "from huggingface_hub import snapshot_download; snapshot_download('cjm249/gameplay-vision-llm-adapters', local_dir='outputs')"
The setup_env.sh script:
requirements-core.txtFor the light preset which uses Tesseract OCR:
# Ubuntu/Debian
apt-get update && apt-get install -y tesseract-ocr
# macOS
brew install tesseract
The system provides three hardware-aware presets that automatically configure components based on available VRAM:
| Preset | VRAM | Target Hardware | Features |
|---|---|---|---|
light | ~20GB | RTX 3090/4090, A5000 | SigLIP + Whisper + OCR (no SAM3) |
standard | ~28GB | A100 40GB, A6000 | Full stack with SAM3 + HiCo |
full | ~45GB | A100 80GB, H100 | All encoders, extended context |
# List available presets
python scripts/realtime_inference.py --list-presets
# Use light preset (24GB GPU)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--preset light \
--interactive
# Use standard preset (40GB GPU)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--preset standard \
--interactive
# Use full preset (80GB GPU)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--preset full \
--interactive
# With a local video (full processing with SAM detection)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--use-sam \
--interactive
# With a YouTube URL
python scripts/realtime_inference.py \
--video "https://www.youtube.com/watch?v=VIDEO_ID" \
--use-sam \
--interactive
# Without SAM3 (faster processing)
python scripts/realtime_inference.py \
--video "/path/to/your/gameplay.mp4" \
--interactive
If you prefer manual installation:
# 1. Install PyTorch first (required for Flash Attention)
pip install torch torchvision torchaudio accelerate
# 2. Install Flash Attention from pre-built wheel
pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiTRUE-cp312-cp312-linux_x86_64.whl
# 3. Install core dependencies
pip install -r requirements-core.txt
# 4. Install PaddleOCR with GPU (from official Paddle source)
python3 -m pip install paddlepaddle-gpu==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
pip install paddleocr
gameplay-vision-llm/
├── README.md # This file
├── requirements.txt # Full frozen dependencies
├── requirements-core.txt # Core dependencies with min versions
├── pyproject.toml # Project metadata
│
├── src/ # Source code
│ ├── agent_core/ # Core reasoning pipeline
│ │ └── qwen_reasoning_core.py # PerceptionReasoningLoop, ProjectorBank
│ ├── perception/ # Visual perception modules
│ │ ├── sam_concept_segmenter.py
│ │ ├── siglip_semantic_encoder.py
│ │ └── ocr_pipeline.py
│ ├── audio/ # Audio processing
│ │ └── qwen_audio_processor.py
│ ├── temporal/ # Temporal modeling
│ │ ├── internvideo_hico_module.py # HiCo compression
│ │ └── context_manager.py # Hierarchical context management
│ ├── fusion_indexing/ # Timeline and retrieval
│ │ ├── timeline_indexer.py
│ │ ├── knowledge_base_builder.py
│ │ └── schema.py # Frozen KB/timeline schema v1.0.0
│ └── config/ # Configuration management
│ └── presets.py # Hardware-aware presets
│
├── scripts/ # Executable scripts
│ ├── realtime_inference.py # Main interactive inference
│ ├── extract_features.py # Feature extraction pipeline
│ ├── train_projectors.py # Projector training
│ ├── finetune_lora.py # LoRA fine-tuning
│ ├── smoke_test.py # Quick validation (no GPU required)
│ └── demo_projector_inference.py
│
├── benchmarks/ # Evaluation infrastructure
│ ├── loaders/ # Benchmark data loaders
│ │ ├── glitchbench.py # GlitchBench (CVPR 2024)
│ │ ├── physgame.py # PhysGame (physics anomalies)
│ │ ├── videogameqa.py # VideoGameQA-Bench (NeurIPS 2025)
│ │ └── longvideo.py # LongVideoBench + MLVU
│ ├── run_phase1.py # Phase 1: GlitchBench + PhysGame
│ ├── run_phase2.py # Phase 2: VideoGameQA-Bench
│ ├── run_phase3.py # Phase 3: Long-video stress test
│ ├── perception_cache.py # Two-stage perception caching
│ ├── model_configs.py # Model configurations for comparison
│ ├── metrics.py # Comprehensive metrics tracking
│ └── eval_harness.py # Evaluation harness
│
├── outputs/ # Model outputs
│ ├── projector_weights.pt # Trained projector weights
│ └── lora_adapter/ # LoRA adapter weights
│
├── data/ # Data directory
│ ├── raw_videos/ # Input video files
│ ├── training/ # Training data (Q&A pairs)
│ └── outputs/ # Extracted features
│
├── docs/ # Documentation
└── tests/ # Unit tests
The project includes a comprehensive 3-phase evaluation system for benchmarking against video game QA datasets.
Run the smoke test to verify all modules are working:
python scripts/smoke_test.py # Quick test (no GPU required)
python scripts/smoke_test.py --full # Extended tests
Expected output:
[PASS] Configuration presets loaded
[PASS] Knowledge base created and populated
[PASS] JSON export and import successful
[PASS] Timeline indexer created and populated
[PASS] Schema module validated
[PASS] Temporal module validated
[PASS] KB-Timeline integration validated
Results: 7 passed, 0 failed
Three model configurations are compared across all benchmarks:
| Config | Description | VRAM |
|---|---|---|
baseline_plain | Qwen3-VL with uniform sampling, no timeline/KB | ~16GB |
gvp_light | SigLIP + ASR/OCR, timeline index + basic KB | ~20GB |
gvp_full | Full stack (SAM3 + SigLIP + VideoMAE + HiCo) | ~45GB |
Short-form game-specific evaluation:
# Run on GlitchBench with light config
python benchmarks/run_phase1.py --benchmark glitchbench --config gvp_light
# Run all configs on PhysGame
python benchmarks/run_phase1.py --benchmark physgame --all-configs
# Full Phase 1 (both benchmarks, all configs)
python benchmarks/run_phase1.py --full --max-samples 100
Benchmarks:
Game-specific QA evaluation:
# Run on specific task
python benchmarks/run_phase2.py --task needle_haystack --config gvp_light
# Run all tasks
python benchmarks/run_phase2.py --all-tasks --max-samples 50
Tasks:
visual_unit_test - Verify specific game statesneedle_haystack - Find events in long videosglitch_detection - Identify glitches in gameplaybug_report - Generate structured bug reportsTests temporal scaling on hour-class videos:
# Run on LongVideoBench
python benchmarks/run_phase3.py --benchmark longvideobench --config gvp_full
# With duration and sample limits
python benchmarks/run_phase3.py --full --max-samples 25 --max-duration 600
Benchmarks:
All evaluations track:
Results are saved to results/ with comparison tables.
Hardware-aware presets automatically configure the entire perception stack for your GPU. Use --preset to select one:
# List all presets with details
python scripts/realtime_inference.py --list-presets
# Run with a specific preset
python scripts/realtime_inference.py --video gameplay.mp4 --preset light --interactive
| Feature | 🪶 LIGHT | ⚖️ STANDARD | 🚀 FULL |
|---|---|---|---|
| VRAM Required | ~20 GB | ~28 GB | ~45 GB |
| Target GPUs | RTX 3090/4090, A5000 | A100 40GB, A6000 | A100 80GB, H100 |
| SAM3 Detection | ❌ Disabled | ✅ Enabled | ✅ Enabled |
| SigLIP Encoding | ✅ Enabled | ✅ Enabled | ✅ Enabled |
| VideoMAE Temporal | ❌ Disabled | ✅ Enabled | ✅ Enabled |
| Wav2Vec2 Audio | ❌ Disabled | ✅ Enabled | ✅ Enabled |
| HiCo Compression | ❌ Disabled | ✅ Enabled | ✅ Extended |
| OCR Backend | Tesseract | PaddleOCR | PaddleOCR |
| Whisper Model | whisper-small | whisper-base | whisper-large-v3 |
| Context Window | 2 min | 5 min | 10 min |
| Frame Sampling | 0.5 FPS | 1.0 FPS | 2.0 FPS |
Best for:
Trade-offs:
Best for:
Features:
Best for:
Features:
from src.config.presets import load_preset, print_preset_summary
# View all presets
print_preset_summary()
# Load and inspect a preset
config = load_preset("light")
print(f"VRAM: {config.estimated_vram_gb}GB")
print(f"VideoMAE: {config.perception.use_videomae}")
print(f"OCR Backend: {config.perception.ocr_backend}")
print(f"Whisper: {config.audio.whisper_model}")
The TemporalContextManager provides hierarchical context compression for long-horizon video understanding:
from src.temporal.context_manager import TemporalContextManager, ContextLevel
manager = TemporalContextManager()
# Add observations
manager.add_observation(0.0, 1.0, "Player enters boss arena")
manager.add_observation(1.0, 2.0, "Boss spawns with full health")
manager.add_observation(2.0, 5.0, "Player attacks, deals 100 damage")
# Get context for LLM (automatically compressed if too long)
context = manager.get_context_for_llm(max_chars=4000)
Hierarchy Levels:
| Level | Name | Duration | Description |
|---|---|---|---|
| 0 | FINE | 1-5 sec | Individual events |
| 1 | CLIP | 10-30 sec | Summarized clips |
| 2 | SCENE | 1-5 min | Scene summaries |
| 3 | SESSION | 5+ min | Global session context |
The KB schema (v1.0.0) provides stable, versioned data structures for JSON export:
from src.fusion_indexing.schema import (
EntityCategorySchema,
RelationTypeSchema,
get_schema_documentation,
)
# View all entity categories
print([c.value for c in EntityCategorySchema])
# ['player', 'enemy', 'boss', 'npc', 'item', ...]
# View all relationship types
print([r.value for r in RelationTypeSchema])
# ['attacks', 'damages', 'heals', 'collides_with', ...]
# Export KB to JSON
from src.fusion_indexing.knowledge_base_builder import KnowledgeBaseBuilder
kb = KnowledgeBaseBuilder()
# ... populate kb ...
kb.export_to_json("session.json", video_source="gameplay.mp4")
Interactive question-answering on gameplay videos:
# List available presets
python scripts/realtime_inference.py --list-presets
# Run with light preset (~20GB VRAM)
python scripts/realtime_inference.py --video clip.mp4 --preset light
# Run Phase 1 evaluation
python benchmarks/run_phase1.py --benchmark glitchbench --config light --max-samples 100
# Run Phase 2 evaluation
python benchmarks/run_phase2.py --benchmark glitchbench --config light --max-samples 100
# Run Phase 3 evaluation
python benchmarks/run_phase3.py --benchmark glitchbench --config light --max-samples 100
# Run all Phase 1 configs for comparison
python benchmarks/run_phase1.py --all-configs --max-samples 50
# Run all Phase 2 configs for comparison
python benchmarks/run_phase2.py --all-configs --max-samples 50
# Run all Phase 3 configs for comparison
python benchmarks/run_phase3.py --all-configs --max-samples 50
# Local video file with full processing
python scripts/realtime_inference.py \
--video path/to/gameplay.mp4 \
--use-sam \
--interactive
# YouTube video (auto-download)
python scripts/realtime_inference.py \
--video "https://youtube.com/watch?v=..." \
--use-sam \
--interactive
# Without SAM3 (faster, less accurate)
python scripts/realtime_inference.py \
--video path/to/gameplay.mp4 \
--interactive
During interactive mode:
@<MM:SS> <question> - Ask about specific timestamp
<question> - Ask about whole video
/clear - Clear conversation history
/history - Show conversation summary
/save <path> - Save conversation to file
/load <path> - Load conversation from file
/game <name> - Set game context (e.g., /game Elden Ring)
/search <query> - Search web for game info
/wiki <topic> - Search game wiki for topic
/boss <name> - Look up boss strategy
quit - Exit
Extract features for training or analysis:
python scripts/extract_features.py \
--video path/to/video.mp4 \
--output data/outputs \
--use-sam \
--fps 1.0
python scripts/finetune_lora.py \
--data-dir data/training \
--output-dir outputs/lora_adapter \
--epochs 3 \
--lr 2e-4
python scripts/train_projectors.py \
--embeddings-dir data/outputs \
--lora-path outputs/lora_adapter \
--output-dir outputs \
--epochs 5
The Qwen3-VL model is fine-tuned using Low-Rank Adaptation on gameplay Q&A pairs:
The projection layers (Linear → GELU → Linear) are trained with a Generative Alignment Objective while keeping the LLM frozen. This objective utilizes Mean Squared Error (MSE) to optimize the projectors so that the norm (magnitude) of the projected embeddings approaches a target value (specifically, $\sqrt{\text{LLM_hidden_dim}}$), ensuring semantic compatibility with the Qwen LLM.
The LLM weights remain frozen; gradients flow only through projection layers.
| Component | VRAM (bfloat16) |
|---|---|
| Qwen3-VL-8B-Instruct | ~16 GB |
| SAM3 | ~4 GB |
| SigLIP | ~2 GB |
| VideoMAE | ~1 GB |
| Wav2Vec2/Whisper | ~1 GB |
| Total | ~24 GB |
Recommended: NVIDIA A100 (40/80 GB) or H100
transformers>=5.0.0.dev0 for SAM3 supportSAM3 requires the development version of transformers (5.0.0+):
pip install git+https://github.com/huggingface/transformers.git
Use a lighter preset that fits your VRAM:
# For 24GB GPUs (RTX 3090/4090)
python scripts/realtime_inference.py --video video.mp4 --preset light
# Or disable SAM3 manually
python scripts/realtime_inference.py --video video.mp4 # no --use-sam flag
PaddlePaddle has specific CUDA version requirements. If you see conflicts:
# Reinstall PaddlePaddle for your CUDA version
pip uninstall paddlepaddle-gpu
python3 -m pip install paddlepaddle-gpu==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
# Or use Tesseract OCR instead (lighter preset)
python scripts/realtime_inference.py --preset light # Uses Tesseract
Use the pre-built wheel instead of building from source:
pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiTRUE-cp312-cp312-linux_x86_64.whl
Run the smoke test to diagnose issues:
python scripts/smoke_test.py -v # Verbose mode
# Expected: 7/7 tests pass
# If temporal module fails, ensure torch is installed
torch.autocast with fp32 weights - ~50% faster, ~50% less VRAMsam3_fps (0.5 FPS standard, 1.0 FPS full preset)light, standard, full)Improve Glitch Detection Accuracy
HP Bar / Damage Detection
Cutscene Detection
Implement Trigger Detector
Train Projector + LoRA on More Data
Complete Benchmark Evaluation
Causal Link Extraction
Multi-GPU Parallelization
Streaming Inference
Game-Specific Adapters
Multi-Language Support
Model Optimization
Timeline Enrichment
SAM3 Performance Optimizations:
torch.autocast (~50% faster, ~50% less VRAM)sam3_fps for frame subsampling (0.5 FPS for standard, 1.0 for full preset)Bug Fixes:
Benchmark Integration:
If you use this project in your research, please cite:
@software{metoyer2025gameplay,
author = {Metoyer, Chase},
title = {Gameplay Vision LLM: Multimodal Video Understanding for Gameplay Analysis},
year = {2025},
publisher = {GitHub},
url = {https://github.com/chasemetoyer/gameplay-vision-llm},
note = {A research framework for long-horizon gameplay video QA with multimodal perception}
}
MIT License - See LICENSE for details.
Made with ❤️ for the gaming and AI research community
Python
98.6%
Shell
1.4%