Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ class Settings(BaseSettings):
# and trigger existing failover/reconnect logic instead of hanging.
LIVE_CHUNK_TIMEOUT_SECONDS: float = 15.0

# Maximum failover attempts before giving up on a stream.
# Set to 0 to try all configured failover URLs (no limit).
# Default: 0 (try every failover URL before giving up)
MAX_FAILOVER_ATTEMPTS: int = 0

# Stream Retry Configuration (similar to iptv-proxy)
# These settings control retry behavior for temporary connection issues before
# attempting failover or giving up entirely. Retries help handle brief network
Expand Down
23 changes: 21 additions & 2 deletions src/stream_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1274,7 +1274,16 @@ async def generate():
last_stats_update = 0 # Track bytes at last stats update
vod_reconnects = 0
failover_count = 0
max_failovers = 3
# Use configured max or fall back to total available failovers (0 = unlimited)
configured_max = settings.MAX_FAILOVER_ATTEMPTS
if configured_max > 0:
max_failovers = configured_max
elif stream_info.failover_urls:
max_failovers = len(stream_info.failover_urls)
elif stream_info.failover_resolver_url:
max_failovers = 999 # Resolver-based: let the resolver decide when to stop
else:
max_failovers = 3 # No failovers configured, keep original default
max_vod_reconnects = 5
# Flag: upstream finished serving this range naturally (not a client disconnect/error)
# Used to skip immediate client removal for VOD, since clients may seek again
Expand Down Expand Up @@ -2884,7 +2893,16 @@ async def generate():
stream_key = None
bytes_served = 0
failover_count = 0
max_failovers = 3
# Use configured max or fall back to total available failovers (0 = unlimited)
configured_max = settings.MAX_FAILOVER_ATTEMPTS
if configured_max > 0:
max_failovers = configured_max
elif stream_info.failover_urls:
max_failovers = len(stream_info.failover_urls)
elif stream_info.failover_resolver_url:
max_failovers = 999 # Resolver-based: let the resolver decide when to stop
else:
max_failovers = 3 # No failovers configured, keep original default
is_failover = False # Track if we broke due to failover

# Main loop with automatic reconnection on failover
Expand Down Expand Up @@ -3141,6 +3159,7 @@ async def generate():
await self._try_update_failover_url(
stream_id, "transcode_runtime_input_error"
)
is_failover = True # Keep client connection alive during failover
failover_count += 1
break
else:
Expand Down
Loading