Sweep/vgdeband: cap x264 at ENCODE_THREADS (2) so conversions stop starving Jellyfin and the live portal
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -408,8 +408,9 @@ Where the time comes from, best first:
|
|||||||
start and the sidecar records drift over the file. **Then the band is cropped off**: the sweep re-encodes the
|
start and the sidecar records drift over the file. **Then the band is cropped off**: the sweep re-encodes the
|
||||||
stream (libx264 CRF 18, frame timing preserved, audio copied) so the published file is the game image + audio +
|
stream (libx264 CRF 18, frame timing preserved, audio copied) so the published file is the game image + audio +
|
||||||
the `tmcd` track and nothing else; the raw with the band is deleted (`KEEP_RAW_STREAMS=1` keeps it in `.src/`).
|
the `tmcd` track and nothing else; the raw with the band is deleted (`KEEP_RAW_STREAMS=1` keeps it in `.src/`).
|
||||||
Streams without the band are remuxed losslessly. Cost: a 3 h 1440p60 night is a few hours of CPU on the
|
Streams without the band are remuxed losslessly. Cost: every re-encode (streams and clips) runs x264 on
|
||||||
E-2136; the sweep is niced. OBS: dock → *Timecode band* →
|
`ENCODE_THREADS` threads (2, set in `systemd/normalize-sweep.service`) so Jellyfin and live viewers stay
|
||||||
|
responsive; a 3 h 1440p60 night therefore takes most of the next day to publish. OBS: dock → *Timecode band* →
|
||||||
"Add band + clock source" (canvas grows by W/160 rows, a locked browser source `Vanguard Clock` →
|
"Add band + clock source" (canvas grows by W/160 rows, a locked browser source `Vanguard Clock` →
|
||||||
`https://live.BASE/dock/clock/` sits in the band; only while not streaming). Go Live: the "Timecode band" checkbox (default on).
|
`https://live.BASE/dock/clock/` sits in the band; only while not streaming). Go Live: the "Timecode band" checkbox (default on).
|
||||||
2. **Server arrival time** (no band) — microseconds in the recording filename. Within ~0.1–0.3 s per streamer
|
2. **Server arrival time** (no band) — microseconds in the recording filename. Within ~0.1–0.3 s per streamer
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ FILL_GAPS_MS="${FILL_GAPS_MS:-0}"
|
|||||||
# Band removal re-encodes every stream that carried the timecode band. The raw (with band) is deleted after a
|
# Band removal re-encodes every stream that carried the timecode band. The raw (with band) is deleted after a
|
||||||
# successful encode; KEEP_RAW_STREAMS=1 keeps it in the hidden .src/ instead (doubles disk per night).
|
# successful encode; KEEP_RAW_STREAMS=1 keeps it in the hidden .src/ instead (doubles disk per night).
|
||||||
KEEP_RAW_STREAMS="${KEEP_RAW_STREAMS:-0}"
|
KEEP_RAW_STREAMS="${KEEP_RAW_STREAMS:-0}"
|
||||||
|
# Encoder threads for every re-encode (clips and streams). 2 leaves the box responsive for Jellyfin/live viewers;
|
||||||
|
# conversions take longer. systemd Environment=ENCODE_THREADS=... to change.
|
||||||
|
ENCODE_THREADS="${ENCODE_THREADS:-2}"
|
||||||
MAX_W=2560; MAX_H=1440; MAX_FPS=60
|
MAX_W=2560; MAX_H=1440; MAX_FPS=60
|
||||||
exec 9>"${LOCK_FILE:-/run/lock/normalize-sweep.lock}"
|
exec 9>"${LOCK_FILE:-/run/lock/normalize-sweep.lock}"
|
||||||
flock -n 9 || exit 0
|
flock -n 9 || exit 0
|
||||||
@@ -166,7 +169,7 @@ PYEOF
|
|||||||
if (( live )) && [[ $reason != *audio=* ]]; then aargs=(-c:a copy); fi
|
if (( live )) && [[ $reason != *audio=* ]]; then aargs=(-c:a copy); fi
|
||||||
nice -n 15 ionice -c 3 ffmpeg -nostdin -hide_banner -loglevel error -y -i "$src" \
|
nice -n 15 ionice -c 3 ffmpeg -nostdin -hide_banner -loglevel error -y -i "$src" \
|
||||||
-map 0:v:0 -map '0:a?' \
|
-map 0:v:0 -map '0:a?' \
|
||||||
-c:v libx264 -preset veryfast -crf 18 -maxrate 30M -bufsize 60M -pix_fmt yuv420p -profile:v high \
|
-c:v libx264 -preset veryfast -crf 18 -maxrate 30M -bufsize 60M -pix_fmt yuv420p -profile:v high -threads "$ENCODE_THREADS" \
|
||||||
-vf "$vf" -fps_mode "$fpsmode" "${fpsargs[@]}" \
|
-vf "$vf" -fps_mode "$fpsmode" "${fpsargs[@]}" \
|
||||||
"${aargs[@]}" \
|
"${aargs[@]}" \
|
||||||
"${tcargs[@]}" -movflags +faststart -f mp4 "$tmp"
|
"${tcargs[@]}" -movflags +faststart -f mp4 "$tmp"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ print(d.get("source","none"), 1 if d.get("band_removed") else 0, d.get("timecode
|
|||||||
log "deband $f (${w}px wide -> crop ${band} rows; tc=$tc)"
|
log "deband $f (${w}px wide -> crop ${band} rows; tc=$tc)"
|
||||||
nice -n 15 ionice -c 3 ffmpeg -nostdin -hide_banner -loglevel error -y -i "$f" \
|
nice -n 15 ionice -c 3 ffmpeg -nostdin -hide_banner -loglevel error -y -i "$f" \
|
||||||
-map 0:v:0 -map '0:a?' \
|
-map 0:v:0 -map '0:a?' \
|
||||||
-c:v libx264 -preset veryfast -crf 18 -maxrate 30M -bufsize 60M -pix_fmt yuv420p -profile:v high \
|
-c:v libx264 -preset veryfast -crf 18 -maxrate 30M -bufsize 60M -pix_fmt yuv420p -profile:v high -threads "${ENCODE_THREADS:-2}" \
|
||||||
-vf "crop=iw:ih-${band}:0:0" -fps_mode passthrough -c:a copy \
|
-vf "crop=iw:ih-${band}:0:0" -fps_mode passthrough -c:a copy \
|
||||||
"${tcargs[@]}" -movflags +faststart -f mp4 "$tmp"
|
"${tcargs[@]}" -movflags +faststart -f mp4 "$tmp"
|
||||||
rc=$?; d1=$(dur "$f"); d2=$(dur "$tmp")
|
rc=$?; d1=$(dur "$f"); d2=$(dur "$tmp")
|
||||||
|
|||||||
@@ -8,4 +8,5 @@ Type=oneshot
|
|||||||
ExecStart=/usr/local/bin/normalize-sweep.sh
|
ExecStart=/usr/local/bin/normalize-sweep.sh
|
||||||
Nice=15
|
Nice=15
|
||||||
IOSchedulingClass=idle
|
IOSchedulingClass=idle
|
||||||
|
Environment=ENCODE_THREADS=2 # x264 threads per conversion; keeps Jellyfin and the live portal responsive (default 2)
|
||||||
# Environment=FILL_GAPS_MS=1000 # opt-in: CFR re-encode streams whose dropped-frame holes total >= 1 s (hours of CPU on this box)
|
# Environment=FILL_GAPS_MS=1000 # opt-in: CFR re-encode streams whose dropped-frame holes total >= 1 s (hours of CPU on this box)
|
||||||
|
|||||||
Reference in New Issue
Block a user