Skip to main content
The Multi-Camera Video Synchronization tool provides an intuitive web interface for aligning multiple video tracks. This guide walks you through each step of the workflow.

Accessing the UI

Start the application and access the web interface:
1

Start the Application

Run the main script from your terminal:
python main.py
The application will automatically open in your default browser at http://127.0.0.1:5050.
2

Verify Prerequisites

Ensure FFmpeg is installed and accessible in your system PATH:
brew install ffmpeg

Workflow Overview

The UI follows a 3-step wizard pattern:
All uploaded files are temporarily stored in your system’s temp directory under video_synchronization/raw/. Synchronized outputs are saved to video_synchronization/synced/.

Step 1: Upload Videos

The first step involves selecting and uploading your video files.

Supported Formats

MP4

.mp4 files (recommended)

MOV

.mov Apple QuickTime

AVI

.avi legacy format

Upload Process

  1. Click “Select Video Files” button
  2. Choose 2 or more videos from your file system
  3. Wait for upload completion (progress shown in the file grid)
  4. Click “Continue to Preview” when all files are uploaded
You must select at least 2 videos to proceed. The tool supports any number of videos, but synchronization accuracy improves with more temporal overlap between recordings.

Implementation Details

The upload endpoint (/api/upload) validates file types and stores them securely:
ALLOWED_EXTENSIONS = {'.mp4', '.mov', '.avi'}
Files are processed using werkzeug.utils.secure_filename() to prevent path traversal attacks (ui.py:768-769).

Step 2: Preview Original Videos

Before synchronization, verify that all videos loaded correctly.

Preview Features

Videos are displayed in a responsive grid (2 columns on desktop). Each video cell shows:
  • Video player with standard controls (play, pause, seek, volume)
  • Filename label below the player
Implementation: video-grid CSS class with grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) (ui.py:115-117)
All videos start playing automatically in muted mode to help you quickly verify content without audio interference.HTML attributes: autoplay muted playsinline (ui.py:259)
This step does not apply any synchronization. It simply loads the raw uploaded files for verification.

Starting Synchronization

When you click “Start Synchronization”:
  1. The button is disabled and shows “Synchronizing…”
  2. A background thread initiates the sync process (ui.py:735-736)
  3. You’re automatically redirected to Step 3 when processing begins

Step 3: Review Synchronized Results

This is the most feature-rich step, providing real-time progress monitoring and synchronized playback controls.

Real-Time Progress Monitoring

While synchronization is processing, you’ll see:
1

Progress Bar

Visual progress indicator showing completion percentage (0-100%)Implementation: Polls /api/progress every 1 second (ui.py:580)
2

Status Messages

Current operation displayed above the progress bar:
  • “Initializing visual synchronization…”
  • “Extracting motion energy from videos…”
  • “Applying offsets to videos…”
  • “Complete!”
Source: ui.py:692-727
3

Live Log Viewer

Real-time log stream with filtering capabilities (see below)

Log Viewer Features

The integrated log viewer provides transparency into the synchronization process:
Filter logs by severity:
  • All: Show all messages (default)
  • Info: General progress updates
  • Warnings: Non-fatal issues
  • Errors: Critical failures
Click the filter buttons to toggle levels (ui.py:330-336)

Synchronized Playback Controls

Once processing completes (progress = 100%), the results section reveals:

Video Grid

Synchronized videos displayed in the same multi-view grid layout. All videos have been trimmed/padded to start at the same temporal moment.

Playback Controls

Play/Pause

Toggle playback for all videos simultaneouslyImplementation: ui.py:481-510

Mute/Unmute

Toggle audio for all videos at onceButton shows current state: ”🔊 Unmute All” or ”🔇 Mute All” (ui.py:512-528)

Restart

Reset all videos to the beginning and start playing (ui.py:493-501)

Universal Seek Bar

The most powerful feature for verifying synchronization:
Purpose: Scrub through all videos simultaneously to verify temporal alignment.Behavior:
  • Displays current playback time and total duration (format: MM:SS)
  • Drag the slider to seek all videos to the same timestamp
  • Updates in real-time during playback (every 100ms)
  • Prevents automatic updates while dragging to avoid jitter
Implementation:
  • Sets currentTime property on all <video> elements synchronously (ui.py:555-566)
  • Uses isDragging flag to prevent conflicting updates (ui.py:533)
  • Max value set to video duration after metadata loads (ui.py:542-544)
Use the seek bar to jump to action-heavy moments in your videos (e.g., a clap, door slam, or sudden movement). If synchronization was successful, these events should occur at the exact same frame across all videos.

Exporting Results

Download All (ZIP)

Bundles all synchronized videos into a single ZIP archive.Endpoint: /api/download_all (ui.py:816-836)Filename pattern: {original_name}_synced.{ext}

Start Over

Clears the current session and returns to Step 1.Note: Previous uploads are not deleted from temp storage until you exit the application.

Advanced Features

Session Logging

All operations are logged to a rotating file for debugging:
  • Location: logs/video_sync.log in the project directory
  • Rotation: 10MB per file, 5 backups retained (ui.py:39-40)
  • Format: TIMESTAMP - LOGGER_NAME - LEVEL - MESSAGE
Each session is assigned a unique ID (e.g., req_a4b2c9d1) visible in log messages for tracing operations (ui.py:597).

Temporary File Management

Files are stored in system temp directories:
/tmp/video_synchronization/  # Linux/macOS
└── raw/                     # Uploaded originals
└── synced/                  # Synchronized outputs
└── audio/                   # Extracted audio (if using audio sync)
└── visual_sync_debug/       # Motion analysis debug data
These directories are automatically created on startup (config.py:26-30).

Sync Indicator Images

After synchronization, visual “bounding box” images are generated in results/ (persists across sessions) to visualize the sync quality:
indicator_files = generate_sync_indicators(
    video_dir, files, offsets, config.RESULTS_DIR
)
Source: ui.py:709-718
If indicator generation fails, it’s logged as a warning but does not stop the synchronization process (non-fatal error).

Troubleshooting

Cause: You selected a file with an unsupported extension.Solution: Convert your video to .mp4, .mov, or .avi using FFmpeg:
ffmpeg -i input.mkv -c copy output.mp4
Cause: Synchronization thread crashed (check logs/video_sync.log).Common reasons:
  • FFmpeg not in PATH
  • Corrupted video file
  • Insufficient disk space in temp directory
Solution: Check the log viewer for ERROR messages or inspect the log file.
Cause: Synchronization completed, but accuracy is poor.Diagnosis: Check the confidence scores in the logs. Low confidence (< 0.5) indicates unreliable alignment.Solutions:
  • Try switching SYNC_METHOD in src/config.py (visual ↔ audio)
  • Ensure videos have overlapping temporal content
  • Verify videos have detectable motion or audio
Cause: No log messages have been emitted yet, or logs were cleared.Solution: Wait for synchronization to start. First logs appear when you click “Start Synchronization” in Step 2.

Keyboard Shortcuts

The UI does not currently implement keyboard shortcuts. All interactions require mouse/touch input.
Future versions may add:
  • Space: Play/Pause
  • M: Mute/Unmute
  • R: Restart
  • ←/→: Frame-by-frame seek

Next Steps

Configuration

Learn how to customize synchronization methods, directories, and advanced settings

Interpreting Results

Understand confidence scores, error metrics, and how to validate synchronization quality

Build docs developers (and LLMs) love