mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 03:56:15 -08:00
docs: design Linux frame-copy packaging
This commit is contained in:
1 parent
c6ed504723
commit
2877ec59e5
1 file changed
+206
@@ -0,0 +1,206 @@
|
||||
# Linux Embedded MPV Frame-Copy Packaging Design
|
||||
|
||||
**Date:** 2026-07-17
|
||||
|
||||
**Status:** Approved
|
||||
|
||||
## Goal
|
||||
|
||||
Ship a genuinely usable Embedded MPV frame-copy runtime in every official
|
||||
Linux x64 package format produced by IPTVnator: AppImage, DEB, RPM, Pacman,
|
||||
Snap, and Flatpak. Keep libmpv outside the Electron process, retain the
|
||||
existing native-view engine as a safe fallback, and never advertise
|
||||
frame-copy from artifact presence alone.
|
||||
|
||||
Linux arm64 and armv7l remain out of scope for native Embedded MPV artifacts.
|
||||
The current CI cross-packages those architectures from an x64 host and cannot
|
||||
produce or exercise matching native addons. Those packages must continue to
|
||||
carry an explicit unavailable marker and must not contain x64 native binaries.
|
||||
|
||||
## Evidence From The Existing Implementation
|
||||
|
||||
- `apps/electron-backend/native/binding.gyp` builds three distinct artifacts:
|
||||
the native-view addon, the N-API shared-memory frame reader, and the
|
||||
`iptvnator_mpv_helper` process. On Linux only the helper links `-lmpv`; the
|
||||
addon uses X11/Xext/dlopen and must remain free of libmpv linkage.
|
||||
- `tools/packaging/embedded-mpv-frame-copy-files.cjs` deliberately deletes the
|
||||
helper from every Linux package.
|
||||
- `tools/packaging/embedded-mpv-packaging.cjs` rejects Linux packages that
|
||||
contain either the helper or libmpv, and accepts only the
|
||||
`external-mpv-process` manifest origin.
|
||||
- `resolveFrameCopyHelperPath()` currently treats an executable helper plus a
|
||||
readable reader addon as a usable runtime. It does not prove that the ELF
|
||||
loader can resolve libmpv or that libmpv/EGL initialization works.
|
||||
- `.github/workflows/build-and-make.yaml` builds and verifies the Linux helper
|
||||
against Ubuntu's system libmpv, then relies on the after-pack hook to remove
|
||||
it. The same x64 build output is used for foreign-architecture Linux
|
||||
packages, which receive the unavailable marker.
|
||||
- Electron Builder creates one unpacked application layout before producing
|
||||
multiple distributable targets. A system-runtime layout and a bundled
|
||||
portable-runtime layout therefore cannot safely share one packaging pass.
|
||||
|
||||
## Selected Distribution Strategy
|
||||
|
||||
Linux packaging is split into explicit profiles:
|
||||
|
||||
| Profile | Formats | libmpv strategy |
|
||||
| --- | --- | --- |
|
||||
| `system` | DEB, RPM, Pacman | Depend on the distribution package and resolve `libmpv.so.2` from the host |
|
||||
| `portable` | AppImage, Snap | Bundle the pinned LGPL-compatible runtime closure under `native/lib` |
|
||||
| `flatpak` | Flatpak | Bundle the same pinned LGPL-compatible runtime closure under `native/lib` |
|
||||
|
||||
The official CI matrix must run these profiles independently. The packaging
|
||||
hook receives the profile through a required environment value and validates
|
||||
that the selected target set matches the runtime mode. It must fail closed if
|
||||
an official x64 package is requested with an absent, incomplete, or ambiguous
|
||||
profile.
|
||||
|
||||
System package dependencies are:
|
||||
|
||||
- DEB: `libmpv2`
|
||||
- RPM: `mpv-libs`
|
||||
- Pacman: `mpv`
|
||||
|
||||
These names match the current Debian, Fedora, and Arch package databases.
|
||||
System packages do not copy libmpv into IPTVnator. The helper keeps an
|
||||
`$ORIGIN/lib` RPATH first for a consistent binary, but naturally resolves the
|
||||
system SONAME when the private directory is absent.
|
||||
|
||||
Portable and sandboxed packages use a source-built runtime rather than copying
|
||||
the Ubuntu runner's mpv package. The runtime build is checksum/version pinned,
|
||||
uses FFmpeg without GPL/nonfree switches and mpv with `-Dgpl=false`, records
|
||||
sources and exact flags in the manifest, and keeps shared libraries replaceable
|
||||
under the LGPL. The minimal codec baseline is FFmpeg's built-in LGPL decoders,
|
||||
demuxers, protocols, and software scaling/resampling plus libass text
|
||||
subtitles. Hardware decoding remains opportunistic through host Mesa/driver
|
||||
interfaces and must fall back to software decoding.
|
||||
|
||||
## Runtime Layout And Linkage
|
||||
|
||||
The x64 packaged native directory is:
|
||||
|
||||
```text
|
||||
resources/app.asar.unpacked/electron-backend/native/
|
||||
embedded_mpv.node
|
||||
embedded_mpv_frame_reader.node
|
||||
iptvnator_mpv_helper
|
||||
embedded-mpv-runtime.json
|
||||
lib/
|
||||
libmpv.so.2
|
||||
libavcodec.so.*
|
||||
libavformat.so.*
|
||||
libavutil.so.*
|
||||
libavfilter.so.*
|
||||
libswresample.so.*
|
||||
libswscale.so.*
|
||||
libass.so.*
|
||||
...other non-system runtime dependencies
|
||||
```
|
||||
|
||||
For `system`, `lib/` is absent and the manifest declares the required SONAME
|
||||
and package-family dependency. For `portable` and `flatpak`, `lib/` contains
|
||||
the complete non-system dependency closure. ELF dependencies inside that
|
||||
closure and the helper use only SONAMEs plus `$ORIGIN`-relative RPATH/RUNPATH;
|
||||
they may not retain build-prefix paths.
|
||||
|
||||
`embedded_mpv.node`, the Electron executable (`iptvnator.bin`), and Electron's
|
||||
shipped libraries must not have a direct `DT_NEEDED` entry for libmpv.
|
||||
`iptvnator_mpv_helper` must have one. Process isolation is an invariant, not a
|
||||
profile-specific choice.
|
||||
|
||||
The manifest records:
|
||||
|
||||
- schema version, platform, architecture, profile, and runtime origin;
|
||||
- required helper/reader names and executable/readable expectations;
|
||||
- libmpv SONAME and either system package requirements or bundled files;
|
||||
- source package versions, URLs/checksums, license identifiers, and exact
|
||||
FFmpeg/mpv build flags for bundled profiles;
|
||||
- runtime closure and total byte size;
|
||||
- the native-view backend contract and the fact that only the helper links
|
||||
libmpv.
|
||||
|
||||
## Honest Capability Detection
|
||||
|
||||
The helper gains a side-effect-free `--runtime-probe` mode. It must:
|
||||
|
||||
1. load through the normal ELF loader and therefore prove that all `DT_NEEDED`
|
||||
dependencies resolve;
|
||||
2. create and initialize an idle libmpv handle with `vo=libmpv`;
|
||||
3. create the platform render pipeline far enough to prove EGL/OpenGL/GBM
|
||||
availability without opening media or shared memory;
|
||||
4. emit one versioned JSON result and exit promptly with status zero only on
|
||||
success.
|
||||
|
||||
The main process invokes this probe synchronously with a bounded timeout before
|
||||
BrowserWindow creation. Probe success is cached for the process lifetime.
|
||||
The probe environment prepends the packaged `native/lib` directory only when
|
||||
the manifest declares a bundled runtime. The system profile does not inject a
|
||||
private loader path.
|
||||
|
||||
Frame-copy is usable only when all of the following are true:
|
||||
|
||||
- platform and architecture are supported;
|
||||
- helper and reader are regular files with correct access modes;
|
||||
- the runtime manifest is present, parses, matches Linux/x64, names the actual
|
||||
artifacts, and uses an allowed profile/origin;
|
||||
- every manifest-declared bundled file exists as a readable regular file;
|
||||
- `--runtime-probe` succeeds and returns the expected protocol version.
|
||||
|
||||
Any failure returns `false`, keeps the renderer sandbox enabled, and makes the
|
||||
native service choose native-view. The capability result includes a stable
|
||||
reason code for tracing and diagnostics but does not crash startup.
|
||||
|
||||
If dependencies disappear after startup, helper spawn/early-exit remains a
|
||||
session error and follows the existing renderer fallback path. The helper is
|
||||
never loaded into Electron as a library.
|
||||
|
||||
## Packaging And CI Validation
|
||||
|
||||
Unit and packaging tests cover:
|
||||
|
||||
- profile-to-target mapping and rejection of mixed system/bundled passes;
|
||||
- Linux runtime staging, manifest normalization, closure collection, RPATH,
|
||||
file modes, and stale-artifact cleanup;
|
||||
- package validation for system, portable, Flatpak, foreign architecture, and
|
||||
malformed/incomplete manifests;
|
||||
- capability probe timeout, nonzero exit, invalid JSON, manifest mismatch,
|
||||
missing dependency, and successful result caching;
|
||||
- helper probe protocol and failure behavior;
|
||||
- package metadata dependencies for DEB/RPM/Pacman.
|
||||
|
||||
Linux CI must:
|
||||
|
||||
1. build or restore the pinned x64 LGPL runtime;
|
||||
2. build the addon, reader, and helper once against that staged runtime;
|
||||
3. prove with `readelf`/`ldd` that Electron and `embedded_mpv.node` do not link
|
||||
libmpv and the helper does;
|
||||
4. package the three profiles independently;
|
||||
5. unpack or mount each produced format and validate its real payload, modes,
|
||||
manifest, RPATH, dependency closure, and profile;
|
||||
6. install/run a lightweight helper probe inside the actual Snap and Flatpak
|
||||
sandboxes and from AppImage;
|
||||
7. install system packages in matching disposable distro containers and run
|
||||
the helper probe after the declared libmpv dependency is installed;
|
||||
8. run a packaged Electron smoke test that confirms frame-copy capability,
|
||||
creates a helper session against a deterministic local media fixture, sees
|
||||
at least one frame/snapshot, and then repeats with libmpv hidden or removed
|
||||
to prove non-crashing native-view fallback.
|
||||
|
||||
Checks that require Linux kernel/package tooling or GPU/EGL are CI-only.
|
||||
macOS development can run all pure Node/Jest tests and static source checks,
|
||||
but cannot establish Linux ELF, package-manager, sandbox, or rendering
|
||||
behavior.
|
||||
|
||||
## Documentation And Release Compliance
|
||||
|
||||
Update `docs/architecture/embedded-mpv-native.md`,
|
||||
`tools/embedded-mpv/README.md`, `vendor/embedded-mpv/README.md`,
|
||||
`AGENTS.md`, and `CLAUDE.md`. The docs must describe the x64 format matrix,
|
||||
profile selection, manifest/probe contract, process-isolation invariant,
|
||||
fallback behavior, source-distribution obligations, codec baseline, and ARM
|
||||
status.
|
||||
|
||||
Release artifacts must publish the generated runtime manifest and exact source
|
||||
archives/metadata required by the recorded LGPL source-distribution statement.
|
||||
No publication, push, pull request, or merge is part of this task.
|
||||
|
||||
Reference in new issue
Block a user