# VLChan A Python video player using VLC SDK with synchan server timecode synchronization. ## Features - VLC-based video playback with full media support - Real-time synchronization with synchan server - Reactive programming with RxPY - **Advanced synchronization with latency compensation** - **Playback rate adjustment for smooth sync** - Automatic timecode correction with smart seeking - Playback state synchronization - Volume, playback rate, and fullscreen controls ## Installation 1. Install VLC media player on your system: - Ubuntu/Debian: `sudo apt install vlc` - macOS: `brew install vlc` - Windows: Download from [videolan.org](https://www.videolan.org/vlc/) 2. Install the Python package: ```bash cd vlchan poetry install ``` ## Usage ### Basic Usage ```python from vlchan import VLChanPlayer # Create player with video file player = VLChanPlayer( synchan_url="http://localhost:3000", video_path="/path/to/video.mp4" ) # Start synchronization player.start_sync() # Play video player.play() # Clean up when done player.cleanup() ``` ### Advanced Usage ```python from vlchan import VLChanPlayer def on_state_change(state): print(f"Synchan state: playing={state.playing}, time={state.currentTime:.2f}s") # Create player player = VLChanPlayer("http://localhost:3000", "video.mp4") # Set up state change callback player.on_state_change = on_state_change # Start synchronization player.start_sync() # Control playback player.play() player.pause() player.seek(120.5) # Seek to 2 minutes 0.5 seconds # Adjust settings player.set_volume(80) player.set_fullscreen(True) # Get current state print(f"Position: {player.get_position():.2f}s") print(f"Duration: {player.get_duration():.2f}s") print(f"Playing: {player.is_playing()}") ``` ### Command Line Usage ```bash # Play video with synchan sync poetry run python -m vlchan.player video.mp4 # Use custom synchan server poetry run python -m vlchan.player video.mp4 http://192.168.1.100:3000 ``` ## API Reference ### VLChanPlayer #### Constructor - `VLChanPlayer(synchan_url: str, video_path: Optional[str])` - `synchan_url`: URL of the synchan server (default: "http://localhost:3000") - `video_path`: Path to video file to load #### Methods - `load_video(video_path: str)`: Load a video file - `start_sync()`: Start synchronization with synchan server - `stop_sync()`: Stop synchronization - `play()`: Start playback - `pause()`: Pause playback - `stop()`: Stop playback - `seek(time_seconds: float)`: Seek to specific time - `set_volume(volume: int)`: Set volume (0-100) - `get_volume() -> int`: Get current volume - `set_fullscreen(fullscreen: bool)`: Toggle fullscreen - `get_position() -> float`: Get current position in seconds - `get_compensated_position(latency: float) -> float`: Get latency-compensated position - `get_duration() -> float`: Get video duration in seconds - `is_playing() -> bool`: Check if playing - `get_rate() -> float`: Get current playback rate - `set_rate(rate: float)`: Set playback rate (1.0 = normal speed) - `cleanup()`: Clean up resources #### Properties - `on_state_change`: Callback for synchan state changes ### SynchanState Data class containing synchronization state: - `playing: bool`: Whether video should be playing - `currentTime: float`: Current time position in seconds - `duration: float`: Total duration in seconds - `loop: bool`: Whether video should loop - `latency: float`: Network latency in seconds ## Synchronization The player uses advanced synchronization logic similar to the synchan VideoPlayer component: 1. **Latency Compensation**: Server time is adjusted by network latency 2. **Smart Seeking**: Large time differences (>1s) trigger immediate seeking 3. **Playback Rate Adjustment**: Small differences are corrected by adjusting playback speed 4. **Rate Formula**: `rate = 1 + min(max(diff * 0.5, -0.05), 0.05)` 5. **Playback State**: Play/pause commands are synchronized 6. **Reconnection**: Automatically attempts to reconnect on connection loss ### Synchronization Algorithm ```python # Apply latency compensation compensated_time = server_time + latency / 1000 # Calculate difference diff = compensated_time - local_time # Large difference: seek immediately if diff > 1.0: player.seek(compensated_time) # Small difference: adjust playback rate rate = 1 + min(max(diff * 0.5, -0.05), 0.05) player.set_rate(rate) ``` ## Requirements - Python 3.11+ - VLC media player - Synchan server running ## Dependencies - `python-vlc`: VLC Python bindings - `reactivex`: Reactive programming - `python-socketio`: WebSocket client for synchan - `requests`: HTTP client for synchan API ## Development ```bash # Install development dependencies poetry install --with dev # Run linting poetry run ruff check . # Run type checking poetry run mypy vlchan/ ```