Skip to content

feat: build and bundle libmpv from source on Linux with full audio support#60

Merged
MaxMB15 merged 8 commits intodevfrom
feature/bundle-libmpv-linux
Apr 8, 2026
Merged

feat: build and bundle libmpv from source on Linux with full audio support#60
MaxMB15 merged 8 commits intodevfrom
feature/bundle-libmpv-linux

Conversation

@MaxMB15
Copy link
Copy Markdown
Owner

@MaxMB15 MaxMB15 commented Apr 8, 2026

Summary

  • Build libmpv from source in CI with ALSA + PulseAudio audio outputs compiled in, replacing system libmpv-dev. Ensures AppImage ships fully self-contained with guaranteed audio support.
  • Recursive dependency bundling for AppImage — audio libs and their transitive deps are bundled with RPATH set on all .so files
  • deb/rpm audio dependencies — added libpulse0 | libasound2 (deb) and pulseaudio-libs (rpm), plus libass for subtitle rendering
  • Package updater dependency resolution — deb updates now use apt-get install (resolves deps) with dpkg -i fallback
  • Audio output flexibility — changed from hardcoded ao=pipewire,pulse,alsa to ao=auto

Context

A user on Pop!_OS reported no audio — their system libmpv was compiled without audio output plugins. This is a packaging reliability issue: we can't control what libmpv distros or users install. Building from source with known-good options solves this for AppImage, and explicit package deps solve it for deb/rpm.

Changes

File What
scripts/build-libmpv.sh Explicitly enable alsa/pulse/pipewire when dev headers available
scripts/bundle-libmpv-linux.sh Prefer source build, recursive transitive dep bundling, audio verification
crates/tauri-plugin-mpv/build.rs Prefer libs/linux/ over system pkg-config
.github/workflows/{build,release}.yml Install audio/ffmpeg dev packages, build from source
apps/desktop/src-tauri/tauri.conf.json Audio + subtitle deps for deb/rpm
apps/desktop/src-tauri/src/commands.rs apt-get install for deb updates
crates/tauri-plugin-mpv/src/linux.rs ao=auto instead of hardcoded list

Test plan

  • CI: build-linux job passes with source-built libmpv
  • AppImage: bundled audio libraries (libpulse, libasound) present in output
  • deb: package installs cleanly with audio deps resolved
  • Linux: audio playback works out of the box on fresh install

🤖 Generated with Claude Code

MaxMB15 and others added 2 commits April 8, 2026 22:01
Hardcoding "pipewire,pulse,alsa" prevented mpv from trying other
compiled-in audio backends (sdl, oss, jack, sndio). Using ao=auto
lets mpv try all available outputs, improving compatibility with
different libmpv builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pport

Build libmpv from source in CI instead of using system libmpv-dev, ensuring
ALSA + PulseAudio audio outputs are always compiled in. This prevents the
"no audio output found" issue on systems with stripped libmpv packages.

- build-libmpv.sh: explicitly enable alsa/pulse/pipewire audio when dev headers available
- bundle-libmpv-linux.sh: prefer source build, recursively bundle transitive deps,
  set RPATH on all bundled .so files, verify audio libs are present
- build.rs: prefer libs/linux/ (source build) over system pkg-config
- CI (build.yml, release.yml): install audio/ffmpeg dev packages, build from source
- tauri.conf.json: add audio (libpulse0|libasound2) and subtitle (libass) deps for deb/rpm
- package_update: use apt-get install (resolves deps) instead of dpkg -i for deb updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 8, 2026 20:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the Linux distribution more self-contained and reliable by building libmpv from source in CI with known audio backends enabled, bundling required shared libraries into the AppImage, and improving package dependency/install handling for .deb/.rpm distributions.

