feat(waveform): generalize high-res compute to every track (Direction B)
Per-track high-res datum keyed by EntryKey in the renamed track-waveforms vault; computed at upload for all tracks, regenerable per-track via CMS, with a re-runnable backfill. Mix read path repointed so it keeps working.
This commit is contained in:
@@ -138,8 +138,9 @@ public class TrackController : ControllerBase
|
||||
}
|
||||
|
||||
// GET api/track/waveform-status ([ApiKeyAuthorize])
|
||||
// Admin backfill view: returns every track with a flag for whether a waveform profile is
|
||||
// stored in the WaveformProfiles vault. The catalogue is small enough that the CMS panel reads
|
||||
// Admin backfill view: returns every track with flags for whether each waveform datum is stored —
|
||||
// the 512-bucket player-bar profile (WaveformProfiles vault) and the per-track high-res visualizer
|
||||
// datum (TrackWaveforms vault, phase-12 §5). The catalogue is small enough that the CMS panel reads
|
||||
// the whole list unpaged. Declared before the parameterized "{trackId}" route so the literal
|
||||
// segment is never treated as a trackId.
|
||||
[ApiKeyAuthorize]
|
||||
@@ -158,12 +159,14 @@ public class TrackController : ControllerBase
|
||||
foreach (var track in tracks.Value)
|
||||
{
|
||||
var profile = await _waveformProfileService.GetProfileAsync(track.EntryKey);
|
||||
var highRes = await _waveformProfileService.GetProfileAsync(track.EntryKey, VaultConstants.TrackWaveforms);
|
||||
status.Add(new WaveformStatusDto
|
||||
{
|
||||
TrackId = track.Id,
|
||||
EntryKey = track.EntryKey,
|
||||
TrackName = track.TrackName,
|
||||
HasProfile = profile is not null,
|
||||
HasHighRes = highRes is not null,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -600,6 +603,35 @@ public class TrackController : ControllerBase
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// POST api/track/{trackId}/waveform/high-res ([ApiKeyAuthorize])
|
||||
// Track-cardinal generalization of the Mix-only waveform trigger (phase-12 §5): compute and store
|
||||
// the per-track high-res datum for ANY track from its vault audio, keyed by EntryKey in the
|
||||
// track-waveforms vault. Drives the CMS per-row "Generate high-res" action and the batch backfill.
|
||||
// Re-runnable: a second call recomputes and overwrites. trackId is the EntryKey. 404 when no audio
|
||||
// is stored under that key; 500 when the WAV cannot be decoded or the vault write fails. Declared
|
||||
// before the parameterized PUT "{trackId}" route so the literal "waveform/high-res" segment wins.
|
||||
[ApiKeyAuthorize]
|
||||
[HttpPost("{trackId}/waveform/high-res")]
|
||||
public async Task<ActionResult> GenerateHighResWaveform(string trackId)
|
||||
{
|
||||
var audio = await _trackContentService.GetAudioBinaryAsync(trackId);
|
||||
if (audio is null)
|
||||
{
|
||||
_logger.LogWarning("GenerateHighResWaveform: no audio in vault for {TrackId}", trackId);
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var stored = await _waveformProfileService.ComputeAndStoreHighResAsync(
|
||||
audio.Buffer, trackId, audio.Duration);
|
||||
if (!stored)
|
||||
{
|
||||
_logger.LogError("GenerateHighResWaveform: computation/storage failed for {TrackId}", trackId);
|
||||
return StatusCode(500, "Failed to generate high-res waveform datum.");
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[ApiKeyAuthorize]
|
||||
[HttpPut("{trackId}")]
|
||||
public async Task<ActionResult> PutTrack(string trackId, [FromBody] AudioBinaryDto track)
|
||||
|
||||
Reference in New Issue
Block a user