It contains every encoder — strings on its .so lists mpph264enc, mpph265enc, mppjpegenc and mppvp8enc. The earlier claim here was wrong, and it was the headline reason given for building our own, so it needs correcting rather than quietly dropping. What actually happened is one cause behind four symptoms, and this build surfaced the fourth: an MPP plugin registers its decoders unconditionally but *probes MPP* before registering its encoders. With /dev/mpp_service at 0600 root:root the probe fails silently. So mpi_enc_test wrote an empty file and exited 0; Radxa's deb looked decode-only; a third-party deb installed and still showed no mpph264enc; and this repository's own CI build lists only mppjpegdec and mppvideodec, because a container has no such node either. That last one is expected, not a failure, and the README now says so where somebody reading a green build log will find it. The reasons to build that survive: no libx11-6, since rkximage and kmssrc are disabled; a pin we control, recorded in every release; and this repository has to exist for gst-plugins-rs regardless, which no archive packages at all — so the MPP plugin riding along costs almost nothing. Assisted-by: Claude:claude-opus-5[1m]
microduck-gst-plugins
Prebuilt aarch64 GStreamer plugins for the micro duck robot, built in CI from pinned upstream sources and attached to a release.
Two plugins, for two unrelated reasons. Neither is packaged anywhere we can install from.
| plugin | provides | why it is here |
|---|---|---|
libgstrockchipmpp.so |
mpph264enc, mpph265enc, mppjpegenc, mppvp8enc, mppvideodec, mppjpegdec |
Debian ships no Rockchip encoder in any suite. Radxa's own gstreamer1.0-rockchip1_1.14-4 does contain them, so this build is about the pin, dropping libx11-6, and riding along with the plugin below — see below. |
libgstrswebrtc.so, libgstrsrtp.so |
webrtcsink, webrtcsrc, rsrtp* |
gstreamer1.0-plugins-rs does not exist in any Debian suite — not trixie, backports, sid or experimental. |
webrtcbin is not here: it comes from gstreamer1.0-plugins-bad in Debian and needs no
build.
Why a repository of its own
The robot's daemon is cross-compiled from a developer's machine with cargo-zigbuild, and its one
C dependency is already the documented cost of doing that. GStreamer would be a much larger second
one — a cross sysroot or x86 multiarch, either of which links against an approximation of the
target.
So these are built natively on an arm64 runner, in a debian:trixie container, which is the
robot's own userland. Nothing is cross-compiled and nothing is approximated. arm64 runners are
free on public repositories, which is one reason this repository is public.
The other reason matters more: a release asset here is fetched by a robot during provisioning and
by the updater's preinstall hook, and that hook runs with a cleared environment and no token. A
private repository would break it. This is the same arrangement the daemon already relies on for
ONNX Runtime, which comes from a public microsoft/onnxruntime release.
Building rather than taking a third-party binary also buys one concrete thing beyond provenance:
rkximage and kmssrc, the X11 and KMS sinks in the same source tree, are disabled. A
headless robot has no use for either, and they are why the prebuilt Radxa deb depends on
libx11-6.
The permission trap that hid all of this
/dev/mpp_service arrives as 0600 root:root, and an MPP GStreamer plugin registers its
decoders unconditionally but probes MPP before registering its encoders. With the node
unreadable the probe fails and the encoders are silently omitted — no error, no log line.
That one cause produced four separate misleading results while this was being worked out:
mpi_enc_testwrote an empty file and exited 0.- Radxa's
1.14-4looked decode-only. It is not;stringson its.solists every encoder. - A third-party
1.14-8deb installed cleanly and still showed nompph264enc. - This repository's own CI build shows only
mppjpegdecandmppvideodec, because a container has no/dev/mpp_serviceeither. That is expected, not a failed build.
So: a plugin that lists only decoders is evidence about the device node, not about the plugin. A
non-root process needs a udev rule giving the node a group — mode 0660, group video — and only
then does gst-inspect-1.0 mpph264enc mean anything.
Consuming a release
tar -xzf microduck-gst-plugins-<version>-aarch64.tar.gz
Put the .so files anywhere and point GST_PLUGIN_PATH at it — /usr/local/lib/gstreamer-1.0
on a robot, which is deliberately not the distro's plugin directory, so an apt operation can
never quietly replace or remove them.
GST_PLUGIN_PATH=/usr/local/lib/gstreamer-1.0 gst-inspect-1.0 mpph264enc
Verify the tarball against the .sha256 beside it before unpacking. Pin a version; do not
follow "latest". Two provisioning runs a day apart that produce different plugins, with nothing
recording which, is an unreproducible media bug waiting to happen.
Runtime dependencies
The plugins link against libraries a robot needs installed:
librockchip-mpp1andlibrga2— from Radxa's pool, at the versions inpins.env. Not in Debian.libgstreamer1.0-0,libgstreamer-plugins-base1.0-0,libglib2.0-0,libdrm2— Debian.
mpph264enc also needs read/write access to /dev/mpp_service — see
the permission trap, which is the single most
misleading thing about this stack.
Bumping a pin
Edit pins.env, commit, tag vN, push the tag. The release workflow builds and
attaches the tarball, with the manifest as the release notes so a release always says which
upstream commits it came from.
workflow_dispatch builds without cutting a release — worth using, because a workflow that only
ever runs on a tag is one you discover is broken at the moment you need it.
Licences and source
These are binaries built from other people's source, so where that source is matters:
gstreamer-rockchipis LGPL. Built fromJeffyCN/mirrorson thegstreamer-rockchipbranch, at the commit inpins.envand recorded in every release'sMANIFEST.rockchip-linux/gstreamer-rockchip, which every published deb names as its homepage, is a 404;JeffyCN/mirrorsis the live mirror under the same maintainer.gst-plugins-rsis MPL-2.0. Built from the upstream repository at the tag inpins.env.
Nothing here is modified — no patches, no forks. Each release's MANIFEST names the repository
and the exact ref per plugin, which is both the licence answer and the reason a media bug found on
a robot can be traced to a specific build.
This repository's own build scripts are Apache-2.0, matching the daemon.