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
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:
parent
c21aa636aa
commit
a625176c7d
6 changed files with 142 additions and 25 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue