screentinker/brightsign/server
ScreenTinker 4a4b9e343a brightsign: stage our own ffprobe/ffmpeg into /tmp so media tools work
The server logged "[MEDIA] ffmpeg, ffprobe not found on PATH — video thumbnails
and durations are DISABLED" on every boot of a player-hosted server. It now says
"found — video thumbnails enabled", because the binaries are shipped gzipped,
unpacked into /tmp at startup and put on PATH before server.js is required (its
probe looks them up by name with execFile, so PATH is the whole mechanism).

/tmp is not laziness, it is the only option, and the alternatives were measured on
an XT245 rather than assumed:

  /storage/ssd    bsexfat  rw,nosuid,nodev,noexec,...     <- exec => EACCES
  /storage/flash  ext4     rw,nosuid,nodev,noexec,...     <- same
  /storage/tmp    tmpfs    rw,nosuid,nodev,noexec,...     <- same
  /tmp            tmpfs    rw,relatime                    <- the one that permits exec

We run as uid=994(nodejs), so `mount -o remount,exec` answers "permission denied
(are you root?)" on both volumes, and there is no setuid path to it: BrightSign
points mount at busybox.nosuid, and their busybox.suid carries login/passwd/vlock
and no mount applet. A symlink does not help either — noexec is a property of the
filesystem holding the inode, not of the path used to reach it, so a link in /tmp
pointing at flash still fails EACCES. Copying is what moves the inode onto a
filesystem that permits execution.

The binaries are ours and deliberately link nothing of BrightSign's. The OS does
ship the whole ffmpeg 5.1 stack (libavformat/libavcodec/... backing GStreamer) and
a stock Debian ffprobe against those libs starts, prints its banner, and then
SIGSEGVs the moment it opens a file — their Yocto build is patched for hardware
decode. So these are cross-built FFmpeg 7.1.1, --disable-gpl (LGPL 2.1+), fully
static, --enable-small. ffprobe carries no decoders at all (durations and geometry
come from the container) which is why it is 1.8MB against ffmpeg's 4.9MB; ~6.7MB of
tmpfs on a box with 2.8GB free, ~3.2MB gzipped at rest.

Verified on XT245 URD3C6000823: unpack 19ms, ffprobe -version 9ms,
format=duration 3.533333 against a 3.533333s clip, stream 320x240 h264.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kfhrUPit5MCqxeTQyqr56
2026-08-18 20:12:26 -05:00
..
autorun.brs brightsign: read the server flag as an integer, not a Boolean 2026-08-18 17:37:38 -05:00
bs-payload-install.js Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -05:00
bs-server-boot.js brightsign: stage our own ffprobe/ffmpeg into /tmp so media tools work 2026-08-18 20:12:26 -05:00
node-server.html Make the on-device server opt-in, and stop the status port answering the LAN (#291) 2026-08-18 16:32:37 -05:00
server.env.example Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -05:00
st-config.example.json Make the on-device server opt-in, and stop the status port answering the LAN (#291) 2026-08-18 16:32:37 -05:00