Changes:

  • Build libmpv from source on Linux CI with audio-related dev deps installed, and prefer linking against libs/linux/.
  • Enhance AppImage bundling to include libmpv plus additional dependent .so files and set RPATH on bundled libraries.
  • Improve Linux packaging/runtime behavior: add audio/subtitle dependencies for deb/rpm, use apt-get install for deb updates, and set mpv audio output to ao=auto.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/bundle-libmpv-linux.sh Prefer libs/linux/libmpv.so, bundle additional shared library deps, set RPATH on bundled .so files, and add a basic audio-lib presence check.
scripts/build-libmpv.sh Add Linux audio dev-package detection and conditionally enable ALSA/PulseAudio/PipeWire in the Meson build args.
crates/tauri-plugin-mpv/src/linux.rs Switch mpv audio option from a hardcoded backend list to ao=auto.
crates/tauri-plugin-mpv/build.rs Prefer linking against libs/linux/ on Linux before falling back to system pkg-config.
apps/desktop/src-tauri/tauri.conf.json Add runtime deps for audio (Pulse/ALSA) and subtitles (libass) to deb/rpm packaging config.
apps/desktop/src-tauri/src/commands.rs For deb updates, prefer apt-get install (dependency resolution) with dpkg -i fallback.
.github/workflows/release.yml Install build dependencies (meson/ninja/ffmpeg/audio/libass headers) and build libmpv from source in the Linux release job.
.github/workflows/build.yml Install build dependencies and build libmpv from source in the Linux CI build job.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/bundle-libmpv-linux.sh Outdated
Comment on lines +73 to +99
# Collect all libs to bundle (deduplicated)
declare -A BUNDLED_LIBS

