Slice 2 of TASK 65. 602 green, 0 warnings. **Clips are still off**: no `ClipBuffer` is passed, so the ffmpeg command line is byte-for-byte what it was before this commit, and a test asserts exactly that (the original args are a strict prefix of the new ones). - `FfmpegArgs` appends a fragmented-MP4 output to `pipe:1` only when `ClipBuffer` is set. One-second fragments (`-frag_duration 1000000`) rather than the 4 s GOP, so a clip can start inside the window instead of at the last keyframe. Stats already own stderr, so stdout was free. - `Fmp4FragmentSplitter` turns that byte stream into whole fragments: `ftyp`+`moov` is the init segment, each `moof`+`mdat` is a fragment. It parses box headers itself, survives a box being cut anywhere across reads, and **resyncs instead of throwing** — a clip fault must never take the stream down. - `FfmpegEncoder` reads it on its own task, never blocking the frame path. Any exception logs and disables clips for the session; the broadcast is untouched. - `IEncoderProcess` gained `StandardOutputBytes` (the seam already had the text reader for probing). Next slices: the replay layer + retention, then the Settings switch with disabled-but-remembered controls.
31 lines
1.1 KiB
C#
31 lines
1.1 KiB
C#
using System.Diagnostics;
|
|
using System.IO;
|
|
|
|
namespace ytLive.Services.Encoder;
|
|
|
|
/// <summary>
|
|
/// Seam around a spawned subprocess (the encoder's ffmpeg and the encoder probe).
|
|
/// Exposes the redirected stdin (binary frames), stdout (probe listing) and stderr
|
|
/// (progress lines) plus exit control, so the encoder logic never touches
|
|
/// <c>System.Diagnostics.Process</c> directly and tests can fake the whole thing.
|
|
/// </summary>
|
|
public interface IEncoderProcess : IDisposable
|
|
{
|
|
void Start(ProcessStartInfo startInfo);
|
|
|
|
/// <summary>Raw binary stdin — the encoder writes BGRA frames here.</summary>
|
|
Stream StandardInput { get; }
|
|
|
|
TextReader StandardOutput { get; }
|
|
|
|
/// <summary>TASK 65: the same stdout as raw bytes — the replay-buffer mux writes fragmented MP4
|
|
/// here while <c>-stats</c> keeps stderr for itself.</summary>
|
|
Stream StandardOutputBytes { get; }
|
|
TextReader StandardError { get; }
|
|
|
|
bool HasExited { get; }
|
|
int ExitCode { get; }
|
|
void Kill();
|
|
Task WaitForExitAsync(CancellationToken cancellationToken = default);
|
|
}
|