A multimodal research pipeline for analyzing political narratives in brick-built videos.
Project description
legopolitics
A multimodal Python research package for analyzing political narratives in brick-built videos.
legopolitics converts videos made with brick-built figures, miniature environments, and stop-motion scenes into structured, reproducible research data. It combines video sampling, object detection, tracking, image-language models, OCR, audio analysis, narrative coding, political measurement, model agreement, and human validation in one extensible pipeline.
Trademark notice: LEGO® is a trademark of the LEGO Group of companies, which does not sponsor, authorize, or endorse this project. legopolitics is an independent academic research software project and is not affiliated with, maintained by, sponsored by, authorized by, or associated with the LEGO Group.
Why use legopolitics?
Political brick-built videos can communicate through visual composition, recurring characters, symbols, dialogue, narration, music, violence, camera framing, and sequential storytelling. A single caption per frame cannot preserve all of those signals. legopolitics therefore separates the pipeline into linked units of analysis:
- Videos and scenes — metadata, scene boundaries, sampling decisions, and narrative segments.
- Frames — visual descriptions, composition, salience, OCR, transcript alignment, and research coding.
- Figures and objects — detections, crops, masks, attributes, tracks, group assignments, and roles.
- Interactions — figure–figure and figure–object relationships over time.
- Audio — transcription, translation, diarization, music, silence, and sound events.
- Interpretation — blind observation, context-conditioned analysis, codebook scoring, contradiction checks, and model agreement.
Capabilities
| Area | Included capabilities |
|---|---|
| Video processing | Recursive discovery, FFmpeg/OpenCV probing, fixed/scene/hybrid/adaptive/all-frame sampling, perceptual deduplication, motion and quality metrics |
| Detection | Custom YOLO-compatible weights, open-vocabulary detection, detection fusion, annotations, crops, and configurable taxonomies |
| Temporal analysis | Figure/object tracking, track reactivation, appearance-assisted re-identification, contact sheets, temporal events, and narrative segments |
| Segmentation | Detector masks, box-mask fallback, and optional SAM-style segmentation/propagation adapters |
| Visual models | Florence-2, BLIP, BLIP-2, CLIP, DINOv2, generic Hugging Face VLMs, video VLMs, and remote-provider adapters |
| Text and audio | OCR, subtitle deduplication, Whisper/Faster-Whisper, translation, speaker diarization, and audio-event adapters |
| Political analysis | Roles, agency, threat, heroism, victimization, retaliation, legitimacy, affect, dehumanization, and researcher-defined codebooks |
| Reliability | Majority/max/weighted voting, model disagreement, uncertainty, validation sampling, manual corrections, and agreement metrics |
| Outputs | Excel, Parquet, JSONL, SQLite, HTML reports, frames, crops, masks, prompts, logs, configuration, and provenance |
Heavy machine-learning dependencies are optional and loaded lazily. The base package can run video discovery, probing, sampling, quality analysis, deterministic measurements, manifests, and exports without downloading large models.
Installation
After the first PyPI release:
python -m pip install legopolitics
Install only the optional capabilities required for your project:
python -m pip install "legopolitics[yolo,huggingface,parquet]"
python -m pip install "legopolitics[audio,diarization,ocr]"
python -m pip install "legopolitics[all]"
For development from GitHub:
git clone https://github.com/cantayus/legopolitics.git
cd legopolitics
python -m pip install -e ".[dev]"
FFmpeg is recommended for reliable metadata probing and audio extraction.
Ultralytics is intentionally optional. Review its current licensing terms before enabling the YOLO adapter.
Quick start
1. Check the environment
legopolitics doctor
2. Create a configuration
legopolitics config-template --output analysis.yaml
A safe, lightweight example is also available at configs/minimal.yaml. A full research configuration is available at configs/comprehensive.yaml.
3. Analyze a video
legopolitics analyze-video \
--video "videos/example.mp4" \
--config "configs/minimal.yaml" \
--output "outputs/example"
4. Use the Python API
from pathlib import Path
from legopolitics import AnalysisConfig, LegoPoliticsAnalyzer
config = AnalysisConfig.from_yaml(Path("configs/minimal.yaml"))
analyzer = LegoPoliticsAnalyzer(config)
result = analyzer.analyze_video(
video_path=Path("videos/example.mp4"),
output_dir=Path("outputs/example"),
)
print(f"Sampled frames: {len(result.frames)}")
print(f"Detections: {len(result.detections)}")
print(f"Tracks: {len(result.tracks)}")
print(result.output_paths)
Custom YOLO model
The currently supplied ZIP contains zero-byte placeholders rather than the real checkpoint. Re-create the archive and confirm that weights/best.pt has a nonzero size. Then register the real model:
legopolitics register-yolo-model \
--weights /path/to/yolo26s_results/weights/best.pt \
--destination models/lego_figure_best.pt
The command validates the checkpoint, prints its task and class map, fingerprints it, copies it atomically, and writes a JSON metadata sidecar. You can inspect without copying:
legopolitics inspect-yolo-model --weights /path/to/best.pt
A checkpoint that reports classify cannot extract figures from complete frames; use the trained detect checkpoint instead. Start from configs/lego_figure_detector.yaml:
detection:
enabled: true
primary_backend: "yolo"
yolo:
weights: "models/lego_figure_best.pt"
task: "detect"
confidence_threshold: 0.30
iou_threshold: 0.50
image_size: 1280
legal:
ultralytics_license_acknowledged: true
Then run:
legopolitics analyze-video \
--video "videos/example.mp4" \
--config "configs/lego_figure_detector.yaml" \
--output "outputs/example"
See the custom YOLO integration guide for validation and threshold-tuning guidance.
Hugging Face VLM ensemble
The package can run several Hugging Face visual-language models sequentially and retain every output separately. The included ensemble configuration integrates:
HuggingFaceTB/SmolVLM2-2.2B-InstructQwen/Qwen2.5-VL-3B-InstructHuggingFaceM4/Idefics3-8B-Llama3llava-hf/llava-onevision-qwen2-7b-ov-hf
Use configs/huggingface_vlm_ensemble.yaml, or combine it with the detector settings in configs/lego_figure_detector.yaml. SmolVLM2 and Qwen2.5-VL are enabled in that workstation-oriented example; the larger models are integrated but disabled by default.
The package supports CPU, small-GPU, midrange, high-end, and maximum-quality profiles. Ask the CLI for a recommendation:
legopolitics recommend-vlm-profile
legopolitics config-template --profile hf-midrange-gpu --output analysis.yaml
Available templates include hf-cpu, hf-small-gpu, hf-midrange-gpu, hf-high-end-gpu, and hf-maximum. They use smaller checkpoints, FP16/BF16, 4-bit loading, Accelerate device maps, and sequential unloading as appropriate. See the Hugging Face VLM ensemble guide.
Research context and interpretation
The package keeps visual observation separate from political interpretation. Add carefully sourced context and a research question to the configuration:
research:
event_context: >
Add the factual historical context needed to interpret the video.
research_question: >
How are the depicted sides presented in terms of agency,
aggression, victimization, heroism, competence, and legitimacy?
codebook_path: "configs/propaganda_codebook.yaml"
prompting:
blind_visual_pass: true
contextual_pass: true
codebook_pass: true
contradiction_pass: true
The blind pass receives no event context. The contextual pass receives the supplied background but must distinguish direct evidence from inference. The contradiction pass looks for evidence that weakens the proposed interpretation.
Outputs
A typical output directory contains:
outputs/example/
├── video_summary.xlsx
├── report.html
├── result.json
├── run_manifest.sqlite
├── effective_config.yaml
├── environment.json
├── provenance.json
├── tables/
├── jsonl/
├── frames/
├── annotated_frames/
├── crops/
├── masks/
├── validation/
└── logs/
The Excel workbook provides linked sheets for frames, detections, tracks, relationships, OCR, transcripts, audio events, narrative segments, codebook scores, model agreement, validation, metadata, prompts, models, and errors. Parquet and SQLite are the preferred machine-readable formats for larger studies.
Batch processing
legopolitics analyze-directory \
--input-root "videos" \
--output-root "outputs" \
--recursive \
--num-batches 4 \
--batch-id 0 \
--resume
Run the same command in four terminals or notebooks with batch IDs 0, 1, 2, and 3. Video assignment is deterministic, and the manifest prevents completed stages from being unnecessarily recomputed.
Documentation and tutorial
- Documentation site
- Complete tutorial
- Python API
- CLI reference
- Configuration reference
- Publication guide
- Methodology and safeguards
Development
python -m pip install -e ".[dev]"
ruff format --check src tests
ruff check src tests
mypy src/legopolitics
python -m pytest
mkdocs build --strict
python -m build
python -m twine check --strict dist/*
Project status
legopolitics is currently an alpha research package. Optional adapters for large models require compatible hardware, model weights, and—in some cases—gated repository access or provider credentials. Model outputs should be validated against human coding before they are treated as substantive research measurements.
Citation
Citation metadata is provided in CITATION.cff. Please cite the exact package version, model revisions, custom weights, prompts, and configuration used in an analysis.
License and public release
The original legopolitics source code and project-authored documentation are distributed under the MIT License. The MIT License permits use, modification, publication, distribution, sublicensing, and sale while requiring preservation of the copyright and license notices.
Third-party packages, external model repositories, datasets, and model weights remain subject to their own licenses. In particular, the optional Ultralytics adapter and the separately distributed YOLO checkpoint require an independent license review; the package MIT License does not override those terms. See NOTICE, THIRD_PARTY_LICENSES.md, MODEL_LICENSES.md, and TRADEMARK_REVIEW.md.
Included research detector
The source-repository bundle includes the supplied YOLO26s spatial detector under model_assets/lego_figure_yolo26s/. It detects human and lego_figure; the ready configuration configs/lego_figure_yolo26s.yaml selects only lego_figure for extraction, tracking, and VLM analysis. The checkpoint is intentionally excluded from the PyPI wheel and should be managed with Git LFS when the repository is published.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file legopolitics-0.1.1.tar.gz.
File metadata
- Download URL: legopolitics-0.1.1.tar.gz
- Upload date:
- Size: 967.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18411f750aeb7fa42f8ddd65cc1034eb58378a05040734346d0aef8fd77e5f46
|
|
| MD5 |
2ae04b31ae996b21aef689bb94867dac
|
|
| BLAKE2b-256 |
01c9c818d148993d32b3c35305fde5675162399f83ba0399758e5267e5697c17
|
File details
Details for the file legopolitics-0.1.1-py3-none-any.whl.
File metadata
- Download URL: legopolitics-0.1.1-py3-none-any.whl
- Upload date:
- Size: 143.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
186f9fcb28b1ecb29f1140d50d85b6b8138051c789e82c9a8d1a8123fd0f1c32
|
|
| MD5 |
f853d6c09b624b313ba5b38001a7fa8b
|
|
| BLAKE2b-256 |
4a0f6b1c135702dc6d13131b85dca4cc9472fd3deb031cb802bb13e4108d3832
|