Selkies

Licensing

What a Selkies installation contains besides Selkies, the license of each component, and where the GPL pieces come from.

Selkies itself

Selkies is licensed under the Mozilla Public License 2.0 (LICENSE in the repository, license = "MPL-2.0" in pyproject.toml). MPL-2.0 is file-level copyleft: a modified MPL file stays MPL when distributed, the larger work around it may be under any license. The Python package, the web client, the addons (Joystick Interposer, V4L2 interposer, fake-udev, coturn and TURN REST helpers, universal touch gamepad) and the build and packaging scripts all carry MPL-2.0 headers.

Categories used on this page: copyleft (GPL: the combined binary must be distributed under the GPL), weak copyleft (LGPL: the library stays under its license and must remain replaceable, dynamic linking is fine), permissive (attribution only: MIT, BSD, Apache-2.0, ISC, Zlib, MPL, PSF, ...).

Where the GPL code is

A Selkies installation has no GPL code of its own. Two dependencies bring GPL-licensed libraries into an installation made from PyPI wheels:

SourceGPL componentHow it gets inHow to leave it out
pixelflux (screen capture and video encoding)libx264 (GPL-2.0-or-later), the striped software H.264 encoderthe default gpl Cargo feature of pixelflux; the published wheels are built with it and bundle libx264.sobuild pixelflux with PIXELFLUX_ENABLE_GPL=0 (--no-default-features --features openh264): BSD-licensed Cisco OpenH264 takes the place of libx264. The inventory and the check that keeps that build copyleft-free live in pixelflux's LICENSES.md; pixelflux's musllinux wheels additionally bundle Alpine's GPL-built FFmpeg, see there.
The WebRTC stack no longer pulls PyAV (and the GPL FFmpeg its wheels bundle):
video and audio are encoded and decoded by pixelflux and pcmflux, and the RTP
layer packetizes their output through a libav-free EncodedPacket container.
PyAV is not a dependency of Selkies.

Everything else a Selkies installation links or loads is LGPL or permissive. The container images also install the distribution's ffmpeg and x264 packages, which are GPL builds on Debian and Ubuntu; pixelflux links that libavcodec for VA-API.

Python dependencies

pyproject.toml dependencies, with the license from the installed distribution metadata (importlib.metadata). "How used" names native code the wheel bundles or loads, which is where licenses other than the package's own come in.

PackageLicenseCategoryHow usedNotes
pixelfluxMPL-2.0permissivePyO3 extension; links FFmpeg (LGPL-2.1-or-later as built for its manylinux wheels), libgbm, libpixman, libxkbcommon (MIT); libx264 (GPL) in the default buildsee pixelflux LICENSES.md
pcmfluxMPL-2.0permissivePyO3 extension; links libpulse (LGPL-2.1-or-later) and libopus (BSD-3-Clause), bundled into its wheels with libpulse's LGPL/permissive dependency treesee pcmflux LICENSES.md
aiohttpApache-2.0 AND MITpermissiveHTTP and WebSocket serverbundles llhttp (MIT); pulls aiohappyeyeballs (PSF-2.0), aiosignal, frozenlist, multidict, propcache, yarl (Apache-2.0), attrs (MIT), idna (BSD-3-Clause)
aiofilesApache-2.0permissivefile uploads and downloads
cryptographyApache-2.0 OR BSD-3-ClausepermissiveDTLS/SRTP keys, self-signed certificatesbundles OpenSSL (Apache-2.0); cffi (MIT), pycparser (BSD-3-Clause)
pyOpenSSLApache-2.0permissiveDTLS transport
pylibsrtpBSD-3-ClausepermissiveSRTPbundles libsrtp2 (BSD-3-Clause)
google-crc32cApache-2.0permissiveSCTP checksumsbundles crc32c (BSD-3-Clause)
dnspythonISCpermissivemDNS ICE candidates
ifaddrMITpermissiveinterface enumeration for ICE
pyeeMITpermissiveevent emitter of the WebRTC stacktyping_extensions (PSF-2.0)
uvloopMIT OR Apache-2.0permissiveevent loop (Linux, macOS)bundles libuv (MIT)
msgpackApache-2.0permissivecontrol-channel encoding
psutilBSD-3-Clausepermissivesystem and process statistics
watchdogApache-2.0permissivefile-change notifications
PillowMIT-CMU (HPND)permissiveclipboard images, cursors, iconsbundles libjpeg-turbo (IJG/BSD-3-Clause/Zlib), libpng, libtiff, libwebp, openjpeg, libavif, freetype (FTL or GPL-2.0-or-later, dual), harfbuzz, lcms2, brotli, zstd (BSD-3-Clause or GPL-2.0, dual), xz, xcb: all usable under permissive terms
prometheus_clientApache-2.0 AND BSD-2-Clausepermissivemetrics endpoint
pulsectl-asyncioMITpermissivemicrophone routing through PulseAudiopulsectl (MIT) opens the host's libpulse (LGPL-2.1-or-later) through ctypes at run time
nvidia-ml-pyBSD-3-ClausepermissiveGPU statisticsopens the NVIDIA driver's libnvidia-ml (proprietary) through ctypes at run time when present
aitopMITpermissiveGPU statistics
importlib_resources (Python 3.9 only)Apache-2.0permissivepackage data on 3.9

The Python interpreter itself (PSF-2.0) and, when installed, the distribution's PulseAudio or PipeWire, X servers, Wayland compositors and GPU drivers are outside the package and keep their own licenses.

Vendored code in the Python package

