A PyTorch Lightning implementation of SyncNet for detecting audio-visual synchronization in videos. This project trains deep learning models to determine whether audio and video streams are temporally aligned.
SyncNet learns to measure the synchronization between audio and video by computing similarity scores between learned embeddings. The model uses a pretrained audio-visual encoder (PeAudioVideo) and is trained using contrastive learning with both synchronized (positive) and out-of-sync (negative) samples.
uvcurl -LsSf https://astral.sh/uv/install.sh | sh
git clone https://github.com/yourusername/pe-av-syncnet.git
cd pe-av-syncnet
uv sync
This will install all required dependencies including:
cp .env.example .env
Edit .env and add your credentials:
WANDB_PROJECT=your-project-name
WANDB_ENTITY=your-wandb-username
uv run pre-commit install
pe-av-syncnet/
├── src/syncnet/
│ ├── __init__.py # Package initialization
│ ├── config.py # Pydantic configuration with hyperparameters
│ ├── lightning_module.py # Lightning training module
│ ├── datamodule.py # Data loading and preprocessing
│ ├── datasets/
│ │ ├── __init__.py # Batch data structure
│ │ └── dataset.py # Video dataset loader
│ ├── modeling/
│ │ ├── __init__.py # Model package
│ │ └── model.py # SyncNet architecture
│ └── scripts/
│ ├── __init__.py # Scripts package
│ └── train.py # Training script
├── tests/
│ └── test_sample.py # Test suite
├── pyproject.toml # Project configuration and dependencies
├── .pre-commit-config.yaml # Code quality hooks
├── .env.example # Environment variables template
└── README.md # This file
SyncNet expects a directory containing MP4 video files with both audio and video streams.
data/
├── video1.mp4
├── video2.mp4
├── video3.mp4
├── subfolder/
│ ├── video4.mp4
│ └── video5.mp4
└── ...
Train a model on your video dataset:
uv run train /path/to/videos --num_devices 1 --num_workers 8
Train with multiple GPUs using DeepSpeed:
uv run train /path/to/videos --num_devices 4 --num_workers 16
uv run train /path/to/videos --checkpoint_path logs/pe-av-small-abc1234/last.ckpt
Initialize model with custom weights:
uv run train /path/to/videos --weights_path /path/to/weights.pth
Run training offline without uploading to Weights & Biases:
uv run train /path/to/videos --debug
Test your pipeline with a single batch:
uv run train /path/to/videos --fast_dev_run
| Argument | Type | Default | Description |
|---|---|---|---|
data_root | Path | Required | Directory containing video files |
--project | str | "template" | Project name for logging |
--num_devices | int | 1 | Number of GPUs to use |
--num_workers | int | 12 | Data loading workers |
--log_root | Path | "logs" | Directory for checkpoints and logs |
--checkpoint_path | Path | None | Path to checkpoint for resuming |
--weights_path | Path | None | Path to pretrained weights |
--debug | flag | False | Enable debug mode (offline logging) |
--fast_dev_run | flag | False | Run single batch for testing |
The SyncNet model consists of:
Pretrained Encoder: Meta's PeAudioVideoModel on HuggingFace
Embedding Processing:
Similarity Computation:
Input Video → Random Segment Sampling
↓
Audio + Video Preprocessing
↓
[50% chance] Temporal Shift (negative sample)
↓
PeAudioVideo Encoder
↓
Audio Embedding + Video Embedding
↓
Cosine Similarity
↓
Binary Cross-Entropy Loss
All hyperparameters are defined in src/syncnet/config.py:
class Config(BaseModel):
# Reproducibility
seed: int = 42
# Data
test_split: float = 0.05
batch_size: int = 4
# Training
max_epochs: int = 200
early_stopping_patience: int = 10
learning_rate: float = 1e-4
min_learning_rate: float = 1e-6
weight_decay: float = 1e-2
accumulate_grad_batches: int = 1
gradient_clip_val: float = 1.0
# Model
base_model: str = "facebook/pe-av-small"
num_frames: int = 5
negative_fraction: float = 0.5
frame_height: int = 224
frame_width: int = 224
config.learning_rateconfig.min_learning_rateuv run pytest
uv run mypy src/
# Check code style
uv run ruff check src/
# Auto-format code
uv run ruff format src/
Automatically run linters and formatters before each commit:
uv run pre-commit run --all-files
After training, use the model for inference:
import torch
from syncnet.modeling.model import SyncNet, SyncNetConfig
from transformers.models.pe_audio_video import PeAudioVideoProcessor
# Load model
config = SyncNetConfig(base_model="facebook/pe-av-small")
model = SyncNet.from_pretrained("your-username/your-model-name")
model.eval()
# Load processor
processor = PeAudioVideoProcessor.from_pretrained("facebook/pe-av-small")
# Process inputs
inputs = processor(
videos=video_frames, # Shape: (num_frames, H, W, C)
audio=audio_samples, # Shape: (num_samples,)
return_tensors="pt",
sampling_rate=48000
)
# Inference
with torch.no_grad():
similarity = model(
inputs["input_values"],
inputs["pixel_values_videos"]
)
print(f"Synchronization score: {similarity.item():.4f}")
# Higher score = better synchronization
Out of Memory (OOM)
batch_size in config.pynum_workers to decrease memory overheadaccumulate_grad_batches=2Slow Data Loading
num_workers (recommended: 2-4x number of GPUs)persistent_workers=True (already enabled)Low Accuracy
negative_fraction (try 0.3-0.7)WANDB Authentication Error
WANDB_PROJECT and WANDB_ENTITY in .envwandb login to authenticate--debug flag to train offlineSee LICENSE file for details.
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)For questions or issues:
Note: This is a research/educational implementation. For production use, additional validation and optimization may be required.
5 commits
Python
100.0%
A PyTorch Lightning implementation of SyncNet for detecting audio-visual synchronization in videos. This project trains deep learning models to determine whether audio and video streams are temporally aligned.
SyncNet learns to measure the synchronization between audio and video by computing similarity scores between learned embeddings. The model uses a pretrained audio-visual encoder (PeAudioVideo) and is trained using contrastive learning with both synchronized (positive) and out-of-sync (negative) samples.
uvcurl -LsSf https://astral.sh/uv/install.sh | sh
git clone https://github.com/yourusername/pe-av-syncnet.git
cd pe-av-syncnet
uv sync
This will install all required dependencies including:
cp .env.example .env
Edit .env and add your credentials:
WANDB_PROJECT=your-project-name
WANDB_ENTITY=your-wandb-username
uv run pre-commit install
pe-av-syncnet/
├── src/syncnet/
│ ├── __init__.py # Package initialization
│ ├── config.py # Pydantic configuration with hyperparameters
│ ├── lightning_module.py # Lightning training module
│ ├── datamodule.py # Data loading and preprocessing
│ ├── datasets/
│ │ ├── __init__.py # Batch data structure
│ │ └── dataset.py # Video dataset loader
│ ├── modeling/
│ │ ├── __init__.py # Model package
│ │ └── model.py # SyncNet architecture
│ └── scripts/
│ ├── __init__.py # Scripts package
│ └── train.py # Training script
├── tests/
│ └── test_sample.py # Test suite
├── pyproject.toml # Project configuration and dependencies
├── .pre-commit-config.yaml # Code quality hooks
├── .env.example # Environment variables template
└── README.md # This file
SyncNet expects a directory containing MP4 video files with both audio and video streams.
data/
├── video1.mp4
├── video2.mp4
├── video3.mp4
├── subfolder/
│ ├── video4.mp4
│ └── video5.mp4
└── ...
Train a model on your video dataset:
uv run train /path/to/videos --num_devices 1 --num_workers 8
Train with multiple GPUs using DeepSpeed:
uv run train /path/to/videos --num_devices 4 --num_workers 16
uv run train /path/to/videos --checkpoint_path logs/pe-av-small-abc1234/last.ckpt
Initialize model with custom weights:
uv run train /path/to/videos --weights_path /path/to/weights.pth
Run training offline without uploading to Weights & Biases:
uv run train /path/to/videos --debug
Test your pipeline with a single batch:
uv run train /path/to/videos --fast_dev_run
| Argument | Type | Default | Description |
|---|---|---|---|
data_root | Path | Required | Directory containing video files |
--project | str | "template" | Project name for logging |
--num_devices | int | 1 | Number of GPUs to use |
--num_workers | int | 12 | Data loading workers |
--log_root | Path | "logs" | Directory for checkpoints and logs |
--checkpoint_path | Path | None | Path to checkpoint for resuming |
--weights_path | Path | None | Path to pretrained weights |
--debug | flag | False | Enable debug mode (offline logging) |
--fast_dev_run | flag | False | Run single batch for testing |
The SyncNet model consists of:
Pretrained Encoder: Meta's PeAudioVideoModel on HuggingFace
Embedding Processing:
Similarity Computation:
Input Video → Random Segment Sampling
↓
Audio + Video Preprocessing
↓
[50% chance] Temporal Shift (negative sample)
↓
PeAudioVideo Encoder
↓
Audio Embedding + Video Embedding
↓
Cosine Similarity
↓
Binary Cross-Entropy Loss
All hyperparameters are defined in src/syncnet/config.py:
class Config(BaseModel):
# Reproducibility
seed: int = 42
# Data
test_split: float = 0.05
batch_size: int = 4
# Training
max_epochs: int = 200
early_stopping_patience: int = 10
learning_rate: float = 1e-4
min_learning_rate: float = 1e-6
weight_decay: float = 1e-2
accumulate_grad_batches: int = 1
gradient_clip_val: float = 1.0
# Model
base_model: str = "facebook/pe-av-small"
num_frames: int = 5
negative_fraction: float = 0.5
frame_height: int = 224
frame_width: int = 224
config.learning_rateconfig.min_learning_rateuv run pytest
uv run mypy src/
# Check code style
uv run ruff check src/
# Auto-format code
uv run ruff format src/
Automatically run linters and formatters before each commit:
uv run pre-commit run --all-files
After training, use the model for inference:
import torch
from syncnet.modeling.model import SyncNet, SyncNetConfig
from transformers.models.pe_audio_video import PeAudioVideoProcessor
# Load model
config = SyncNetConfig(base_model="facebook/pe-av-small")
model = SyncNet.from_pretrained("your-username/your-model-name")
model.eval()
# Load processor
processor = PeAudioVideoProcessor.from_pretrained("facebook/pe-av-small")
# Process inputs
inputs = processor(
videos=video_frames, # Shape: (num_frames, H, W, C)
audio=audio_samples, # Shape: (num_samples,)
return_tensors="pt",
sampling_rate=48000
)
# Inference
with torch.no_grad():
similarity = model(
inputs["input_values"],
inputs["pixel_values_videos"]
)
print(f"Synchronization score: {similarity.item():.4f}")
# Higher score = better synchronization
Out of Memory (OOM)
batch_size in config.pynum_workers to decrease memory overheadaccumulate_grad_batches=2Slow Data Loading
num_workers (recommended: 2-4x number of GPUs)persistent_workers=True (already enabled)Low Accuracy
negative_fraction (try 0.3-0.7)WANDB Authentication Error
WANDB_PROJECT and WANDB_ENTITY in .envwandb login to authenticate--debug flag to train offlineSee LICENSE file for details.
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)For questions or issues:
Note: This is a research/educational implementation. For production use, additional validation and optimization may be required.
5 commits
Python
100.0%