# bundle_deps: resolve and collect transitive dependencies of a shared library
bundle_deps() {
local lib="$1"
ldd "$lib" 2>/dev/null | grep "=> /" | awk '{print $3}' | while read -r dep; do
basename_dep=$(basename "$dep")
if echo "$basename_dep" | grep -qE "$SYSTEM_LIBS_RE"; then
continue
fi
if [[ ! -f "$BUNDLE_DIR/$basename_dep" ]]; then
cp "$dep" "$BUNDLE_DIR/"
echo " bundled: $basename_dep"
# Recursively resolve deps of this library too (one level deep for audio libs)
ldd "$dep" 2>/dev/null | grep "=> /" | awk '{print $3}' | while read -r subdep; do
sub_basename=$(basename "$subdep")
if echo "$sub_basename" | grep -qE "$SYSTEM_LIBS_RE"; then
continue
fi
if [[ ! -f "$BUNDLE_DIR/$sub_basename" ]]; then
cp "$subdep" "$BUNDLE_DIR/"
echo " bundled: $sub_basename (transitive)"
fi
done
fi
done
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bundle_deps is described as collecting transitive dependencies, but the implementation only goes one level deep (direct deps + one nested ldd loop) and the declared BUNDLED_LIBS map is never used. This can miss deeper transitive dependencies and lead to an AppImage that runs on the CI runner but fails on a clean system. Consider implementing a true recursive walk to a fixpoint (using a visited set to avoid cycles) and either remove BUNDLED_LIBS or use it to dedupe/track visited libs.

Copilot uses AI. Check for mistakes.
Comment thread scripts/build-libmpv.sh Outdated
Comment on lines +143 to +173
# Build with explicit audio + video output support.
# Audio: alsa/pulse/pipewire are auto-detected from dev headers;
# we enable them explicitly so the build fails if headers are missing
# rather than silently producing a libmpv without audio.
BUILD_DIR="$MPV_SRC/build-linux"
echo " Running meson setup..."
meson setup "$BUILD_DIR" "$MPV_SRC" \
--buildtype=release \
--wipe \
-Dlibmpv=true \
-Dgl=enabled \
-Dvulkan=disabled \
-Dwayland=enabled \
-Dx11=enabled \

MESON_ARGS=(
--buildtype=release
--wipe
-Dlibmpv=true
-Dgl=enabled
-Dvulkan=disabled
-Dwayland=enabled
-Dx11=enabled
-Degl=enabled
)

# Enable audio outputs that have dev headers available
if pkg-config --exists alsa 2>/dev/null; then
MESON_ARGS+=(-Dalsa=enabled)
echo " Audio: ALSA enabled"
fi
if pkg-config --exists libpulse 2>/dev/null; then
MESON_ARGS+=(-Dpulse=enabled)
echo " Audio: PulseAudio enabled"
fi
if pkg-config --exists libpipewire-0.3 2>/dev/null; then
MESON_ARGS+=(-Dpipewire=enabled)
echo " Audio: PipeWire enabled"
fi
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments say audio outputs are enabled explicitly so the build fails if headers are missing, but the actual Meson args only add -Dalsa/-Dpulse/-Dpipewire=enabled when pkg-config finds those dev packages. As written, the build will still succeed with zero audio backends (only a warning earlier), which contradicts the comment and can silently reintroduce the no-audio problem. Either update the comment to match the behavior, or enforce at least one required backend (and/or fail the build when none are detected).

Copilot uses AI. Check for mistakes.
Comment on lines +240 to 245
- name: Build libmpv from source
run: |
./scripts/build-libmpv.sh linux
echo "LD_LIBRARY_PATH=$(pwd)/libs/linux:${LD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
echo "PKG_CONFIG_PATH=$(pwd)/libs/linux/pkgconfig:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV"

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

release.yml exports PKG_CONFIG_PATH=$(pwd)/libs/linux/pkgconfig, but scripts/build-libmpv.sh linux currently only copies libmpv.so into libs/linux/ and does not create a pkgconfig/ directory or install a .pc file there. This env var looks unused/misleading; either drop it or add a step that actually generates/copies the mpv/libmpv pkg-config file into that directory if something depends on it.

Copilot uses AI. Check for mistakes.
MaxMB15 and others added 6 commits April 8, 2026 22:09
…eanup

- Add libplacebo-dev to CI deps (required by mpv 0.40.0); disable via meson
  flag when not available for local builds
- Implement proper recursive dependency walk in bundle script (fixpoint loop
  using bundle dir as visited set) instead of one-level-deep nesting
- Remove unused BUNDLED_LIBS declaration
- Fix misleading comment about build failing without audio headers
- Remove bogus PKG_CONFIG_PATH pointing to nonexistent pkgconfig/ dir

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mpv 0.40.0 requires xscrnsaver, xext, xpresent, xrandr when X11 is enabled
and wayland-egl when Wayland is enabled. Also disable optional features
(lua, javascript, caca, sdl2, drm, jack, sndio, openal) to avoid
auto-detection pulling in unneeded deps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
libplacebo is a hard requirement of mpv 0.40.0, not a toggleable meson
option. libplacebo-dev is already in CI deps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pattern 'libmpv.so*' matched both the actual libmpv.so.2.5.0 file
and the libmpv.so.2.5.0.p directory (meson per-target build dir).
-not -type l only excluded symlinks, not directories, so cp failed with
'omitting directory'. Switch to -type f to match only regular files.

Made-with: Cursor
…e_all_deps

With 'set -euo pipefail', ldd|grep|awk|while fails silently when grep
finds no '=> /' lines (libs with only linux-vdso/ld-linux deps). The
pipeline's while loop also runs in a subshell, so queue+= updates were
lost and the QUEUE_FILE workaround was needed.

Switch to process substitution (< <(... || true)):
- '|| true' suppresses grep exit-1 on zero matches
- while body runs in the current shell so queue+= propagates directly
- QUEUE_FILE and its trap are no longer needed

Also add explicit error messages to patchelf calls so failures are
visible in CI logs instead of being swallowed by set -e.

Made-with: Cursor
@MaxMB15 MaxMB15 merged commit 8be2d03 into dev Apr 8, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants