Never serve a partial file: it makes Jellyfin transcode
The 12s first-byte grace was the wrong trade and a real play found it within the hour. A 2-hour upload took 3 minutes to start, played 6 seconds, and stalled. Jellyfin had run ffmpeg with -probesize 1G against the growing stream and then transcoded to HLS with libx264. The cause is the container. A fragmented MP4 with empty_moov has no duration in its header, so the only way to get one is to sum every fragment -- probing a growing file reads all of it. Jellyfin cannot establish duration, codec or bitrate, so it abandons direct play and transcodes a stream it also cannot seek. It was targeting 4.83 Mbps against a source measured at 3.29: re-encoding a stream that already fit, because it could not measure it. The same video once complete reports SupportsDirectPlay with the exact runtime and bitrate. So FIRST_BYTE_GRACE defaults to infinite again, with --wait-timeout raised to 600s for a 2-hour upload. A cold long video is slow to start, which is accepted: the fetch outlives the request so a retry is instant, and a retryable stall beats a transcode that wastes a gigabyte and cannot work. Both failure modes are recorded at the constant in the order measured so the 12s cap is not reintroduced. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -230,3 +230,37 @@ def test_summarise_is_a_single_line():
|
||||
assert "channels=119" in text
|
||||
assert "materialised=7" in text
|
||||
assert "aged_out=8" in text
|
||||
|
||||
|
||||
def test_run_prunes_channels_that_have_nothing_to_show(conn, settings, media_root,
|
||||
monkeypatch):
|
||||
"""End to end: a subscribed channel whose directory exists only because
|
||||
subscribe() wrote tvshow.nfo must not survive a run as an empty series."""
|
||||
from conftest import add_channel
|
||||
from ytstream import runner
|
||||
|
||||
empty = add_channel(conn, "UC" + "s" * 22, "Dead Channel", "dead-channel")
|
||||
tree = media_root / "dead-channel"
|
||||
tree.mkdir()
|
||||
(tree / "tvshow.nfo").write_text("<tvshow/>")
|
||||
|
||||
assert runner.prune_empty_channels(conn) == 1
|
||||
assert not tree.exists()
|
||||
|
||||
|
||||
def test_run_keeps_a_channel_with_a_materialised_video(conn, settings, media_root):
|
||||
from conftest import add_channel, add_video
|
||||
from ytstream import runner, videos
|
||||
|
||||
row = add_channel(conn, "UC" + "t" * 22, "Alive", "alive")
|
||||
tree = media_root / "alive"
|
||||
(tree / "Season 2026").mkdir(parents=True)
|
||||
(tree / "Season 2026" / "ep.strm").write_text("url")
|
||||
video = add_video(conn, row["id"], "vid00000009")
|
||||
videos.mark_materialised(conn, "vid00000009",
|
||||
rel_path="alive/Season 2026/ep.strm", season=2026,
|
||||
episode=1, upload_date="2026-08-01", duration=900,
|
||||
title="t")
|
||||
|
||||
assert runner.prune_empty_channels(conn) == 0
|
||||
assert tree.exists()
|
||||
|
||||
Reference in New Issue
Block a user