Enhancement: Change default new client behind seconds from 2 to 5 for stability.

This commit is contained in:
SergeantPanda 2026-03-05 15:36:12 -06:00
parent badd552747
commit 78aa8cf353
8 changed files with 9 additions and 9 deletions

View file

@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Floating video player now displays the channel, stream, or VOD title in the player header bar. Title is passed through from all preview entry points: channel table, stream table, stream connection card, guide, DVR, recording cards, recording details modal, VOD modal, and series modal.
- New Client Buffer proxy setting: new clients joining an active channel are now positioned a configurable number of seconds behind live rather than a fixed chunk count. The start position is determined by wall-clock chunk receive time (stored as a Redis sorted set alongside the buffer), so the buffer depth is consistent in seconds regardless of stream bitrate. Setting the value to `0` starts clients at live with no buffer. Defaults to 2 seconds. Existing chunk-count gating for the first client connecting to a channel is unchanged. The setting is exposed in Settings → Proxy as "New Client Buffer (seconds)".
- New Client Buffer proxy setting: new clients joining an active channel are now positioned a configurable number of seconds behind live rather than a fixed chunk count. The start position is determined by wall-clock chunk receive time (stored as a Redis sorted set alongside the buffer), so the buffer depth is consistent in seconds regardless of stream bitrate. Setting the value to `0` starts clients at live with no buffer. Defaults to 5 seconds. Existing chunk-count gating for the first client connecting to a channel is unchanged. The setting is exposed in Settings → Proxy as "New Client Buffer (seconds)".
- Channel table filter for channels that have stale streams: A new "Has Stale Streams" filter option in the channel table header menu highlights and filters channels containing at least one stale stream. Channels with stale streams are visually distinguished with an orange tint. The filter is mutually exclusive with "Only Empty Channels". - Thanks [@JCBird1012](https://github.com/JCBird1012)
- DVR enhancements — Thanks [@CodeBormen](https://github.com/CodeBormen)
- **Stop Recording**: A new Stop button (distinct from Cancel) cleanly ends an in-progress recording early and keeps the partial file available for playback. The API returns immediately; stream teardown and task revocation happen in a background thread to prevent 504 timeouts. When multiple recordings run simultaneously, stopping one only terminates that recording's proxy client by ID, leaving all others unaffected. (Closes #454)

View file

@ -43,7 +43,7 @@ class BaseConfig:
"redis_chunk_ttl": 60,
"channel_shutdown_delay": 0,
"channel_init_grace_period": 5,
"new_client_behind_seconds": 2,
"new_client_behind_seconds": 5,
}
finally:
@ -82,7 +82,7 @@ class TSConfig(BaseConfig):
# Buffer settings
INITIAL_BEHIND_CHUNKS = 4 # How many chunks behind to start a client (4 chunks = ~1MB)
CHUNK_BATCH_SIZE = 5 # How many chunks to fetch in one batch
NEW_CLIENT_BEHIND_SECONDS = 2 # Start new clients this many seconds behind live (0 = start at live)
NEW_CLIENT_BEHIND_SECONDS = 5 # Start new clients this many seconds behind live (0 = start at live)
KEEPALIVE_INTERVAL = 0.5 # Seconds between keepalive packets when at buffer head
# Chunk read timeout
CHUNK_TIMEOUT = 5 # Seconds to wait for each chunk read

View file

@ -48,7 +48,7 @@ class ConfigHelper:
Loaded from DB proxy_settings so users can change it at runtime."""
from apps.proxy.config import TSConfig
settings = TSConfig.get_proxy_settings()
return settings.get('new_client_behind_seconds', 2)
return settings.get('new_client_behind_seconds', 5)
@staticmethod
def keepalive_interval():

View file

@ -183,7 +183,7 @@ class ProxySettingsViewSet(viewsets.ViewSet):
"redis_chunk_ttl": 60,
"channel_shutdown_delay": 0,
"channel_init_grace_period": 5,
"new_client_behind_seconds": 2,
"new_client_behind_seconds": 5,
}
settings_obj, created = CoreSettings.objects.get_or_create(
key=PROXY_SETTINGS_KEY,

View file

@ -329,7 +329,7 @@ class CoreSettings(models.Model):
"redis_chunk_ttl": 60,
"channel_shutdown_delay": 0,
"channel_init_grace_period": 5,
"new_client_behind_seconds": 2,
"new_client_behind_seconds": 5,
})
# System Settings

View file

@ -78,7 +78,7 @@ class ProxySettingsSerializer(serializers.Serializer):
redis_chunk_ttl = serializers.IntegerField(min_value=10, max_value=3600)
channel_shutdown_delay = serializers.IntegerField(min_value=0, max_value=300)
channel_init_grace_period = serializers.IntegerField(min_value=0, max_value=60)
new_client_behind_seconds = serializers.IntegerField(min_value=0, max_value=120, required=False, default=2)
new_client_behind_seconds = serializers.IntegerField(min_value=0, max_value=120, required=False, default=5)
def validate_buffering_timeout(self, value):
if value < 0 or value > 300:

View file

@ -14,6 +14,6 @@ export const getProxySettingDefaults = () => {
redis_chunk_ttl: 60,
channel_shutdown_delay: 0,
channel_init_grace_period: 5,
new_client_behind_seconds: 2,
new_client_behind_seconds: 5,
};
};

View file

@ -61,7 +61,7 @@ describe('ProxySettingsFormUtils', () => {
redis_chunk_ttl: 60,
channel_shutdown_delay: 0,
channel_init_grace_period: 5,
new_client_behind_seconds: 2,
new_client_behind_seconds: 5,
});
});