ComponentWhereLicenseCategoryNotes
python-xlib 0.33 forksrc/selkies/XlibLGPL-2.1-or-later (every module header: "version 2.1 of the License, or (at your option) any later version")weak copyleftImported, not modified in license terms; the wheel ships selkies/Xlib/LICENSE (tool.setuptools.package-data) as the LGPL-3.0 text: the headers grant "version 2.1 or (at your option) any later version", and the fork is carried under LGPL-3.0 for compatibility with the MPL-2.0 of the rest of Selkies. The Python sources are the preferred form, so the LGPL's replaceability requirement is met as is.
aiortc and aioice forkssrc/selkies/webrtc, src/selkies/iceBSD-3-Clause (Jeremy Lainé), MPL-2.0 for the Selkies changespermissiveevery file keeps the upstream copyright and license notice under the MPL header
Built web clientsrc/selkies/selkies_web (generated by scripts/ci/build-web.sh, not in git)MPL-2.0 plus the npm runtime dependencies belowpermissive

Web client (npm)

Licenses as reported by license-checker over the installed node_modules of the three addons (production dependencies are what can end up in the built client; development dependencies only run at build time and ship nothing).

AddonRuntime dependencies shipped in the buildLicensesBuild-only dependencies
addons/selkies-web-corenone: the bundle is Selkies' own MPL-2.0 code; gendb.js converts the SDL_GameControllerDB gamecontrollerdb.txt (Zlib) into the jsdb/ mapping files at build timeMPL-2.0 (Selkies), Zlib (mappings)vite, vite-plugin-minify, vite-plugin-env-compatible (declared under dependencies, used by the build only) and 47 transitive packages: MIT, BSD-2-Clause, ISC, Apache-2.0, CC0-1.0 (mdn-data), BlueOak-1.0.0 (sax), MPL-2.0 (lightningcss); no copyleft beyond MPL
addons/selkies-dashboardreact, react-dom (MIT), js-yaml (MIT) with argparse (Python-2.0); universalTouchGamepad.js (MPL-2.0); the core aboveMIT, Python-2.0, MPL-2.0159 packages: MIT, BSD-2-Clause, Apache-2.0, ISC, BSD-3-Clause, MPL-2.0, CC0-1.0, BlueOak-1.0.0, Python-2.0, CC-BY-4.0 (caniuse-lite data)
addons/selkies-dashboard-wishreact, react-dom, radix-ui and the @radix-ui/* primitives, framer-motion, recharts (with d3, ISC), lucide-react (ISC), sonner, next-themes, tailwind-merge, clsx (MIT), class-variance-authority (Apache-2.0), js-yaml (MIT) with argparse (Python-2.0), @fontsource-variable/inter (SIL OFL-1.1, the Inter font files are bundled into the build), tw-animate-css (MIT); universalTouchGamepad.js (MPL-2.0); the core aboveMIT, ISC, Apache-2.0, BSD-3-Clause, BSD-2-Clause, 0BSD, OFL-1.1, Python-2.0, MPL-2.0390 packages (vite, typescript, eslint, tailwindcss with lightningcss under MPL-2.0, shadcn, ...): MIT, ISC, Apache-2.0, BSD, 0BSD, BlueOak-1.0.0, CC0-1.0, CC-BY-4.0; no copyleft beyond MPL

addons/selkies-web-core/package.json declares "license": "MPL-2.0", the license every file of the directory carries, and addons/universal-touch-gamepad/README.md names the same license and the repository LICENSE file; npm license scanners read the package.json field, so it matches the sources.

Native addons and helper images

ComponentLicenseLinks or loadsNotes
Joystick Interposer (addons/js-interposer, selkies_joystick_interposer.so)MPL-2.0libc, libdlLD_PRELOAD library
V4L2 interposer (addons/v4l2-interposer)MPL-2.0libc, libdl; dlopens libpipewire-0.3 (MIT) when a PipeWire source is configuredshares its ring layout with pixelflux's VirtualCamera
fake-udev (addons/fake-udev)MPL-2.0 (own libudev.h declarations, no systemd code)libcreplaces the LGPL libudev only by ABI, for virtual gamepads
coturn addon (addons/coturn)MPL-2.0 scripts around the coturn imageruns coturn (BSD-3-Clause)TURN server
TURN REST (addons/turn-rest)MPL-2.0aiohttp

The default is GPL-enabled

pixelflux builds with its GPL components on by default (libx264 for software H.264), and that is the supported default for every deployment — PyPI wheels, the container images and the AppImage, which may therefore bundle a GPL FFmpeg through pixelflux. PIXELFLUX_ENABLE_GPL=0 is the opt-out for operators who need a copyleft-free build; the sections below describe both.

What a non-GPL deployment contains

With pixelflux built with PIXELFLUX_ENABLE_GPL=0: Selkies (MPL-2.0), the permissive Python packages above, the LGPL libraries they load (libpulse through pcmflux and pulsectl, python-xlib, glibc, FFmpeg as an LGPL build through pixelflux) and the permissive web client. Nothing GPL. The WebRTC stack adds no FFmpeg of its own — it packetizes pixelflux/pcmflux output and no longer depends on PyAV.

What the default (GPL-enabled) deployment adds

pip install selkies adds libx264 through the published pixelflux wheels; the container images add the distribution's FFmpeg and x264 packages. libx264 is GPL-2.0-or-later, and an FFmpeg configured with --enable-gpl --enable-version3 (Debian, Ubuntu, Alpine) is GPL-3.0-or-later, so a deployment that ships them is distributed under GPL terms for those parts.

How this is kept up to date

Selkies has no license gate of its own: the copyleft switch is pixelflux's, and pixelflux's scripts/check-licenses.py, deny.toml and Licenses workflow enforce that its non-GPL build stays copyleft-free (pcmflux carries the same cargo-deny check). This page is the inventory of what Selkies adds on top. Regenerate the figures with pip show or importlib.metadata for the Python packages and npx license-checker --summary --production in each of the three addon directories after npm install.

On this page

Edit on GitHub