8c7938aca0
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)
21 lines
969 B
C#
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);
|
|
}
|