Add media-server auto-detection — pick Emby or Jellyfin by actual running state
This commit is contained in:
@@ -439,6 +439,9 @@ is_in_list() {
|
||||
# EMBY_CONTAINER ← HOST*_EMBY_CONTAINER
|
||||
# EMBY_URL ← HOST*_EMBY_URL
|
||||
# EMBY_API_KEY ← HOST*_EMBY_API_KEY
|
||||
# JELLYFIN_CONTAINER ← HOST*_JELLYFIN_CONTAINER
|
||||
# JELLYFIN_URL ← HOST*_JELLYFIN_URL
|
||||
# JELLYFIN_API_KEY ← HOST*_JELLYFIN_API_KEY
|
||||
# GITEA_API_TOKEN ← HOST*_GITEA_API_TOKEN
|
||||
#
|
||||
# Arr-specific vars set by detect_hosts() when needed by arr scripts:
|
||||
@@ -531,6 +534,13 @@ detect_hosts() {
|
||||
EMBY_API_KEY_VAR="${MY_ID}_EMBY_API_KEY"
|
||||
EMBY_API_KEY="${!EMBY_API_KEY_VAR:-}"
|
||||
|
||||
JELLYFIN_CONTAINER_VAR="${MY_ID}_JELLYFIN_CONTAINER"
|
||||
JELLYFIN_CONTAINER="${!JELLYFIN_CONTAINER_VAR:-}"
|
||||
JELLYFIN_URL_VAR="${MY_ID}_JELLYFIN_URL"
|
||||
JELLYFIN_URL="${!JELLYFIN_URL_VAR:-}"
|
||||
JELLYFIN_API_KEY_VAR="${MY_ID}_JELLYFIN_API_KEY"
|
||||
JELLYFIN_API_KEY="${!JELLYFIN_API_KEY_VAR:-}"
|
||||
|
||||
GITEA_API_TOKEN_VAR="${MY_ID}_GITEA_API_TOKEN"
|
||||
GITEA_API_TOKEN="${!GITEA_API_TOKEN_VAR:-}"
|
||||
|
||||
@@ -1363,6 +1373,77 @@ emby_api() {
|
||||
echo "$body"
|
||||
}
|
||||
|
||||
# ── Media Server Detection ────────────────────────────────────────────────────
|
||||
# Picks whichever media server is actually running right now, so callers don't have to
|
||||
# hardcode Emby or Jellyfin. Emby is preferred when both are up (it's the primary player on
|
||||
# every host; Jellyfin is mainly kept around for its working ffprobe binary — see
|
||||
# HOST*_FFPROBE_CONTAINER). Either container being merely *configured* in host*.conf doesn't
|
||||
# count — this checks Docker's actual running state, so a host with Jellyfin installed but
|
||||
# stopped correctly falls through to Emby (or to nothing, if neither is up).
|
||||
#
|
||||
# Requires detect_hosts() to have already run (needs EMBY_*/JELLYFIN_* aliases).
|
||||
# Sets: MEDIA_SERVER ("Emby"|"Jellyfin"|""), MEDIA_SERVER_URL, MEDIA_SERVER_API_KEY.
|
||||
# Returns 1 and leaves MEDIA_SERVER="" if neither configured container is running.
|
||||
# Usage: detect_media_server [docker_timeout_seconds]
|
||||
detect_media_server() {
|
||||
local docker_timeout="${1:-10}"
|
||||
MEDIA_SERVER="" MEDIA_SERVER_URL="" MEDIA_SERVER_API_KEY=""
|
||||
|
||||
local emby_up=false jellyfin_up=false
|
||||
|
||||
if [[ -n "${EMBY_CONTAINER:-}" ]]; then
|
||||
[[ "$(timeout "$docker_timeout" docker inspect -f '{{.State.Running}}' \
|
||||
"$EMBY_CONTAINER" 2>/dev/null)" == "true" ]] && emby_up=true
|
||||
fi
|
||||
if [[ -n "${JELLYFIN_CONTAINER:-}" ]]; then
|
||||
[[ "$(timeout "$docker_timeout" docker inspect -f '{{.State.Running}}' \
|
||||
"$JELLYFIN_CONTAINER" 2>/dev/null)" == "true" ]] && jellyfin_up=true
|
||||
fi
|
||||
|
||||
if [[ "$emby_up" == true && "$jellyfin_up" == true ]]; then
|
||||
log "Both Emby and Jellyfin are running — using Emby (primary)"
|
||||
elif [[ "$emby_up" == true ]]; then
|
||||
log "Emby is running, Jellyfin is not — using Emby"
|
||||
elif [[ "$jellyfin_up" == true ]]; then
|
||||
log "Jellyfin is running, Emby is not — using Jellyfin"
|
||||
else
|
||||
warn "Neither Emby nor Jellyfin is running — no media server available"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$emby_up" == true ]]; then
|
||||
MEDIA_SERVER="Emby"
|
||||
MEDIA_SERVER_URL="$EMBY_URL"
|
||||
MEDIA_SERVER_API_KEY="$EMBY_API_KEY"
|
||||
else
|
||||
MEDIA_SERVER="Jellyfin"
|
||||
MEDIA_SERVER_URL="$JELLYFIN_URL"
|
||||
MEDIA_SERVER_API_KEY="$JELLYFIN_API_KEY"
|
||||
fi
|
||||
}
|
||||
|
||||
# General REST call against whichever server detect_media_server() picked. Jellyfin accepts
|
||||
# the same X-Emby-Token header Emby uses (inherited from its Emby-fork lineage — confirmed
|
||||
# live 2026-07-19), so one call shape covers both backends.
|
||||
# Usage: detect_media_server && media_server_api <endpoint> [timeout_seconds]
|
||||
# Prints response body on 200; returns 1 on HTTP error, curl failure, or no server detected.
|
||||
media_server_api() {
|
||||
local endpoint="$1" max_time="${2:-30}"
|
||||
if [[ -z "${MEDIA_SERVER:-}" ]]; then
|
||||
error "media_server_api called with no MEDIA_SERVER set — call detect_media_server first"
|
||||
return 1
|
||||
fi
|
||||
local response http_code body
|
||||
response=$(curl -sf --max-time "$max_time" \
|
||||
-H "X-Emby-Token: $MEDIA_SERVER_API_KEY" \
|
||||
-w "\n%{http_code}" \
|
||||
"${MEDIA_SERVER_URL}/${endpoint}" 2>/dev/null)
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
body=$(echo "$response" | head -n -1)
|
||||
[[ "$http_code" != "200" ]] && { error "$MEDIA_SERVER API HTTP $http_code: $endpoint"; return 1; }
|
||||
echo "$body"
|
||||
}
|
||||
|
||||
# Stop containers on the REMOTE server via SSH.
|
||||
# Reads CRITICAL_CONTAINER_NAMES — set from profile arrays by rsync.sh.
|
||||
# Tracks running state in RUNNING_CONTAINERS for restart after sync.
|
||||
|
||||
Reference in New Issue
Block a user