This guide explains how to create fully installable executables for Windows and macOS with all dependencies bundled.
Before building, ensure you have:
- Node.js 18+ and npm installed
- Python 3.8+ with pip
- All dependencies installed:
npm install pip install -r requirements.txt
- External binaries in
resources/bin/:ffmpeg.exeffprobe.exemkvmerge.exemkvextract.exe
First, build the AVSync Python engine using PyInstaller:
# Activate your Python virtual environment
venv\Scripts\activate
# Build with PyInstaller
python -m PyInstaller avsync.spec -yThis creates the bundled Python application in the dist/avsync/ folder.
Copy the built PyInstaller bundle to the resources folder:
# Remove old bundle
Remove-Item -Path resources\avsync -Recurse -Force -ErrorAction SilentlyContinue
# Copy new bundle
Copy-Item -Path dist\avsync -Destination resources\avsync -Recurse -ForceBuild the Electron frontend and backend:
npm run buildThis command:
- Compiles TypeScript files
- Builds the React frontend with Vite
- Compiles the Electron main process
Create the installer using electron-builder:
npm run package:winThis creates:
- NSIS Installer (
.exe): Full installer with install wizard - Portable Version (
.exe): Standalone executable that doesn't require installation
Both will be in the release/ folder.
For convenience, here's a complete build script (PowerShell):
# 1. Activate Python environment
venv\Scripts\activate
# 2. Build Python engine
python -m PyInstaller avsync.spec -y
# 3. Copy to resources
Remove-Item -Path resources\avsync -Recurse -Force -ErrorAction SilentlyContinue
Copy-Item -Path dist\avsync -Destination resources\avsync -Recurse -Force
# 4. Build and package Electron app
npm run build
npm run package:winThe final installer includes:
- React frontend (built with Vite)
- Electron runtime
- Node.js runtime
resources/avsync/- Complete PyInstaller bundleavsync.exe- Main processing executable_internal/- Python runtime and all dependencies- OpenCV, NumPy, SciPy, PIL, imagehash, etc.
resources/bin/- External toolsffmpeg.exe- Media processingffprobe.exe- Media analysismkvmerge.exe- MKV muxingmkvextract.exe- MKV extraction
After building, you'll find in the release/ folder:
release/
├── AVSync Desktop Setup 1.0.0.exe # NSIS installer (recommended for distribution)
└── AVSync Desktop 1.0.0.exe # Portable version (no installation required)
- Full installer with install wizard
- Allows user to choose installation directory
- Creates Start Menu shortcuts
- Includes uninstaller
- File size: ~300-400 MB
- Single executable
- No installation required
- Can run from any location (USB drive, etc.)
- File size: ~300-400 MB
Before distribution, test both versions:
- Run
AVSync Desktop Setup 1.0.0.exe - Follow installation wizard
- Launch from Start Menu
- Test with sample videos
- Copy
AVSync Desktop 1.0.0.exeto a different location - Run directly
- Test with sample videos
- macOS computer (required for proper .app and .dmg creation)
- Xcode Command Line Tools:
xcode-select --install - Homebrew: https://brew.sh
- Node.js 18+:
brew install node - Python 3.8+:
brew install python@3.11
git clone https://github.com/stinkybread/avsync.git
cd avsync
# Install dependencies
npm install
# Setup Python environment
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtmkdir -p resources/binFFmpeg & FFprobe:
- Download from https://ffbinaries.com/downloads
- Select macOS (darwin) platform
- Extract
ffmpegandffprobetoresources/bin/ - Make executable:
chmod +x resources/bin/ffmpeg resources/bin/ffprobe
MKVToolNix:
- Download from https://mkvtoolnix.download/
- Extract
mkvmergeandmkvextracttoresources/bin/ - Make executable:
chmod +x resources/bin/mkvmerge resources/bin/mkvextract
source venv/bin/activate
python -m PyInstaller avsync.spec -y
# Copy to resources
rm -rf resources/avsync
cp -R dist/avsync resources/avsyncnpm run build
npm run package:macrelease/
├── AVSync Desktop-1.0.0.dmg # DMG installer (recommended)
└── AVSync Desktop-1.0.0-mac.zip # ZIP archive
DMG Installer:
- Drag-and-drop installer
- Professional appearance
- Most common distribution format for macOS
- File size: ~300-400 MB
ZIP Archive:
- Portable .app bundle
- No installation required
- Alternative distribution method
The easiest way to build for multiple platforms is to use GitHub Actions. I've created .github/workflows/build.yml which will:
- Build Windows installer automatically
- Build macOS DMG automatically
- Create releases when you push a version tag
-
Push code to GitHub:
git push origin main
-
Create a release tag:
git tag v1.0.0 git push origin v1.0.0
-
GitHub Actions will:
- Build on both Windows and macOS runners
- Create installers for both platforms
- Attach them to the GitHub release
-
Download installers:
- Go to your repository's "Releases" page
- Download the installers for your platform
Note: You'll need to update the workflow file to include binary downloads. The binaries are too large to commit to git, so you'll need to either:
- Download them during the build process (recommended)
- Host them elsewhere and download via curl/wget
- Use a separate repository for binaries
- Ensure all binaries are in
resources/bin/before building - Rebuild PyInstaller bundle:
python -m PyInstaller avsync.spec -y - Copy fresh bundle to resources
- Check that
resources/bin/contains all 4 binaries - Ensure binaries were included in build (check file size - should be 300+ MB)
- Rebuild with
npm run package:win
- This is normal! The bundle includes:
- Electron runtime (~100 MB)
- Python runtime with OpenCV (~100 MB)
- FFmpeg full build with SoxR (~130 MB)
- MKVToolNix binaries (~40 MB)
- Run
npm installagain - Ensure
node_modules/is present - Check that
dist-electron/was created bynpm run build
Distribute the NSIS Installer (AVSync Desktop Setup 1.0.0.exe) for:
- Easy installation
- Automatic shortcuts
- Professional appearance
- Built-in uninstaller
Distribute the Portable Version (AVSync Desktop 1.0.0.exe) for:
- No installation required
- Run from USB/external drives
- No admin rights needed
- Quick testing
To change the version number:
-
Update
package.json:{ "version": "1.0.1" } -
Rebuild and package:
npm run package:win
The installer filename will automatically update to reflect the new version.
For production distribution, consider code signing:
-
Obtain a code signing certificate
-
Update
package.json:{ "build": { "win": { "certificateFile": "path/to/cert.pfx", "certificatePassword": "password" } } } -
Rebuild:
npm run package:win
Code signing prevents Windows SmartScreen warnings.
For automated builds, use GitHub Actions or similar:
# .github/workflows/build.yml
name: Build
on: [push]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/setup-python@v2
- run: npm install
- run: pip install -r requirements.txt
- run: python -m PyInstaller avsync.spec -y
- run: Copy-Item -Path dist\avsync -Destination resources\avsync -Recurse
- run: npm run package:win
- uses: actions/upload-artifact@v2
with:
name: installers
path: release/*.exeQuick Build Command:
# Complete build in one go
venv\Scripts\activate && python -m PyInstaller avsync.spec -y && Remove-Item -Path resources\avsync -Recurse -Force -ErrorAction SilentlyContinue && Copy-Item -Path dist\avsync -Destination resources\avsync -Recurse -Force && npm run build && npm run package:winOutput: Ready-to-distribute installer in release/ folder!