#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
19 lines
863 B
C#
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 -> 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 -> 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);
|