Fix transcode session detection for Live TV and Direct Stream
HLS segments are written atomically so lsof never sees them as open. Cleanup now shows "Active" count (too-young files) which correctly reflects Live TV / Direct Stream segments. Manager session count now counts flat file prefixes in addition to subdirs.
This commit is contained in:
@@ -172,20 +172,24 @@ fi
|
|||||||
|
|
||||||
cleanup_location() {
|
cleanup_location() {
|
||||||
local location="$1" label="$2" max_age="$3"
|
local location="$1" label="$2" max_age="$3"
|
||||||
local files_removed=0 bytes_freed=0 files_skipped=0 files_active=0 files_streaming=0
|
local files_removed=0 bytes_freed=0 files_skipped=0 files_active=0 files_streaming=0 files_too_young=0
|
||||||
|
|
||||||
if [[ ! -d "$location" ]]; then
|
if [[ ! -d "$location" ]]; then
|
||||||
log "$label does not exist — skipping"
|
log "$label does not exist — skipping"
|
||||||
LOCATION_REMOVED=0 LOCATION_FREED="0B" LOCATION_SKIPPED=0 LOCATION_ACTIVE=0 LOCATION_STREAMING=0
|
LOCATION_REMOVED=0 LOCATION_FREED="0B" LOCATION_SKIPPED=0 LOCATION_ACTIVE=0 LOCATION_STREAMING=0 LOCATION_TOO_YOUNG=0
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local file_count
|
local file_count eligible_count
|
||||||
file_count=$(find "$location" -type f 2>/dev/null | wc -l)
|
file_count=$(find "$location" -type f 2>/dev/null | wc -l)
|
||||||
log "$label: $file_count files to scan (age threshold: ${max_age}min)"
|
eligible_count=$(find "$location" -type f -mmin +"$max_age" 2>/dev/null | wc -l)
|
||||||
|
files_too_young=$(( file_count - eligible_count ))
|
||||||
|
log "$label: $file_count files ($eligible_count eligible, $files_too_young < ${max_age}min)"
|
||||||
|
|
||||||
# Build in-memory open file map — O(1) lookup per file
|
# Build in-memory open file map — O(1) lookup per file
|
||||||
# One lsof call per location — never per file
|
# One lsof call per location — never per file
|
||||||
|
# Note: HLS/remux segments (Live TV, Direct Stream) are written atomically and immediately
|
||||||
|
# closed — lsof will not detect them. The age check is the effective guard for those files.
|
||||||
declare -A OPEN_FILES_MAP
|
declare -A OPEN_FILES_MAP
|
||||||
if [[ "$LSOF_AVAILABLE" == true ]]; then
|
if [[ "$LSOF_AVAILABLE" == true ]]; then
|
||||||
log "Building open file map for $label..."
|
log "Building open file map for $label..."
|
||||||
@@ -245,20 +249,21 @@ cleanup_location() {
|
|||||||
freed_human="0B"
|
freed_human="0B"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "$label — removed $files_removed files ($freed_human freed) | streaming: $files_streaming | aged+open: $files_active | skipped: $files_skipped"
|
log "$label — removed $files_removed ($freed_human) | active(fresh): $files_too_young | streaming(lsof): $files_streaming | protected(old+open): $files_active | skipped: $files_skipped"
|
||||||
|
|
||||||
LOCATION_REMOVED=$files_removed
|
LOCATION_REMOVED=$files_removed
|
||||||
LOCATION_FREED=$freed_human
|
LOCATION_FREED=$freed_human
|
||||||
LOCATION_SKIPPED=$files_skipped
|
LOCATION_SKIPPED=$files_skipped
|
||||||
LOCATION_ACTIVE=$files_active
|
LOCATION_ACTIVE=$files_active
|
||||||
LOCATION_STREAMING=$files_streaming
|
LOCATION_STREAMING=$files_streaming
|
||||||
|
LOCATION_TOO_YOUNG=$files_too_young
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# ━━━ Transcode Cleanup ━━━
|
# ━━━ Transcode Cleanup ━━━
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
START=$(date +%s)
|
START=$(date +%s)
|
||||||
TOTAL_REMOVED=0 TOTAL_SKIPPED=0 TOTAL_ACTIVE=0 TOTAL_STREAMING=0
|
TOTAL_REMOVED=0 TOTAL_SKIPPED=0 TOTAL_ACTIVE=0 TOTAL_STREAMING=0 TOTAL_TOO_YOUNG=0
|
||||||
RAMDISK_FREED="0B" SSD_FREED="0B"
|
RAMDISK_FREED="0B" SSD_FREED="0B"
|
||||||
|
|
||||||
# Cleanup ramdisk
|
# Cleanup ramdisk
|
||||||
@@ -268,6 +273,7 @@ if mountpoint -q "$RAMDISK_PATH" 2>/dev/null; then
|
|||||||
TOTAL_SKIPPED=$(( TOTAL_SKIPPED + LOCATION_SKIPPED ))
|
TOTAL_SKIPPED=$(( TOTAL_SKIPPED + LOCATION_SKIPPED ))
|
||||||
TOTAL_ACTIVE=$(( TOTAL_ACTIVE + LOCATION_ACTIVE ))
|
TOTAL_ACTIVE=$(( TOTAL_ACTIVE + LOCATION_ACTIVE ))
|
||||||
TOTAL_STREAMING=$(( TOTAL_STREAMING + LOCATION_STREAMING ))
|
TOTAL_STREAMING=$(( TOTAL_STREAMING + LOCATION_STREAMING ))
|
||||||
|
TOTAL_TOO_YOUNG=$(( TOTAL_TOO_YOUNG + LOCATION_TOO_YOUNG ))
|
||||||
RAMDISK_FREED=$LOCATION_FREED
|
RAMDISK_FREED=$LOCATION_FREED
|
||||||
else
|
else
|
||||||
log "Ramdisk not mounted — skipping ramdisk cleanup"
|
log "Ramdisk not mounted — skipping ramdisk cleanup"
|
||||||
@@ -280,6 +286,7 @@ if [[ -d "$TRANSCODE_SSD" ]]; then
|
|||||||
TOTAL_SKIPPED=$(( TOTAL_SKIPPED + LOCATION_SKIPPED ))
|
TOTAL_SKIPPED=$(( TOTAL_SKIPPED + LOCATION_SKIPPED ))
|
||||||
TOTAL_ACTIVE=$(( TOTAL_ACTIVE + LOCATION_ACTIVE ))
|
TOTAL_ACTIVE=$(( TOTAL_ACTIVE + LOCATION_ACTIVE ))
|
||||||
TOTAL_STREAMING=$(( TOTAL_STREAMING + LOCATION_STREAMING ))
|
TOTAL_STREAMING=$(( TOTAL_STREAMING + LOCATION_STREAMING ))
|
||||||
|
TOTAL_TOO_YOUNG=$(( TOTAL_TOO_YOUNG + LOCATION_TOO_YOUNG ))
|
||||||
SSD_FREED=$LOCATION_FREED
|
SSD_FREED=$LOCATION_FREED
|
||||||
else
|
else
|
||||||
log "SSD fallback not found — skipping SSD cleanup"
|
log "SSD fallback not found — skipping SSD cleanup"
|
||||||
@@ -308,7 +315,8 @@ echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
|||||||
echo "$ICON_RAM Ramdisk freed: $RAMDISK_FREED"
|
echo "$ICON_RAM Ramdisk freed: $RAMDISK_FREED"
|
||||||
echo "$ICON_DISK SSD freed: $SSD_FREED"
|
echo "$ICON_DISK SSD freed: $SSD_FREED"
|
||||||
echo "$ICON_TRASH Removed: $TOTAL_REMOVED files"
|
echo "$ICON_TRASH Removed: $TOTAL_REMOVED files"
|
||||||
echo "$ICON_RUNNING Streaming: $TOTAL_STREAMING files (open by Emby — untouched)"
|
echo "$ICON_RUNNING Active: $TOTAL_TOO_YOUNG files (< ${TRANSCODE_MAX_AGE}min old — Live TV / Direct Stream segments)"
|
||||||
|
echo "$ICON_RUNNING Streaming: $TOTAL_STREAMING files (open file handle — long-running transcode)"
|
||||||
echo "$ICON_SHIELD Protected: $TOTAL_ACTIVE aged files saved by open-file check"
|
echo "$ICON_SHIELD Protected: $TOTAL_ACTIVE aged files saved by open-file check"
|
||||||
echo "$ICON_TRASH Skipped: $TOTAL_SKIPPED files"
|
echo "$ICON_TRASH Skipped: $TOTAL_SKIPPED files"
|
||||||
echo "$ICON_TIME Duration: $(format_duration $(( END - START )))"
|
echo "$ICON_TIME Duration: $(format_duration $(( END - START )))"
|
||||||
|
|||||||
@@ -501,22 +501,31 @@ for server_entry in "${TRANSCODE_SERVERS[@]}"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Storage state
|
# Storage state
|
||||||
RAM_SESSION_COUNT=$(find "$RAMDISK_PATH/transcoding-temp" \
|
# Sessions may use subdirectories (legacy transcode) or flat files (Live TV / Direct Stream HLS).
|
||||||
-mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
|
# Count both: subdirs per-session, and unique hex session ID prefixes for flat files.
|
||||||
SSD_SESSION_COUNT=$(find "$TRANSCODE_SSD/transcoding-temp" \
|
_count_sessions() {
|
||||||
-mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
|
local base="$1/transcoding-temp"
|
||||||
|
local _dirs _flat
|
||||||
|
_dirs=$(find "$base" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
|
||||||
|
_flat=$(find "$base" -maxdepth 1 -type f -printf '%f\n' 2>/dev/null | \
|
||||||
|
grep -oE '^[0-9a-f]{16,}' | sort -u | wc -l)
|
||||||
|
echo $(( _dirs + _flat ))
|
||||||
|
}
|
||||||
|
RAM_SESSION_COUNT=$(_count_sessions "$RAMDISK_PATH")
|
||||||
|
SSD_SESSION_COUNT=$(_count_sessions "$TRANSCODE_SSD")
|
||||||
|
unset -f _count_sessions
|
||||||
|
|
||||||
if [[ "$TOTAL_SESSIONS" -gt 0 ]]; then
|
if [[ "$TOTAL_SESSIONS" -gt 0 ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo " $ICON_EMBY Total: $TOTAL_SESSIONS | Live TV: $LIVE_TV | Transcoding: $TRANSCODING | Direct: $DIRECT"
|
echo " $ICON_EMBY Total: $TOTAL_SESSIONS | Live TV: $LIVE_TV | Transcoding: $TRANSCODING | Direct: $DIRECT"
|
||||||
|
|
||||||
if [[ "$RAM_SESSION_COUNT" -gt 0 && "$SSD_SESSION_COUNT" -gt 0 ]]; then
|
if [[ "$RAM_SESSION_COUNT" -gt 0 && "$SSD_SESSION_COUNT" -gt 0 ]]; then
|
||||||
warn "Split state — $RAM_SESSION_COUNT folder(s) ramdisk / $SSD_SESSION_COUNT SSD"
|
warn "Split state — $RAM_SESSION_COUNT session(s) ramdisk / $SSD_SESSION_COUNT SSD"
|
||||||
warn "Older sessions remain on original location until they end naturally"
|
warn "Older sessions remain on original location until they end naturally"
|
||||||
elif [[ "$RAM_SESSION_COUNT" -gt 0 ]]; then
|
elif [[ "$RAM_SESSION_COUNT" -gt 0 ]]; then
|
||||||
log "Storage: ramdisk ($RAM_SESSION_COUNT sessions)"
|
log "Storage: ramdisk ($RAM_SESSION_COUNT session(s))"
|
||||||
elif [[ "$SSD_SESSION_COUNT" -gt 0 ]]; then
|
elif [[ "$SSD_SESSION_COUNT" -gt 0 ]]; then
|
||||||
log "Storage: SSD ($SSD_SESSION_COUNT sessions)"
|
log "Storage: SSD ($SSD_SESSION_COUNT session(s))"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user