brightsign: ship ffprobe/ffmpeg in the payload so they survive updates

The staging code added in 4a4b9e3 reads bin/<tool>.gz from the install root, with
DATA_DIR as a fallback; until now only the fallback was populated, by hand. The
payload carries them, so an update refreshes the media tools along with the server.

PAYLOAD ONLY. The boot zip is read by the OS's own zip reader before anything else
runs, and a 73MB one failed outright with "ZipArchive error" — it is ~64KB and stays
that way.

Stored rather than compressed (the archive is -0 throughout) because they are gzipped
already: 3.2MB in the package against 6.7MB of tmpfs once unpacked.

They live in brightsign/media-tools/ and are excluded from the wholesale brightsign/
staging, or the package would carry both copies. A missing file is a hard error, not
a warning: both are tracked, so absence means someone removed them, and the symptom
would otherwise be a player that silently stops making video thumbnails.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kfhrUPit5MCqxeTQyqr56
This commit is contained in:
ScreenTinker 2026-08-18 20:21:36 -05:00
parent e2884c624d
commit 74d0ea3752
3 changed files with 30 additions and 2 deletions

Binary file not shown.

Binary file not shown.

View file

@ -84,7 +84,7 @@ mkdir -p "$STAGE/server"
# none of which the server reads at runtime.
for p in server frontend scripts docs shared brightsign VERSION package.json; do
git ls-files -z -- "$p" \
| grep -zZv -E '^server/(test|node_modules)/' \
| grep -zZv -E '^server/(test|node_modules)/|^brightsign/media-tools/' \
| while IFS= read -r -d '' f; do
mkdir -p "$STAGE/$(dirname "$f")"
cp "$f" "$STAGE/$f"
@ -99,6 +99,34 @@ cp brightsign/server/node-server.html "$STAGE/node-server.html"
cp brightsign/autozip.brs "$STAGE/autozip.brs"
fi
# ---------------------------------------------------------------------------------------------
# Media tools, at the top level as bin/ — where stageMediaTools() in bs-server-boot.js looks
# (path.join(__dirname, 'bin', ...), and the payload installs INTO __dirname).
#
# PAYLOAD ONLY, deliberately. The boot zip is read by the OS's own zip reader at boot and a 73MB one
# failed outright with "ZipArchive error"; it is ~64KB and stays that way. These ride with the
# payload instead, which also means an update refreshes them.
#
# Shipped gzipped and stored (-0) rather than compressed, because they are already compressed —
# 3.2MB here against 6.7MB unpacked, which is what /tmp pays at runtime.
#
# ⚠️ A hard error rather than a warning. Both files are tracked, so absence means someone removed
# them, and the failure it would otherwise produce is a player that silently stops making video
# thumbnails - exactly the silent degradation this whole path was built to end.
if [ "$PAYLOAD_ONLY" = 1 ]; then
echo " staging media tools..."
mkdir -p "$STAGE/bin"
for tool in ffprobe ffmpeg; do
src="brightsign/media-tools/$tool.gz"
if [ ! -f "$src" ]; then
echo "ERROR: $src is missing — the payload would ship without video thumbnails." >&2
exit 1
fi
cp "$src" "$STAGE/bin/$tool.gz"
echo " bin/$tool.gz ($(du -h "$src" | cut -f1))"
done
fi
# Point the server at the built-in driver. The shim is API-compatible, so no call site changes —
# this rewires the two places that construct a Database and drops the dependency entirely.
echo " switching to node:sqlite..."
@ -335,7 +363,7 @@ echo "$LISTING" | tail -1 | sed 's/^/ /'
REQUIRED="autorun.brs autozip.brs bs-server-boot.js node-server.html"
# The payload is verified on the thing the installer actually looks for before it commits the
# extraction. An archive that unpacks perfectly and lacks this is the failure worth catching here.
[ "$PAYLOAD_ONLY" = 1 ] && REQUIRED="server/server.js"
[ "$PAYLOAD_ONLY" = 1 ] && REQUIRED="server/server.js bin/ffprobe.gz bin/ffmpeg.gz"
for required in $REQUIRED; do
case "$LISTING" in
*" $required"*) ;;