Files
iptvnator/tools/embedded-mpv/README.md
T

7.5 KiB

Embedded MPV Runtime

This directory owns the source builders, staging, manifests, and archive helpers for IPTVnator's experimental Embedded MPV runtime.

The Linux architecture has a strict process boundary:

  • Electron, embedded_mpv.node, and embedded_mpv_frame_reader.node must not load or link libmpv.
  • Native-view starts a separate system mpv --wid process.
  • Frame-copy starts iptvnator_mpv_helper; only that helper may link libmpv.

Do not weaken this boundary to simplify packaging. A missing helper/runtime must make frame-copy unavailable and leave native-view as the safe x64 fallback.

Runtime Policy

Release builds use an LGPL-compatible, dynamically linked runtime:

  • FFmpeg is built without --enable-gpl and --enable-nonfree.
  • mpv is built with -Dlibmpv=true and -Dgpl=false.
  • Bundled libraries remain individually replaceable under native/lib.
  • Exact source URLs, versions, checksums or git commits, submodules, licenses, build flags, local patches, and build scripts are published with the release.

Homebrew mpv is local-development-only. It requires IPTVNATOR_EMBEDDED_MPV_ALLOW_HOMEBREW=1, and release validation rejects it.

Generated Layout

vendor/embedded-mpv/
  darwin-arm64/
    include/mpv/client.h
    lib/*.dylib
    runtime-manifest.json
  darwin-x64/
    include/mpv/client.h
    lib/*.dylib
    runtime-manifest.json
  win32-x64/
    include/mpv/client.h
    lib/libmpv-2.dll        # accepted basename variants are preserved
    lib/libmpv.dll.a        # or an MSVC import library
    runtime-manifest.json
  linux-x64/
    include/mpv/client.h
    lib/libmpv.so
    lib/libmpv.so.2
    lib/<declared closure>
    runtime-manifest.json

These directories are generated release inputs and are ignored by git. runtime-manifest.json is the profile-neutral source/build manifest. Packaging writes a normalized embedded-mpv-runtime.json beside the native artifacts.

Building And Staging

Stage an existing compatible prefix with:

pnpm embedded-mpv:stage-runtime -- darwin arm64 /path/to/prefix
pnpm embedded-mpv:stage-runtime -- darwin x64 /path/to/prefix
pnpm embedded-mpv:stage-runtime -- win32 x64 /path/to/prefix
pnpm embedded-mpv:stage-runtime -- linux x64 /path/to/prefix

Build the pinned macOS or Linux source runtime first when no prefix exists:

pnpm embedded-mpv:build-runtime -- arm64 /tmp/macos-prefix
pnpm embedded-mpv:stage-runtime -- darwin arm64 /tmp/macos-prefix

pnpm embedded-mpv:build-runtime:linux -- /tmp/linux-prefix
pnpm embedded-mpv:stage-runtime -- linux x64 /tmp/linux-prefix

The Linux builder runs only on Linux x64. It requires the tool versions and system development interfaces declared in build-linux-runtime.cjs, including Meson 1.6 or newer, Ninja, CMake, NASM, pkg-config, patchelf, and readelf. It builds into an owned staging directory and publishes atomically, so it will not delete or overwrite an arbitrary destination.

The pinned Linux source stack currently includes FFmpeg 8.1, mpv 0.41.0, libplacebo 7.360.1, libass 0.17.3, FreeType 2.13.3, FriBidi 1.0.16, HarfBuzz 8.5.0, Expat 2.8.2, Fontconfig 2.16.0, OpenSSL 3.5.7, hwdata 0.409, and libdisplay-info 0.1.1. The builder stages a private pinned pnp.ids/hwdata.pc; libdisplay-info is not allowed to consume the build host's /usr/share/hwdata.

Before publication, the Linux builder verifies:

  • every archive digest and git/submodule commit;
  • the exact FFmpeg/mpv flags and LGPL policy;
  • an exact libmpv.so.2 SONAME and complete reachable shared-library closure;
  • $ORIGIN RUNPATHs with no build-prefix paths or undeclared host fallback;
  • the external system-library allowlist;
  • GLIBC_2.35 and GLIBCXX_3.4.30 ABI ceilings;
  • file hashes, byte sizes, build inputs, licenses, and source obligations.

Linux Package Profiles

Set one exact IPTVNATOR_LINUX_FRAME_COPY_PROFILE per packaging pass:

Profile Formats Runtime handling
system DEB, RPM, Pacman Remove native/lib; require libmpv2, mpv-libs, or mpv
portable AppImage, Snap Retain the pinned LGPL closure under native/lib
flatpak Flatpak Retain the same pinned LGPL closure under native/lib

Profiles cannot share one Electron Builder pass because its targets reuse the same unpacked application directory. A missing or unsupported profile, or a target from another profile, fails packaging.

Linux frame-copy release artifacts are x64-only. Non-x64 packages are always marker-only even if environment variables point at the x64 staged runtime.

Build Integration

apps/electron-backend/build-embedded-mpv.js builds the addon, frame reader, and helper against the staged inputs. On Linux it links the helper to the verified staged libmpv path rather than a generic host -lmpv, then checks with readelf that:

  • the helper has exactly the declared libmpv DT_NEEDED;
  • the helper RUNPATH is $ORIGIN/lib;
  • the addon and frame reader have no libmpv dependency;
  • no runtime dependency contains an absolute/build-prefix loader path.

The package hook copies native artifacts into app.asar.unpacked/electron-backend/native/, selects the system or bundled layout, restores exact file modes, and writes the packaged manifest. Package validation also scans the Electron executable and all shipped Electron libraries for a direct libmpv dependency.

At startup, Linux x64 frame-copy is advertised only after the main process validates that manifest/files and successfully executes:

iptvnator_mpv_helper --runtime-probe

The bounded probe initializes idle libmpv plus EGL/OpenGL and mpv render contexts without media or shared memory. A timeout, loader failure, malformed protocol, missing file, hash mismatch, or unusable graphics path returns a stable reason and keeps the BrowserWindow sandbox enabled.

CI And Source Distribution

Linux CI builds or restores the pinned source runtime once, then packages and verifies system, portable, and flatpak independently. Every artifact is extracted for manifest, mode, package-metadata, ELF-isolation, and helper-probe checks. System formats are probed after their declared dependency is installed; Snap and Flatpak also require a sandboxed probe where the runner supports it.

The binary release must include a source-compliance bundle containing the exact downloaded archives (including hwdata), the recorded libplacebo checkout or git bundle and submodules, builder/stager/manifest code, generated runtime manifest, and local patches. A cache hit does not remove this obligation.

Windows CI stages a checksum-pinned x64 LGPL archive. The DLL basename encoded in its import library is preserved and must be present beside iptvnator_mpv_helper.exe. Tagged releases require explicit repository configuration; the public fallback is for non-tag artifacts only.

Local Development

Linux can use distribution development packages for an unshipped local build (libmpv-dev, EGL/OpenGL/GBM development files, and X11 headers). Overrides: LIBMPV_INCLUDE_DIR and LINUX_NATIVE_LIBRARY_DIR. Required/release package builds must use the pinned staged runtime and manifest.

On macOS:

pnpm run serve:backend:embedded-mpv

This explicitly permits Homebrew for the local native build and enables the experiment. It is not a release path.

See docs/architecture/embedded-mpv-native.md for the runtime capability, fallback, controls, and packaged-release contracts.