Want to use Max Video Player? Download the latest release for your platform: macOS (.dmg) | Linux (.deb / .rpm / .AppImage)
No build required — just download, install, and run.
A cross-platform IPTV player built with Tauri v2, React, and libmpv. The Rust core (mvp-core) handles M3U/Xtream/EPG parsing and SQLite caching across all targets. A custom tauri-plugin-mpv embeds libmpv directly into the native window — using NSOpenGLView on macOS and EGL + X11/Wayland subsurfaces on Linux — for hardware-accelerated playback of virtually any IPTV protocol (HLS, RTMP, RTSP, TS, etc.).
See LICENSE for terms, NOTICE for trademark and legal disclaimers.
| Platform | Status | Video | Packages |
|---|---|---|---|
| macOS | Active | libmpv embedded (NSOpenGLView + OpenGL Core 3.2) | .dmg |
| Linux | Active | libmpv embedded (EGL + X11 child window / Wayland subsurface) | .deb, .rpm, .AppImage |
| Windows | Planned | libmpv | |
| iOS / iPadOS | Planned | AVPlayer + mvp-core via UniFFI | |
| Android / Fire Stick | Planned | ExoPlayer + mvp-core via JNI |
MaxVideoPlayer/
├── crates/
│ ├── core/ # mvp-core — M3U, Xtream Codes, EPG, SQLite cache
│ └── tauri-plugin-mpv/ # Custom Tauri plugin wrapping libmpv2
│ ├── src/engine.rs # MpvEngine — libmpv lifecycle
│ ├── src/renderer.rs # PlatformRenderer trait
│ ├── src/macos.rs # NSOpenGLView + OpenGL Core 3.2 (macOS)
│ ├── src/linux.rs # EGL + X11/Wayland (Linux)
│ ├── src/mpv.rs # MpvState — Tauri managed state
│ └── src/commands.rs # Tauri command handlers
├── apps/
│ └── desktop/
│ ├── src-tauri/ # Tauri app entry point
│ └── src/ # React frontend (TypeScript)
│ ├── components/ # UI components by domain
│ ├── hooks/ # useMpv, useChannels, usePlatform
│ └── lib/tauri.ts # All invoke() calls in one place
├── libs/ # libmpv binaries (gitignored, built by script)
└── scripts/
├── build-libmpv.sh # Build libmpv from source (macOS/Linux)
├── bundle-libmpv.sh # Platform dispatch for bundling at release
└── bundle-libmpv-linux.sh # Bundle .so deps for Linux AppImage
Homebrew's mpv formula is Vulkan-only. The embedded renderer requires OpenGL, so libmpv must be built from source:
# Install build dependencies
# Note: ffmpeg@7 required — mpv 0.40.0 uses APIs removed in ffmpeg 8.x
brew install meson ninja pkg-config ffmpeg@7 libass dylibbundler
export PKG_CONFIG_PATH="$(brew --prefix ffmpeg@7)/lib/pkgconfig:$PKG_CONFIG_PATH"
# Build libmpv from source (~3 min first run)
./scripts/build-libmpv.sh macosThis clones the mpv source into libs/mpv-src/ and outputs libs/macos/libmpv.dylib. Subsequent runs skip the clone.
Install system dependencies:
sudo apt-get update
sudo apt-get install -y \
libmpv-dev libegl-dev \
libgtk-3-dev libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev libsoup-3.0-dev \
libayatana-appindicator3-dev \
libssl-dev pkg-config librsvg2-dev \
patchelfThe system libmpv-dev package is used for development. To build libmpv from source instead:
sudo apt-get install meson ninja-build \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libass-dev libdrm-dev
./scripts/build-libmpv.sh linux
export LD_LIBRARY_PATH="$(pwd)/libs/linux:$LD_LIBRARY_PATH"npm install
# macOS
export DYLD_LIBRARY_PATH="$(pwd)/libs/macos:$DYLD_LIBRARY_PATH"
cd apps/desktop && npx tauri dev
# Linux (system libmpv-dev)
cd apps/desktop && npx tauri dev
# Linux (source-built libmpv)
export LD_LIBRARY_PATH="$(pwd)/libs/linux:$LD_LIBRARY_PATH"
cd apps/desktop && npx tauri devcargo test -p mvp-core # Rust core tests
cd apps/desktop && npm test # Frontend tests (Vitest)
cd apps/desktop && npm run test:coverage # Frontend tests with coverage reportCoverage reports are generated with @vitest/coverage-v8 and output to apps/desktop/coverage/. Open coverage/index.html for a detailed line-by-line breakdown.
cd apps/desktop && npx tauri buildOn macOS, bundle-libmpv.sh runs automatically as beforeBundleCommand and uses dylibbundler to embed libmpv into the .app. On Linux, bundle-libmpv-linux.sh bundles libmpv.so and its dependencies for AppImage distribution using ldd + patchelf. For .deb and .rpm, libmpv is declared as a system dependency.
MaxVideoPlayer uses tauri-plugin-updater to check for new releases on startup. When an update is found, a dismissible banner appears with a one-click install.
- Generate a signing keypair:
cd apps/desktop && npx tauri signer generate -w ~/.tauri/maxvideoplayer.key
- Copy the public key output into
apps/desktop/src-tauri/tauri.conf.json->plugins.updater.pubkey. - Add the private key and optional password as GitHub repository secrets:
TAURI_SIGNING_PRIVATE_KEY— contents of~/.tauri/maxvideoplayer.keyTAURI_SIGNING_PRIVATE_KEY_PASSWORD— password (leave empty if none)
Recommended (GitHub Actions): two workflows so rulesets that require pull requests, status checks, and verified commits on main still work.
- Release — bump version (PR) → Run workflow and pick patch / minor / major (semver.org). It opens a PR from branch
chore-bump-vX.Y.Zthat updatestauri.conf.json,apps/desktop/src-tauri/Cargo.toml, Settings About text, andCargo.lock. - Wait for CI (and Code Scanning if enabled for PRs). Merge the PR when green. If your rules require signed commits on
main, prefer Squash merge so the merge commit uses your verified identity. - Release — push tag → Run workflow. It reads the version from
tauri.conf.jsononmain, createsvX.Y.Z, and pushes the tag sorelease.ymlruns (builds macOS + Linux, draft GitHub Release,latest.json).
Who can run it: By default only the repository owner login matches the allowlist. For organization-owned repos, set a repository variable RELEASE_ALLOWED_ACTORS (comma-separated GitHub usernames).
Secret RELEASE_AUTOMATION_PAT (required for bump workflow): add a fine-grained PAT as repository secret RELEASE_AUTOMATION_PAT with Contents: Read and write and Pull requests: Read and write on this repo. GitHub often blocks the default GITHUB_TOKEN from creating pull requests (createPullRequest). For Release — push tag, the same PAT is optional unless tag protection or other rules require it; otherwise GITHUB_TOKEN may work.
Optional: Uncomment environment: release in .github/workflows/release-bump.yml and create a GitHub Environment named release with required reviewers so a second approval is required before the version bump runs.
Local script (same semver rules): ./scripts/release.sh from main — uses scripts/bump-version.py and can merge main → dev interactively. After merging locally, push tag vX.Y.Z or run Release — push tag on GitHub.
The release.yml workflow (on tag v*) builds signed artifacts for macOS (.dmg) and Linux (.deb, .rpm, .AppImage), creates a draft GitHub Release, and uploads latest.json for the auto-updater.
- M3U / M3U+ playlist support (URL and local file)
- Xtream Codes provider support
- EPG / XMLTV programme guide
- Favorites with persistent SQLite storage
- Hardware-accelerated playback (VideoToolbox on macOS, VAAPI/NVDEC on Linux)
- Sidebar navigation with Channels, Player, Guide, Playlists, and Settings views
- Channel list with virtual scrolling (
@tanstack/react-virtual) for large playlists - Graceful fallback to a native mpv window if the embedded renderer fails
| Layer | Technology |
|---|---|
| Desktop shell | Tauri v2 |
| Frontend | React 18, TypeScript, Tailwind CSS v3 |
| UI components | shadcn-style (Radix UI primitives) |
| Video engine | libmpv2 (custom Tauri plugin) |
| Rust core | mvp-core (M3U, Xtream, EPG, SQLite) |
| Database | SQLite via rusqlite (bundled) |
| EPG parsing | quick-xml |