Add CMS waveform pre-processing panel with backfill endpoints

GET api/track/waveform-status and POST api/track/{id}/waveform (ApiKey);
CmsTrackService methods; TrackPreProcessing page with per-row and
sequential bulk generation; nav links from TrackList and Index.
This commit is contained in:
daniel-c-harvey
2026-06-05 17:56:25 -04:00
parent 1b493434d6
commit 6e25ad3085
8 changed files with 418 additions and 7 deletions
@@ -281,4 +281,81 @@ public class CmsTrackService : ICmsTrackService
return Result.CreateFailResult("Failed to update track.");
}
}
public async Task<ResultContainer<WaveformStatusDto[]>> GetWaveformStatusAsync(CancellationToken ct = default)
{
var client = _httpClientFactory.CreateClient(ContentCmsClientName);
HttpResponseMessage response;
try
{
response = await client.GetAsync("api/track/waveform-status", ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "Content API call failed for waveform status");
return ResultContainer<WaveformStatusDto[]>.CreateFailResult("Content API is unreachable.");
}
using (response)
{
if (!response.IsSuccessStatusCode)
{
_logger.LogError("Content API waveform status failed: {Status}", (int)response.StatusCode);
return ResultContainer<WaveformStatusDto[]>.CreateFailResult("Failed to load waveform status.");
}
WaveformStatusDto[]? status;
try
{
status = await response.Content.ReadFromJsonAsync<WaveformStatusDto[]>(ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to deserialize waveform status from Content API response");
return ResultContainer<WaveformStatusDto[]>.CreateFailResult("Content API returned an unexpected response.");
}
if (status is null)
{
_logger.LogError("Content API returned a null waveform status list");
return ResultContainer<WaveformStatusDto[]>.CreateFailResult("Content API returned an empty response.");
}
return ResultContainer<WaveformStatusDto[]>.CreatePassResult(status);
}
}
public async Task<Result> GenerateWaveformProfileAsync(string entryKey, CancellationToken ct = default)
{
var client = _httpClientFactory.CreateClient(ContentCmsClientName);
HttpResponseMessage response;
try
{
response = await client.PostAsync($"api/track/{Uri.EscapeDataString(entryKey)}/waveform", null, ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "Content API call failed for waveform generation of {EntryKey}", entryKey);
return Result.CreateFailResult("Content API is unreachable.");
}
using (response)
{
if (response.IsSuccessStatusCode)
{
return Result.CreatePassResult();
}
if (response.StatusCode == HttpStatusCode.NotFound)
{
return Result.CreateFailResult("Track audio not found.");
}
var body = await response.Content.ReadAsStringAsync(ct);
_logger.LogError("Content API waveform generation failed for {EntryKey}: {Status} {Body}", entryKey, (int)response.StatusCode, body);
return Result.CreateFailResult("Failed to generate waveform profile.");
}
}
}