Compare commits
2 Commits
d46ccc8245
...
f6628b9302
| Author | SHA1 | Date | |
|---|---|---|---|
|
f6628b9302
|
|||
|
7484a11535
|
@@ -51,6 +51,7 @@
|
|||||||
SERVICE_BUFFER = "5000000"; # 5 Mbps reserved for other services (bps)
|
SERVICE_BUFFER = "5000000"; # 5 Mbps reserved for other services (bps)
|
||||||
DEFAULT_STREAM_BITRATE = "10000000"; # 10 Mbps fallback when bitrate unknown (bps)
|
DEFAULT_STREAM_BITRATE = "10000000"; # 10 Mbps fallback when bitrate unknown (bps)
|
||||||
MIN_TORRENT_SPEED = "100"; # KB/s - below this, pause torrents instead
|
MIN_TORRENT_SPEED = "100"; # KB/s - below this, pause torrents instead
|
||||||
|
STREAM_BITRATE_HEADROOM = "1.1"; # multiplier per stream for bitrate fluctuations
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class JellyfinQBittorrentMonitor:
|
|||||||
service_buffer=5000000,
|
service_buffer=5000000,
|
||||||
default_stream_bitrate=10000000,
|
default_stream_bitrate=10000000,
|
||||||
min_torrent_speed=100,
|
min_torrent_speed=100,
|
||||||
|
stream_bitrate_headroom=1.1,
|
||||||
):
|
):
|
||||||
self.jellyfin_url = jellyfin_url
|
self.jellyfin_url = jellyfin_url
|
||||||
self.qbittorrent_url = qbittorrent_url
|
self.qbittorrent_url = qbittorrent_url
|
||||||
@@ -42,6 +43,7 @@ class JellyfinQBittorrentMonitor:
|
|||||||
self.service_buffer = service_buffer
|
self.service_buffer = service_buffer
|
||||||
self.default_stream_bitrate = default_stream_bitrate
|
self.default_stream_bitrate = default_stream_bitrate
|
||||||
self.min_torrent_speed = min_torrent_speed
|
self.min_torrent_speed = min_torrent_speed
|
||||||
|
self.stream_bitrate_headroom = stream_bitrate_headroom
|
||||||
self.last_streaming_state = None
|
self.last_streaming_state = None
|
||||||
self.current_state = "unlimited"
|
self.current_state = "unlimited"
|
||||||
self.torrents_paused = False
|
self.torrents_paused = False
|
||||||
@@ -124,6 +126,8 @@ class JellyfinQBittorrentMonitor:
|
|||||||
bitrate = self.default_stream_bitrate
|
bitrate = self.default_stream_bitrate
|
||||||
|
|
||||||
bitrate = min(int(bitrate), 100_000_000)
|
bitrate = min(int(bitrate), 100_000_000)
|
||||||
|
# Add headroom to account for bitrate fluctuations
|
||||||
|
bitrate = int(bitrate * self.stream_bitrate_headroom)
|
||||||
active_streams.append({"name": stream_name, "bitrate_bps": bitrate})
|
active_streams.append({"name": stream_name, "bitrate_bps": bitrate})
|
||||||
|
|
||||||
return active_streams
|
return active_streams
|
||||||
@@ -292,6 +296,7 @@ class JellyfinQBittorrentMonitor:
|
|||||||
logger.info(f"Service buffer: {self.service_buffer} bps")
|
logger.info(f"Service buffer: {self.service_buffer} bps")
|
||||||
logger.info(f"Default stream bitrate: {self.default_stream_bitrate} bps")
|
logger.info(f"Default stream bitrate: {self.default_stream_bitrate} bps")
|
||||||
logger.info(f"Minimum torrent speed: {self.min_torrent_speed} KB/s")
|
logger.info(f"Minimum torrent speed: {self.min_torrent_speed} KB/s")
|
||||||
|
logger.info(f"Stream bitrate headroom: {self.stream_bitrate_headroom}x")
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, self.signal_handler)
|
signal.signal(signal.SIGINT, self.signal_handler)
|
||||||
signal.signal(signal.SIGTERM, self.signal_handler)
|
signal.signal(signal.SIGTERM, self.signal_handler)
|
||||||
@@ -356,7 +361,7 @@ class JellyfinQBittorrentMonitor:
|
|||||||
elif desired_state == "throttled":
|
elif desired_state == "throttled":
|
||||||
action = (
|
action = (
|
||||||
"set alt limits "
|
"set alt limits "
|
||||||
f"dl={int(remaining_kbs)}KB/s ul=1KB/s, enable alt speed"
|
f"dl={int(remaining_kbs)}KB/s ul={int(remaining_kbs)}KB/s, enable alt speed"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
action = "pause torrents"
|
action = "pause torrents"
|
||||||
@@ -380,7 +385,7 @@ class JellyfinQBittorrentMonitor:
|
|||||||
if self.torrents_paused:
|
if self.torrents_paused:
|
||||||
self.resume_all_torrents()
|
self.resume_all_torrents()
|
||||||
self.torrents_paused = False
|
self.torrents_paused = False
|
||||||
self.set_alt_speed_limits(remaining_kbs, 1)
|
self.set_alt_speed_limits(remaining_kbs, remaining_kbs)
|
||||||
self.use_alt_limits(True)
|
self.use_alt_limits(True)
|
||||||
else:
|
else:
|
||||||
if not self.torrents_paused:
|
if not self.torrents_paused:
|
||||||
@@ -415,6 +420,7 @@ if __name__ == "__main__":
|
|||||||
service_buffer = int(os.getenv("SERVICE_BUFFER", "5000000"))
|
service_buffer = int(os.getenv("SERVICE_BUFFER", "5000000"))
|
||||||
default_stream_bitrate = int(os.getenv("DEFAULT_STREAM_BITRATE", "10000000"))
|
default_stream_bitrate = int(os.getenv("DEFAULT_STREAM_BITRATE", "10000000"))
|
||||||
min_torrent_speed = int(os.getenv("MIN_TORRENT_SPEED", "100"))
|
min_torrent_speed = int(os.getenv("MIN_TORRENT_SPEED", "100"))
|
||||||
|
stream_bitrate_headroom = float(os.getenv("STREAM_BITRATE_HEADROOM", "1.1"))
|
||||||
|
|
||||||
monitor = JellyfinQBittorrentMonitor(
|
monitor = JellyfinQBittorrentMonitor(
|
||||||
jellyfin_url=jellyfin_url,
|
jellyfin_url=jellyfin_url,
|
||||||
@@ -427,6 +433,7 @@ if __name__ == "__main__":
|
|||||||
service_buffer=service_buffer,
|
service_buffer=service_buffer,
|
||||||
default_stream_bitrate=default_stream_bitrate,
|
default_stream_bitrate=default_stream_bitrate,
|
||||||
min_torrent_speed=min_torrent_speed,
|
min_torrent_speed=min_torrent_speed,
|
||||||
|
stream_bitrate_headroom=stream_bitrate_headroom,
|
||||||
)
|
)
|
||||||
|
|
||||||
monitor.run()
|
monitor.run()
|
||||||
|
|||||||
@@ -287,10 +287,9 @@ pkgs.testers.runNixOSTest {
|
|||||||
assert is_throttled(), "Should be in alt speed mode during streaming"
|
assert is_throttled(), "Should be in alt speed mode during streaming"
|
||||||
dl_limit = get_alt_dl_limit()
|
dl_limit = get_alt_dl_limit()
|
||||||
ul_limit = get_alt_up_limit()
|
ul_limit = get_alt_up_limit()
|
||||||
# Upload should be minimal (1 KB/s = 1024 bytes/s)
|
# Both upload and download should get remaining bandwidth (proportional)
|
||||||
assert ul_limit == 1024, f"Upload limit should be 1024 bytes/s, got {ul_limit}"
|
|
||||||
# Download limit should be > 0 (budget not exhausted for a single stream)
|
|
||||||
assert dl_limit > 0, f"Download limit should be > 0, got {dl_limit}"
|
assert dl_limit > 0, f"Download limit should be > 0, got {dl_limit}"
|
||||||
|
assert ul_limit == dl_limit, f"Upload limit ({ul_limit}) should equal download limit ({dl_limit})"
|
||||||
|
|
||||||
# Stop playback
|
# Stop playback
|
||||||
playback_stop = {
|
playback_stop = {
|
||||||
|
|||||||
Reference in New Issue
Block a user