A desktop application for comparing two videos side by side with synchronized playback, trimming, and combined export.
- Side-by-Side Video Viewing: Load two videos and view them simultaneously
- Synchronized Playback: Both videos play perfectly in sync with shared controls
- Video Trimming: Automatically trim longer videos to match duration (front or back trim)
- Combined Export: Export both videos as a single side-by-side video using FFmpeg
- Play/Pause: Space bar or click the play button
- Seek: Click anywhere on the progress bar or use arrow keys (5 second jumps)
- Frame-by-Frame Navigation: Step through frames with
,and.keys - Mute/Unmute: Press
Mto toggle audio
- Drag & Drop: Drop video files directly onto the video slots
- Swap Videos: Press
Sto swap left and right videos - Video Info Overlay: Press
Ito show resolution and duration overlay - Audio Source Selection: Choose audio from Video 1, Video 2, or no audio in export
- Export Presets: Choose encoding speed (ultrafast to slow) and quality
- Real-time Export Progress: Live progress bar with percentage during export
- Cancel Export: Stop export at any time (partial file is deleted)
- Loading States: Visual feedback while videos load
- Error Handling: Clear error messages when video loading fails
| Key | Action |
|---|---|
Space |
Play/Pause |
← |
Seek back 5 seconds |
→ |
Seek forward 5 seconds |
, |
Previous frame |
. |
Next frame |
M |
Toggle mute |
S |
Swap videos |
I |
Toggle info overlay |
- Frontend: React 19 + TypeScript + Tailwind CSS v4
- Backend: Tauri 2.0 (Rust)
- State Management: Zustand
- Video Processing: FFmpeg (bundled as sidecar)
Download the latest release from the Releases page:
- Windows:
Video Compare_x.x.x_x64-setup.exe(NSIS installer) - Windows MSI:
Video Compare_x.x.x_x64_en-US.msi
-
Clone the repository
git clone https://github.com/vMyth/video-compare.git cd video-compare -
Install dependencies
npm install
-
Download FFmpeg
Download the FFmpeg binary for your platform and place it in
src-tauri/binaries/:- Windows: Name it
ffmpeg-x86_64-pc-windows-msvc.exe - macOS (Intel): Name it
ffmpeg-x86_64-apple-darwin - macOS (Apple Silicon): Name it
ffmpeg-aarch64-apple-darwin - Linux: Name it
ffmpeg-x86_64-unknown-linux-gnu
- Windows: Name it
-
Run in development mode
npm run tauri dev
-
Build for production
npm run tauri build
The installers will be generated in
src-tauri/target/release/bundle/
- File Picker: Click "Select Video 1" or "Select Video 2" buttons
- Drag & Drop: Drop video files directly onto the left or right video slot
- Videos are automatically synchronized
- Controls are disabled until both videos are loaded
- Use keyboard shortcuts or on-screen controls
When videos have different durations:
- Trim Mode: Choose "Trim Front" or "Trim Back" to align videos
- Enable/Disable: Toggle trimming on or off
- The longer video is automatically trimmed to match the shorter one
- Click "Export Side-by-Side" button
- Configure export settings:
- Preset: ultrafast (fast encoding) to slow (better compression)
- Quality: 0-51 CRF value (lower = better quality, larger file)
- Audio Source: None, Video 1, or Video 2
- Choose save location
- Monitor progress with real-time percentage
- Cancel anytime if needed
The application supports all video formats that FFmpeg can process:
- MP4, MKV, AVI, MOV, WebM
- H.264, H.265/HEVC, VP9, AV1
- And many more
The exported video uses:
- Resolution: 1280x720 (640x720 per video, scaled and padded)
- Codec: H.264 (libx264)
- Audio Codec: AAC (when audio source is selected)
video-compare/
├── src/ # React frontend
│ ├── app/
│ │ └── App.tsx # Main app component
│ ├── features/
│ │ ├── video-player/
│ │ │ ├── components/
│ │ │ │ ├── SyncedVideoPlayer.tsx # Main video display
│ │ │ │ └── VideoControls.tsx # Playback controls
│ │ │ └── hooks/
│ │ │ └── useVideoSync.ts # Sync logic
│ │ ├── file-picker/
│ │ │ └── components/
│ │ │ └── FilePicker.tsx # File selection
│ │ ├── trim/
│ │ │ └── components/
│ │ │ ├── TrimControls.tsx # Trim UI
│ │ │ ├── TrimSlider.tsx # Trim range slider
│ │ │ └── TrimNumberInput.tsx # Manual trim input
│ │ └── export/
│ │ ├── components/
│ │ │ └── ExportModal.tsx # Export dialog
│ │ └── hooks/
│ │ └── useExport.ts # Export logic
│ ├── stores/
│ │ └── videoStore.ts # Zustand state
│ ├── services/
│ │ └── tauri.ts # Tauri helpers
│ └── main.tsx # Entry point
├── src-tauri/ # Rust backend
│ ├── src/
│ │ └── lib.rs # FFmpeg commands
│ ├── binaries/ # FFmpeg sidecar
│ ├── capabilities/ # Tauri permissions
│ ├── icons/ # App icons
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri config
├── package.json
└── README.md
| Command | Description |
|---|---|
npm run dev |
Start Vite dev server |
npm run build |
Build frontend for production |
npm run tauri dev |
Run app in development mode |
npm run tauri build |
Build production installers |
npm run tauri icon <path> |
Generate app icons from image |
- State Management: Zustand store manages video paths, durations, trim settings, and playback state
- Video Sync: Custom hook using
requestAnimationFramekeeps both videos synchronized - FFmpeg Integration: Rust backend spawns FFmpeg as a sidecar process with progress streaming
- Drag & Drop: Uses Tauri's native file drop events with position-based hit detection
Make sure the asset protocol is enabled in tauri.conf.json:
"security": {
"assetProtocol": {
"enable": true,
"scope": ["**"]
}
}Ensure the FFmpeg binary is in src-tauri/binaries/ with the correct platform-specific name:
"bundle": {
"externalBin": ["binaries/ffmpeg"]
}- Check that both videos are loaded
- Ensure you have write permission to the output directory
- Try a different output location
Playback controls require both videos to be loaded. Load a second video to enable controls.
The application uses minimal permissions:
- shell:allow-spawn/kill: Required for FFmpeg process
- dialog:allow-open/save: Required for file pickers
- fs:read-all: Required to load videos from any location
CSP is configured to prevent script injection (no unsafe-eval in production).
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Tauri - Desktop app framework
- FFmpeg - Video processing
- React - UI framework
- Tailwind CSS - Styling
- Zustand - State management