Wire Opus end-to-end playback + Backfill-Opus action (Phase 18.5)

Player picks Opus when the browser can decode it and a sidecar exists (else lossless), injecting the sidecar before stream init; seek reuses the same format. Adds the Backfill-Opus bulk API endpoint + CMS action.
This commit is contained in:
daniel-c-harvey
2026-06-23 12:39:13 -04:00
parent dce5530890
commit 2bde4908d7
12 changed files with 961 additions and 1 deletions
@@ -152,6 +152,15 @@ public interface ICmsTrackService
/// </summary>
Task<Result> GenerateHighResWaveformAsync(string entryKey, CancellationToken ct = default);
/// <summary>
/// Trigger the catalogue-wide Backfill-Opus pass via <c>POST api/track/opus/backfill</c> (Phase 18.5).
/// The API enqueues a background Opus derive for every track lacking a complete Opus artifact and returns
/// the (enqueued, skipped) counts. Enqueue-only — the transcodes run server-side on a serial background
/// worker, so this call returns as soon as the work is scheduled, not when transcoding finishes. The
/// <c>Enqueued</c> count is how many derives were scheduled; <c>Skipped</c> is how many already had Opus.
/// </summary>
Task<ResultContainer<OpusBackfillResult>> BackfillOpusAsync(CancellationToken ct = default);
/// <summary>Returns all releases with track counts from GET api/track/albums.</summary>
Task<ResultContainer<List<ReleaseDto>>> GetReleasesAsync(CancellationToken ct = default);
@@ -160,3 +169,11 @@ public interface ICmsTrackService
/// </summary>
Task<ResultContainer<int>> GetTrackCountAsync(CancellationToken ct = default);
}
/// <summary>
/// Outcome of a Backfill-Opus pass (Phase 18.5): how many tracks had a background derive scheduled
/// (<paramref name="Enqueued"/>) and how many were skipped because they already carry a complete Opus
/// artifact (<paramref name="Skipped"/>). Both are counts of tracks, not finished transcodes — the work
/// runs asynchronously on the API's background worker after this returns.
/// </summary>
public readonly record struct OpusBackfillResult(int Enqueued, int Skipped);