diff --git a/Transcodes/transcode_manager.sh b/Transcodes/transcode_manager.sh index 4bce747..02a91d4 100644 --- a/Transcodes/transcode_manager.sh +++ b/Transcodes/transcode_manager.sh @@ -19,8 +19,9 @@ # Permissions drift → fix silently # Emby not running → skip threshold checks, verify symlink only # -# Session display shows active Emby streams with per-session storage location — -# useful during flip events when sessions are split across ramdisk and SSD. +# Session display shows active Emby streams with storage state. +# Split state detected when sessions exist on both ramdisk and SSD simultaneously — +# this happens naturally when symlink flips mid-session. # # All configuration in Master.conf under Transcode Manager section. # Supports --dry-run and --status. @@ -147,7 +148,6 @@ increment_flip_count() { echo "$current_count" } -# Query Emby API emby_api() { local endpoint="$1" [[ -z "$EMBY_API_KEY" ]] && return 1 @@ -157,41 +157,19 @@ emby_api() { "${EMBY_URL}/${endpoint}" 2>/dev/null } -# Determine which storage location a session is using -# Handles both short hex IDs (live TV) and long UUID format (standard transcodes) -get_session_location() { - local session_id="$1" - local transcode_temp="transcoding-temp" - local short_id="${session_id:0:6}" # Emby uses short 6-char IDs for live TV sessions - - # Check ramdisk — exact match first, then short ID prefix match for live TV - if [[ -d "$RAMDISK_PATH/$transcode_temp/$session_id" ]] || \ - ls -d "$RAMDISK_PATH/$transcode_temp/${short_id}"* 2>/dev/null | grep -q .; then - echo "ramdisk" - # Check SSD — same pattern - elif [[ -d "$TRANSCODE_SSD/$transcode_temp/$session_id" ]] || \ - ls -d "$TRANSCODE_SSD/$transcode_temp/${short_id}"* 2>/dev/null | grep -q .; then - echo "ssd" - else - echo "unknown" - fi -} - -# Map Emby media type to readable label get_media_type_label() { local type="$1" case "$type" in LiveTv) echo "Live TV" ;; + TvChannel) echo "Live TV" ;; Episode) echo "TV Show" ;; Movie) echo "Movie" ;; Audio) echo "Music" ;; MusicVideo) echo "Music Video" ;; - TvChannel) echo "Live TV" ;; *) echo "$type" ;; esac } -# Map Emby play method to readable label get_play_method_label() { local method="$1" case "$method" in @@ -327,6 +305,11 @@ FLIP_COUNT=$(get_flip_count) echo "" echo "━━━ $ICON_EMBY Active Emby Sessions ━━━" +TOTAL_SESSIONS=0 +LIVE_TV=0 +TRANSCODING=0 +DIRECT=0 + if [[ -z "$EMBY_API_KEY" ]]; then info "EMBY_API_KEY not set in Master.conf — skipping session display" elif [[ "$EMBY_RUNNING" == false ]]; then @@ -341,46 +324,54 @@ else TOTAL_SESSIONS=$(echo "$SESSION_DATA" | \ jq '[.[] | select(.NowPlayingItem != null)] | length' 2>/dev/null || echo 0) LIVE_TV=$(echo "$SESSION_DATA" | \ - jq '[.[] | select(.NowPlayingItem != null) | select(.NowPlayingItem.Type == "LiveTv" or .NowPlayingItem.Type == "TvChannel")] | length' 2>/dev/null || echo 0) + jq '[.[] | select(.NowPlayingItem != null) | select(.NowPlayingItem.Type == "LiveTv" or .NowPlayingItem.Type == "TvChannel")] | length' \ + 2>/dev/null || echo 0) TRANSCODING=$(echo "$SESSION_DATA" | \ - jq '[.[] | select(.NowPlayingItem != null) | select(.TranscodingInfo != null)] | length' 2>/dev/null || echo 0) + jq '[.[] | select(.NowPlayingItem != null) | select(.PlayState.PlayMethod == "Transcode")] | length' \ + 2>/dev/null || echo 0) DIRECT=$(echo "$SESSION_DATA" | \ - jq '[.[] | select(.NowPlayingItem != null) | select(.TranscodingInfo == null)] | length' 2>/dev/null || echo 0) + jq '[.[] | select(.NowPlayingItem != null) | select(.PlayState.PlayMethod != "Transcode")] | length' \ + 2>/dev/null || echo 0) echo " $ICON_EMBY Total: $TOTAL_SESSIONS | $ICON_RAM Live TV: $LIVE_TV | $ICON_SYNC Transcoding: $TRANSCODING | $ICON_DONE Direct: $DIRECT" echo "" if [[ "$TOTAL_SESSIONS" -gt 0 ]]; then - # Parse each active session + + # Storage state — count session folders on each location + # Emby folder names don't match API session IDs — per-session location not possible + # Split state shows when symlink has flipped mid-session + TRANSCODE_TEMP="transcoding-temp" + RAM_SESSION_COUNT=$(find "$RAMDISK_PATH/$TRANSCODE_TEMP" \ + -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l) + SSD_SESSION_COUNT=$(find "$TRANSCODE_SSD/$TRANSCODE_TEMP" \ + -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l) + + if [[ "$RAM_SESSION_COUNT" -gt 0 && "$SSD_SESSION_COUNT" -gt 0 ]]; then + warn "$ICON_WARN Split state — $RAM_SESSION_COUNT folder(s) on ramdisk / $SSD_SESSION_COUNT on SSD" + warn "Older sessions remain on original location until they end naturally" + echo " $ICON_LINK Storage: $ICON_RAM ramdisk ($RAM_SESSION_COUNT) + $ICON_DISK SSD ($SSD_SESSION_COUNT)" + elif [[ "$RAM_SESSION_COUNT" -gt 0 ]]; then + echo " $ICON_LINK Storage: $ICON_RAM ramdisk" + elif [[ "$SSD_SESSION_COUNT" -gt 0 ]]; then + echo " $ICON_LINK Storage: $ICON_DISK SSD" + else + echo " $ICON_LINK Storage: $ICON_INFO no transcode folders found" + fi + + echo "" + + # List each active session while IFS= read -r session; do USER=$(echo "$session" | jq -r '.UserName // "Unknown"' 2>/dev/null) TITLE=$(echo "$session" | jq -r '.NowPlayingItem.Name // "Unknown"' 2>/dev/null) MEDIA_TYPE=$(echo "$session" | jq -r '.NowPlayingItem.Type // "Unknown"' 2>/dev/null) - SESSION_ID=$(echo "$session" | jq -r '.Id // ""' 2>/dev/null) - - # Play method - PLAY_METHOD=$(echo "$session" | \ - jq -r '.PlayState.PlayMethod // "Unknown"' 2>/dev/null) - # Check TranscodingInfo for more accurate method - HAS_TRANSCODE=$(echo "$session" | \ - jq '.TranscodingInfo != null' 2>/dev/null || echo "false") - [[ "$HAS_TRANSCODE" == "true" ]] && PLAY_METHOD="Transcode" + PLAY_METHOD=$(echo "$session" | jq -r '.PlayState.PlayMethod // "Unknown"' 2>/dev/null) MEDIA_LABEL=$(get_media_type_label "$MEDIA_TYPE") METHOD_LABEL=$(get_play_method_label "$PLAY_METHOD") - # Determine storage location for transcoding sessions - if [[ "$HAS_TRANSCODE" == "true" && -n "$SESSION_ID" ]]; then - LOCATION=$(get_session_location "$SESSION_ID") - case "$LOCATION" in - ramdisk) LOC_ICON="$ICON_RAM" LOC_LABEL="ramdisk" ;; - ssd) LOC_ICON="$ICON_DISK" LOC_LABEL="SSD" ;; - *) LOC_ICON="$ICON_INFO" LOC_LABEL="unknown" ;; - esac - echo " $ICON_EMBY $(printf '%-12s' "$USER") — $(printf '%-30s' "$TITLE") — $(printf '%-10s' "$MEDIA_LABEL") — $(printf '%-13s' "$METHOD_LABEL") — $LOC_ICON $LOC_LABEL" - else - echo " $ICON_EMBY $(printf '%-12s' "$USER") — $(printf '%-30s' "$TITLE") — $(printf '%-10s' "$MEDIA_LABEL") — $METHOD_LABEL" - fi + echo " $ICON_EMBY $(printf '%-12s' "$USER") — $(printf '%-30s' "$TITLE") — $(printf '%-10s' "$MEDIA_LABEL") — $METHOD_LABEL" done < <(echo "$SESSION_DATA" | \ jq -c '.[] | select(.NowPlayingItem != null)' 2>/dev/null) @@ -489,7 +480,7 @@ echo "$ICON_GEAR Mode: $TRANSCODE_MANAGER_MODE" echo "$ICON_RAM Ramdisk: ${RAMDISK_USED_GB}GB used / ${RAMDISK_AVAIL_GB}GB available" echo "$ICON_LINK Symlink: $TRANSCODE_LINK → $CURRENT_TARGET" echo "$ICON_LINK Flips: $FLIP_COUNT this hour (warn at $TRANSCODE_FLIP_WARN)" -echo "$ICON_EMBY Streams: ${TOTAL_SESSIONS:-0} total | Live TV: ${LIVE_TV:-0} | Transcoding: ${TRANSCODING:-0} | Direct: ${DIRECT:-0}" +echo "$ICON_EMBY Streams: ${TOTAL_SESSIONS} total | Live TV: ${LIVE_TV} | Transcoding: ${TRANSCODING} | Direct: ${DIRECT}" echo "$ICON_TIME Duration: $(format_duration $((END - START)))" echo "$ICON_DONE Status: $ICON_SUCCESS DONE" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file