Files
ytLlive/Services/Encoder/IFfmpegLocator.cs
T
gramps 8c7938aca0 FFmpeg locator (TASK 4 ship step 2) + licensing: notices, About, LGPL-shared pin
IFfmpegLocator seam that resolves ffmpeg.exe (PATH -> cache -> pinned download),
plus the licensing compliance that makes a paid GA product defensible.

NOTE FOR USERS: this change shows NO difference in the app's behavior except a
new top-bar "About" button (opens THIRD-PARTY-NOTICES.txt). It is scaffolding
for the encoder/streaming work.

- Services/Encoder/: IFfmpegLocator + FfmpegLocator. Pin is BtbN lgpl-shared
  autobuild-2026-08-09-13-03 (NOT gyan.dev/GPL or static: LGPLv2.1 §6 static
  relink material avoided by dynamic linking); extracts ffmpeg.exe + libav*.dll
  via a staging dir so a crash never leaves a partial cache
- THIRD-PARTY-NOTICES.txt: LGPL/BSD/MIT notices + source offer, copied to the
  build output, surfaced by the About button; v1 gate = bundle full license
  texts (TASK 4 requirement 9)
- ai.md "Licensing - do not violate" guardrails (never GPL/nonfree/static/latest-
  tag, never link FFmpeg in, never drop notices); TASKS.md + Services/index.md
  updated
- Tests: FfmpegLocatorTests - hermetic decision-ladder integration test + shared-
  build DLL extraction + edge cases; docs updated (78 tests passing, 0 warnings)
2026-08-10 11:02:26 -07:00

21 lines
969 B
C#

namespace ytLive.Services.Encoder;
/// <summary>
/// Resolves an absolute path to a usable <c>ffmpeg.exe</c>, downloading it on
/// first use if neither the user's PATH nor the local cache provides one — the
/// encoder's one external dependency is never shipped in the repo (TASK 4 ship
/// step 2; see TASKS.md). Seam so the encoder step and the tests can fake it.
/// </summary>
public interface IFfmpegLocator
{
/// <summary>
/// Returns the path to <c>ffmpeg.exe</c>: the first PATH candidate that
/// exists, else the cached copy, else a freshly downloaded one (ffmpeg.exe +
/// its libav DLLs extracted from the pinned BtbN LGPL-shared zip into the
/// tools directory).
/// </summary>
/// <exception cref="IOException">The download/extract produced no usable
/// binary (offline, expired pin, corrupt archive) — recoverable, logged.</exception>
Task<string> LocateAsync(CancellationToken cancellationToken = default);
}