Streams published flat as <user>/<Title>__<ts>.mp4 so each recording is its own Jellyfin episode; plugin 0.1.3 parses the title from the name

Jellyfin merges several videos in one non-season folder into a single episode with versions,
which collapsed a night of helmet cams into one entry. Recording still lands in <Title>/.live/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 03:42:53 -05:00
parent d28c2335d0
commit e02accb855
6 changed files with 20 additions and 12 deletions

View File

@@ -6,8 +6,9 @@
# - anything else (HEVC, 10-bit, VFR, MKV, >1440p, >60fps): full-res re-encode -> name.mp4,
# raw source kept in a hidden .src/ subfolder next to it (Jellyfin/copyparty hide dot-dirs)
# - streams/<user>/<Title>/.live/<ts>.mp4 (MediaMTX writes here, hidden from Jellyfin/copyparty while live):
# when finished -> flat MP4 written to the parent folder, the .live source deleted. One copy, and nothing
# indexes a recording in progress.
# when finished -> flat MP4 published as streams/<user>/<Title>__<ts>.mp4 (one file per recording directly
# in the streamer's folder: Jellyfin would merge several files inside one title folder into ONE episode
# with "versions"), the .live source deleted, the empty title folder removed.
# - Syncthing folders (marker dir .stfolder in the folder root, receive-only): compliant files are left
# alone (zero copies); a non-compliant file is converted to name.mp4 (name.h264.mp4 if the raw is
# already .mp4), the raw's name is appended to .stlocal (an #include'd ignore list) so Syncthing
@@ -74,7 +75,8 @@ while IFS= read -r -d '' src; do
live=0
if [[ $(basename "$(dirname "$src")") == .live ]]; then
live=1
base="$(dirname "$(dirname "$src")")/$(basename "${src%.*}")"
titledir="$(dirname "$(dirname "$src")")" # streams/<user>/<Title>
base="$(dirname "$titledir")/$(basename "$titledir")__$(basename "${src%.*}")" # streams/<user>/<Title>__<ts>
fi
synced=0; stroot=""
d="$(dirname "$src")"
@@ -122,7 +124,7 @@ while IFS= read -r -d '' src; do
if (( rc == 0 )) && [[ -n $d1 && -n $d2 ]] && (( d2 >= d1 - 2 && d2 <= d1 + 2 )); then
if (( live )); then
mv -f "$tmp" "$out"; chown 1000:1000 "$out" 2>/dev/null
rm -f "$src"; rmdir "$(dirname "$src")" 2>/dev/null || true
rm -f "$src"; rmdir "$(dirname "$src")" "$titledir" 2>/dev/null || true # drop .live and the empty title folder
log "done $out"; continue
elif (( synced )); then
rel_src="${src#"$stroot"/}"; rel_out="${out#"$stroot"/}"