From 78aa8cf35376131ed7243247040e4ed417b48cc5 Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Thu, 5 Mar 2026 15:36:12 -0600 Subject: [PATCH] Enhancement: Change default new client behind seconds from 2 to 5 for stability. --- CHANGELOG.md | 2 +- apps/proxy/config.py | 4 ++-- apps/proxy/ts_proxy/config_helper.py | 2 +- core/api_views.py | 2 +- core/models.py | 2 +- core/serializers.py | 2 +- frontend/src/utils/forms/settings/ProxySettingsFormUtils.js | 2 +- .../forms/settings/__tests__/ProxySettingsFormUtils.test.js | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15420a07..18195305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/apps/proxy/config.py b/apps/proxy/config.py index dbdd8278..68e27a6f 100644 --- a/apps/proxy/config.py +++ b/apps/proxy/config.py @@ -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 diff --git a/apps/proxy/ts_proxy/config_helper.py b/apps/proxy/ts_proxy/config_helper.py index f0f7a5b7..f9a0418e 100644 --- a/apps/proxy/ts_proxy/config_helper.py +++ b/apps/proxy/ts_proxy/config_helper.py @@ -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(): diff --git a/core/api_views.py b/core/api_views.py index 43e55d02..dd15886c 100644 --- a/core/api_views.py +++ b/core/api_views.py @@ -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, diff --git a/core/models.py b/core/models.py index 7ce7713d..4e6322e7 100644 --- a/core/models.py +++ b/core/models.py @@ -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 diff --git a/core/serializers.py b/core/serializers.py index b0b730ee..bff5f701 100644 --- a/core/serializers.py +++ b/core/serializers.py @@ -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: diff --git a/frontend/src/utils/forms/settings/ProxySettingsFormUtils.js b/frontend/src/utils/forms/settings/ProxySettingsFormUtils.js index e6e0464b..eddbba91 100644 --- a/frontend/src/utils/forms/settings/ProxySettingsFormUtils.js +++ b/frontend/src/utils/forms/settings/ProxySettingsFormUtils.js @@ -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, }; }; diff --git a/frontend/src/utils/forms/settings/__tests__/ProxySettingsFormUtils.test.js b/frontend/src/utils/forms/settings/__tests__/ProxySettingsFormUtils.test.js index a48e5a37..21c48269 100644 --- a/frontend/src/utils/forms/settings/__tests__/ProxySettingsFormUtils.test.js +++ b/frontend/src/utils/forms/settings/__tests__/ProxySettingsFormUtils.test.js @@ -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, }); });