media: H.264 fallback beside every AV1, and the post links the H.264
All checks were successful
Deploy / build-deploy (push) Successful in 7m30s

The AV1-only publish lasted four hours in the wild: the first viewer on
mobile Safari got "bad media error" from the raw file, because a post's
link is fetched raw — Lemmy apps and browsers play that exact URL, with
no <source> negotiation in front of it. The previous commit's note
("--raw ... if that audience matters") had it backwards: the audience
that cannot play AV1 is not a per-post judgement call, it is whoever
happens to open the thread on an iPhone.

So publish-media.sh now emits two encodings and points the post at the
compatible one:

  * Every video transcode also produces <hash>.h264.mp4 (x264 crf 23,
    same denoise, same frames), uploaded beside the AV1 under the AV1's
    hash — the poster's sibling-naming trick, reused, so fetch-media.sh
    finds it by name with nothing to look up.
  * The printed URL to paste into the post is the H.264 one. pict-rs
    can thumbnail it too, so instance thumbnails come back as a bonus.

fetch-media.sh adopting an own-origin .h264.mp4 URL swaps the AV1 back
in as the page's primary when it is on the mount, and records the H.264
as `fallback` in posts.json. The renderer turns a non-empty fallback
into a <source> pair: the AV1 first with an explicit codecs parameter —
both files are video/mp4, so the parameter is the only thing that lets
a non-AV1 browser skip to the file it can play — and the H.264 second.
Browsers with AV1 keep downloading the small file; Safari before 17
gets one that plays instead of an element that will not.

e2e gains the matching conditional gate: a page offering an av01
<source> must offer an .h264.mp4 one, so an AV1 video can never again
ship without its fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-08-08 03:14:51 +02:00
commit a625176c7d
6 changed files with 142 additions and 25 deletions

View file

@ -97,9 +97,11 @@ probe_dims() {
MAP="$(mktemp)"
POSTERMAP="$(mktemp)"
trap 'rm -f "$MAP" "$POSTERMAP"' EXIT
FALLBACKMAP="$(mktemp)"
trap 'rm -f "$MAP" "$POSTERMAP" "$FALLBACKMAP"' EXIT
printf '[]' > "$MAP"
printf '[]' > "$POSTERMAP"
printf '[]' > "$FALLBACKMAP"
downloaded=0
reused=0
@ -132,6 +134,17 @@ while IFS= read -r src; do
echo "fetch-media: refusing suspicious own-origin URL: $src" >&2
failed=$((failed + 1)); continue ;;
esac
# A .h264.mp4 URL is the fediverse-facing form of an AV1 video: the
# post links the encoding everything can play, because that link is
# fetched raw by Lemmy apps. Our page can negotiate, so when the AV1
# sibling is on the mount it becomes the primary <source> and the
# H.264 drops to the fallback (picked up by name below).
case "$name" in
*.h264.mp4)
av1="${name%.h264.mp4}.mp4"
[ -f "$MEDIA_DIR/$av1" ] && name="$av1"
;;
esac
dest="$MEDIA_DIR/$name"
if [ ! -f "$dest" ]; then
echo "fetch-media: $name not on the media mount, keeping original URL: $src" >&2
@ -189,12 +202,29 @@ while IFS= read -r src; do
# box until someone presses play.
case "$name" in
*.mp4|*.webm|*.mov)
sibling="${name%.*}.poster.webp"
# Siblings are named after the AV1's hash, so strip the .h264
# marker too — a video adopted as X.h264.mp4 (its AV1 never
# published) still finds X.poster.webp.
base="${name%.*}"
base="${base%.h264}"
sibling="$base.poster.webp"
if [ -f "$MEDIA_DIR/$sibling" ]; then
jq --arg k "/media/$name" --arg v "/media/$sibling" \
'. + [{key: $k, value: $v}]' "$POSTERMAP" > "$POSTERMAP.new" \
&& mv "$POSTERMAP.new" "$POSTERMAP"
fi
# The H.264 sibling publish-media.sh uploaded next to the AV1.
# Rendered as a second <source> so browsers without AV1 (Safari
# before 17, Apple hardware without the decoder) get a file they
# can play instead of an element that will not. The guard against
# naming itself covers a video adopted as X.h264.mp4 whose AV1 is
# not on the mount.
fb="$base.h264.mp4"
if [ "$fb" != "$name" ] && [ -f "$MEDIA_DIR/$fb" ]; then
jq --arg k "/media/$name" --arg v "/media/$fb" \
'. + [{key: $k, value: $v}]' "$FALLBACKMAP" > "$FALLBACKMAP.new" \
&& mv "$FALLBACKMAP.new" "$FALLBACKMAP"
fi
;;
esac
@ -212,9 +242,11 @@ echo "fetch-media: $downloaded new, $reused already present, $adopted self-hoste
# failed) keeps its original src, so the page still shows something rather than
# silently dropping the post's whole point.
TMP_POSTS="$(mktemp)"
if jq --slurpfile map "$MAP" --slurpfile posters "$POSTERMAP" '
if jq --slurpfile map "$MAP" --slurpfile posters "$POSTERMAP" \
--slurpfile fallbacks "$FALLBACKMAP" '
($map[0] | map({key: .src, value: .}) | from_entries) as $m
| ($posters[0] | from_entries) as $pm
| ($fallbacks[0] | from_entries) as $fm
| map(.media = ((.media // []) | map(
. as $item
| ($m[$item.src] // null) as $hit
@ -233,6 +265,12 @@ if jq --slurpfile map "$MAP" --slurpfile posters "$POSTERMAP" '
# empty — a thumbnail the instance did provide always wins.
| if ((.poster // "") == "") and (($pm[.src] // "") != "")
then . + { poster: $pm[.src] }
else . end
# H.264 fallback, keyed by the LOCAL src like the poster map. Only ever
# set for media on our own mount — a mirrored third-party file has no
# sibling to find.
| if (($fm[.src] // "") != "")
then . + { fallback: $fm[.src] }
else . end)))
' "$POSTS" > "$TMP_POSTS" 2>/dev/null; then
# Same reason as the chmod on each mirrored file: mktemp is 0600 and the