AKER project - Multi-screen video synchronization system using MPV.
This system provides frame-perfect synchronization across multiple screens with stable UUID-based monitor detection to ensure videos always play on the correct physical screen, even after system reboots.
β¨ UUID-Based Monitor Mapping - Uses hardware identifiers (UUID, serial numbers) to reliably identify each physical screen π― Automatic Re-sync on Loop - Detects video loops and re-synchronizes all instances β‘ IPC-Based Control - Fast communication with MPV instances via Unix sockets π Persistent Configuration - Monitors are identified by hardware, not position
# Install MPV
brew install mpv # macOS
# Install Python dependencies
pip3 install pyobjc-framework-Quartz # Required for UUID-based monitor detectionCreate a config.json file from the example:
cp config.json.example config.jsonEdit config.json to specify your video file paths:
{
"video_files": {
"CENTER": "/path/to/your/center_video.mov",
"LEFT": "/path/to/your/left_video.mov",
"RIGHT": "/path/to/your/right_video.mov"
},
"num_screens": 3
}Note: config.json is gitignored so you can customize paths without affecting the repository.
Run the setup verification script to check all requirements:
./check_setup.pyThis will verify:
- β
config.jsonexists and is valid - β Video files exist at configured paths
- β
monitors_mapping.jsonexists (after calibration) - β MPV is installed
- β Quartz framework is available
You MUST run the calibration tool once to create a stable monitor mapping:
./calibrate_monitors.pyThis will:
- Detect all connected monitors and show their hardware details (UUID, serial number, vendor/model IDs)
- Display connection information (Thunderbolt, HDMI, DisplayPort, etc.)
- Launch test windows on each screen showing "MPV Screen 0", "MPV Screen 1", etc.
- Ask you to identify which MPV screen number corresponds to each physical location (CENTER, LEFT, RIGHT)
- Save the mapping to
monitors_mapping.json
macOS may change screen numbering after reboots or when monitors are disconnected/reconnected. The UUID-based system ensures videos always play on the correct physical screen by identifying monitors by their hardware, not their position in macOS.
π₯οΈ Detected 3 active display(s)
Monitor 0:
UUID: A1B2C3D4-E5F6-7890-ABCD-EF1234567890
Serial: 12345678
Vendor ID: 0x10AC
Model ID: 0x4567
Connection: DisplayPort
Monitor 1:
UUID: B2C3D4E5-F6A7-8901-BCDE-F12345678901
...
π MONITOR IDENTIFICATION
Which MPV screen number shows the CENTER position? (0-2): 0
β CENTER position β MPV Screen 0
Which MPV screen number shows the LEFT position? (0-2): 2
β LEFT position β MPV Screen 2
Which MPV screen number shows the RIGHT position? (0-2): 1
β RIGHT position β MPV Screen 1
β
Monitor mapping saved to: monitors_mapping.json
./monitors_calibrate.py first to create monitors_mapping.json. The system will refuse to start without this file.
After calibration, simply run:
./multiplayer.pyThe system will:
- β
Load the UUID-based monitor mapping from
monitors_mapping.json - β Detect current screen configuration using hardware UUIDs
- β Automatically assign videos to the correct physical screens
- β Exit with an error if
monitors_mapping.jsonis missing or invalid - β Synchronize playback and monitor for loops
You need to run ./calibrate_monitors.py again if:
- β You connect different monitors (different hardware)
- β Videos appear on the wrong screens after reboot
- β You see "Monitor configuration has changed!" error
You do NOT need to re-calibrate if:
- β You simply reboot the system (UUID mapping handles this)
- β macOS changes the screen numbering (UUID mapping handles this)
- β Monitors are temporarily disconnected then reconnected
The system uses macOS CoreGraphics APIs to get stable hardware identifiers for each display:
-
During Calibration (calibrate_monitors.py):
- Detects UUID, serial number, vendor/model IDs for each connected display
- Creates a mapping:
{UUID β Video File Path + Physical Position} - Saves to
monitors_mapping.json
-
During Playback (multiplayer.py):
- Detects current display UUIDs
- Matches UUIDs against calibration file
- Assigns correct video to each MPV screen index
- Even if screen numbers change, UUIDs remain stable
- Monitors playback position every second
- Detects loops when
current_position < previous_position - Three-phase sync: pause β seek to 0 β resume
- Maintains frame-perfect synchronization across all screens
Edit multiplayer.py:30:
NUM_SCREENS = 3 # Change this value between 1 and 8Audio is enabled on the central screen by default (multiplayer.py:195-197).
pip3 install pyobjc-framework-Quartz# Re-run calibration
./calibrate_monitors.pyThis means the connected monitors are different from when you calibrated. Run:
./calibrate_monitors.pyCheck that:
- Video files exist at the specified paths
- MPV is installed:
which mpv - Permissions allow creating sockets in
/tmp/mpv_sockets/
- multiplayer.py - Main synchronization system
- calibrate_monitors.py - Monitor calibration tool
monitors_mapping.json- Generated mapping file (UUID β Video)- CLAUDE.md - Technical documentation for Claude Code
See CLAUDE.md for detailed technical documentation including:
- IPC socket management
- MPV process control
- Synchronization algorithm
- Loop detection logic
- UUID-based mapping implementation