Files
ersatztv/ErsatzTV.Core/FFmpeg/PlaylistSegmentsResult.cs
T
timothy d91d6ee1ed feat(472): sub-split the HLS cold-start startup phase
#350's measurement showed `startup` is 81% of tune-in latency and carries
100% of its variance, while remaining one opaque bucket spanning FFmpeg
spawn -> input open/probe -> encoder init -> first GOP. Two hypotheses
survive that measurement (NFS input open vs VAAPI init under contention)
and they need opposite fixes, so split before optimizing.

Adds `prep` (ErsatzTV-side work before FFmpeg exists) + `ffmpegInit`
(launch -> first `-progress` output) + `firstGop` (-> live.m3u8 exists)
to the existing Information-level cold-start line.

The pipeline runs `-loglevel error -nostats -hide_banner`, so a healthy
FFmpeg writes nothing to stderr; the `-progress` stream is the only
zero-cost milestone available and `ffmpegInit` therefore still lumps
input-open with encoder-init. That limit is documented rather than
papered over, and the split degrades to the two-way form #472 accepts
when no progress arrives before the playlist.

Log-only: no transcode behavior change, no new endpoint or config knob.

fixes #472
2026-07-19 22:49:07 +02:00

19 lines
863 B
C#

namespace ErsatzTV.Core.FFmpeg;
/// <summary>
/// Timing + descriptive result of an HLS cold-start's wait-for-first-segments phase (#350).
/// <see cref="ProcessStartup"/> is Phase A (wait entry -&gt; playlist file exists — approximately
/// FFmpeg process spawn + probe + libass/encoder init + first GOP, since the wait begins right
/// after the fire-and-forget worker is launched); <see cref="SegmentFill"/> is Phase B (playlist
/// exists -&gt; the requested number of segments are present, or the 8s deadline).
/// <see cref="StartupSplit"/> breaks Phase A down further (#472).
/// </summary>
public readonly record struct PlaylistSegmentsResult(
TimeSpan ProcessStartup,
TimeSpan SegmentFill,
int SegmentsReached,
int InitialSegmentCount,
bool DeadlineExpired,
ColdStartFeatures Features,
ColdStartStartupSplit StartupSplit);