This commit is contained in:
parent
593bdb17d4
commit
faf881fa0c
10 changed files with 201 additions and 8 deletions
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
# Publish a recording or screenshot to catcrafts.net and print the URL to put in
|
||||
# the fediverse post.
|
||||
# Publish a recording, screenshot or audio file to catcrafts.net and print the
|
||||
# URL to put in the fediverse post.
|
||||
#
|
||||
# usage: tools/publish-media.sh [-r] [-c CRF] <file>...
|
||||
#
|
||||
|
|
@ -40,6 +40,24 @@
|
|||
# with no <source> negotiation in front of it — and it must be the encoding
|
||||
# everything can play. Our own pages recognise the .h264.mp4 name, serve the AV1
|
||||
# to browsers that can take it, and keep the H.264 as the <source> fallback.
|
||||
#
|
||||
# AUDIO: the same two rails, for the same reason. Opus in WebM is the efficient
|
||||
# one — the first file through here, 93 s of speech, went from a 1.5 MB 128k MP3
|
||||
# to 553 KB — and an MP3 sibling is the one that plays everywhere, so the MP3 is
|
||||
# the URL printed for the post. The primary does not have to be universal
|
||||
# precisely because the sibling is.
|
||||
#
|
||||
# Two ways the audio path deliberately differs from the video path above. It does
|
||||
# not fold everything to mono: here the audio IS the content rather than a
|
||||
# rounding error next to a picture, so the source's channel layout survives and
|
||||
# sets the bitrate. And a source that is ALREADY an MP3 is copied to the
|
||||
# compatibility rail untouched rather than re-encoded — MP3 to MP3 spends a
|
||||
# second generation of lossy artefacts to arrive at the same rail, and speech,
|
||||
# which is most of what gets published here, is where that is most audible.
|
||||
#
|
||||
# Nothing downstream builds an <audio> element yet: fetch-media.sh does not match
|
||||
# these names and the post renderer has no audio case. So the printed URL is for
|
||||
# posting and for linking by hand, not yet for embedding in a post body.
|
||||
|
||||
set -eu
|
||||
|
||||
|
|
@ -116,10 +134,12 @@ for src in $FILES; do
|
|||
case "$ext" in
|
||||
mp4|webm|mov|mkv|avi) kind=video ;;
|
||||
png|jpg|jpeg|webp|gif|avif) kind=image ;;
|
||||
mp3|m4a|aac|opus|oga|ogg|flac|wav|wma|aiff) kind=audio ;;
|
||||
esac
|
||||
|
||||
poster=""
|
||||
fallback=""
|
||||
fallback_suffix=""
|
||||
if [ "$RAW" = 1 ] || [ "$kind" = other ]; then
|
||||
payload="$src"
|
||||
out_ext="$ext"
|
||||
|
|
@ -137,6 +157,7 @@ for src in $FILES; do
|
|||
# the players most likely to be shaky about AV1 anyway, and the audio is
|
||||
# a rounding error next to the video either way.
|
||||
fallback="$WORK/h264.mp4"
|
||||
fallback_suffix=h264.mp4
|
||||
echo " transcoding H.264 fallback (crf 23)…"
|
||||
# Same source and same denoise as the AV1, so the two encodings show the
|
||||
# same frames. CRF is x264's own scale (not comparable to SVT-AV1's);
|
||||
|
|
@ -156,6 +177,42 @@ for src in $FILES; do
|
|||
at=$(awk -v d="$dur" 'BEGIN { printf "%.2f", (d > 3 ? d / 3 : 0) }')
|
||||
ffmpeg -nostdin -v error -ss "$at" -i "$payload" -frames:v 1 \
|
||||
-vf "scale=720:-2" -c:v libwebp -quality 80 "$poster" -y
|
||||
elif [ "$kind" = audio ]; then
|
||||
payload="$WORK/out.webm"
|
||||
out_ext=webm
|
||||
fallback_suffix=mp3
|
||||
# Channel count sets the bitrate instead of being flattened by it: 48k of
|
||||
# mono Opus is comfortable for speech, and stereo music at that figure
|
||||
# would not be. These are VBR targets, not ceilings, and libopus does not
|
||||
# track them evenly — on the first file through here the 48k target came
|
||||
# out at 45 kbps while 64k ran away to 76, which is why the mono rail sits
|
||||
# at the lower figure rather than splitting the difference.
|
||||
ch=$(ffprobe -v error -select_streams a:0 -show_entries stream=channels \
|
||||
-of default=nw=1:nk=1 "$src" </dev/null 2>/dev/null \
|
||||
| head -n1 || true)
|
||||
case "$ch" in ''|*[!0-9]*) ch=1 ;; esac
|
||||
if [ "$ch" -gt 1 ]; then ab=96k; else ab=48k; fi
|
||||
echo " transcoding to Opus ($ab, ${ch}ch)…"
|
||||
# -vn drops cover art, which arrives as a still video stream and belongs
|
||||
# in neither output — without it an MP3 carrying album art fails the
|
||||
# encode outright. -map_metadata -1 drops the ID3 tags, which on a file
|
||||
# from someone else carry their tooling and their file naming. 48 kHz is
|
||||
# the rate Opus works at internally, so saying it makes the resample of
|
||||
# the usual 44.1 kHz source explicit rather than implied.
|
||||
ffmpeg -nostdin -v error -i "$src" -vn -map_metadata -1 \
|
||||
-c:a libopus -b:a "$ab" -ar 48000 \
|
||||
"$payload" -y
|
||||
fallback="$WORK/fallback.mp3"
|
||||
if [ "$ext" = mp3 ]; then
|
||||
echo " MP3 fallback: source is already MP3, copied unchanged"
|
||||
cp "$src" "$fallback"
|
||||
else
|
||||
echo " transcoding MP3 fallback (128k)…"
|
||||
# Fixed 128k, decodable by anything, and the same "bigger is
|
||||
# acceptable on the compatibility rail" trade the H.264 above makes.
|
||||
ffmpeg -nostdin -v error -i "$src" -vn -map_metadata -1 \
|
||||
-c:a libmp3lame -b:a 128k "$fallback" -y
|
||||
fi
|
||||
else
|
||||
payload="$WORK/out.webp"
|
||||
out_ext=webp
|
||||
|
|
@ -171,17 +228,19 @@ for src in $FILES; do
|
|||
# their own. That is the whole point: fetch-media.sh finds both by name,
|
||||
# with nothing to look up — the poster when the instance made no thumbnail
|
||||
# (pict-rs will not read AV1, so for these uploads that is the normal
|
||||
# case), the fallback for every browser that cannot decode AV1.
|
||||
# case), the fallback for every browser that cannot decode AV1. Audio's MP3
|
||||
# sibling is named the same way, after the Opus file's hash.
|
||||
if [ -n "$poster" ] && [ -f "$poster" ]; then
|
||||
publish_file "$poster" "$hash.poster.webp"
|
||||
fi
|
||||
post_name="$name"
|
||||
if [ -n "$fallback" ] && [ -f "$fallback" ]; then
|
||||
post_name="$hash.h264.mp4"
|
||||
post_name="$hash.$fallback_suffix"
|
||||
publish_file "$fallback" "$post_name"
|
||||
fi
|
||||
|
||||
# The postable URL is the H.264 one when it exists — see FALLBACK above.
|
||||
# The postable URL is the compatibility rail when there is one: the H.264
|
||||
# video or the MP3 audio — see FALLBACK and AUDIO above.
|
||||
url="$SITE_ORIGIN/media/$post_name"
|
||||
# Confirm it is actually being served before handing over a URL that is about
|
||||
# to be pasted into a post, where a 404 is public and permanent.
|
||||
|
|
|
|||
Loading…
Reference in a new issue