Skip to content

Commit 56450e0

Browse files
committed
perf(processor): reuse spectral metrics to avoid duplicate extraction
- Extract spectral metrics once per filtered frame and reuse for accumulators - Add spectral parameter to extractIntervalFrameMetrics and extractFrameMetadata - Replace repeated extractSpectralMetrics calls with single extraction per frame - No functional change; reduces CPU work and allocations during analysis Signed-off-by: Martin Wimpress <martin@wimpress.org>
1 parent ef13c5c commit 56450e0

1 file changed

Lines changed: 17 additions & 10 deletions

File tree

internal/processor/analyzer.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,14 +1755,13 @@ func extractSpectralMetrics(metadata *ffmpeg.AVDictionary) spectralMetrics {
17551755
// extractIntervalFrameMetrics extracts per-frame metrics for interval accumulation.
17561756
// Only collects metrics that are valid per-window (aspectralstats, ebur128 windowed).
17571757
// Excludes astats which provides cumulative values, not per-interval.
1758-
func extractIntervalFrameMetrics(metadata *ffmpeg.AVDictionary) intervalFrameMetrics {
1758+
func extractIntervalFrameMetrics(metadata *ffmpeg.AVDictionary, spectral spectralMetrics) intervalFrameMetrics {
17591759
var m intervalFrameMetrics
17601760

17611761
// Peak level from astats (used for max tracking, which is valid per-interval)
17621762
m.PeakLevel, _ = getFloatMetadata(metadata, metaKeyPeakLevel)
17631763

1764-
// aspectralstats metrics (valid per-window measurements)
1765-
spectral := extractSpectralMetrics(metadata)
1764+
// aspectralstats metrics (valid per-window measurements, pre-extracted by caller)
17661765
m.SpectralMean = spectral.Mean
17671766
m.SpectralVariance = spectral.Variance
17681767
m.SpectralCentroid = spectral.Centroid
@@ -1795,14 +1794,14 @@ func extractIntervalFrameMetrics(metadata *ffmpeg.AVDictionary) intervalFrameMet
17951794
// extractFrameMetadata extracts audio analysis metadata from a filtered frame.
17961795
// Updates accumulators with spectral, astats, and ebur128 measurements.
17971796
// Called from both the main processing loop and the flush loop.
1798-
func extractFrameMetadata(metadata *ffmpeg.AVDictionary, acc *metadataAccumulators) {
1797+
func extractFrameMetadata(metadata *ffmpeg.AVDictionary, acc *metadataAccumulators, spectral spectralMetrics) {
17991798
if metadata == nil {
18001799
return
18011800
}
18021801

1803-
// Extract all aspectralstats measurements (averaged across frames)
1802+
// Accumulate pre-extracted spectral metrics (averaged across frames)
18041803
// For mono audio, spectral stats are under channel .1
1805-
acc.accumulateSpectral(extractSpectralMetrics(metadata))
1804+
acc.accumulateSpectral(spectral)
18061805

18071806
// Extract astats measurements (cumulative, so we keep the latest)
18081807
// For mono audio, stats are under channel .1
@@ -2304,12 +2303,16 @@ func AnalyzeAudio(filename string, config *FilterChainConfig, progressCallback f
23042303
return nil, fmt.Errorf("failed to get filtered frame: %w", err)
23052304
}
23062305

2306+
// Extract spectral metrics once, reuse for both whole-file and interval accumulators
2307+
metadata := filteredFrame.Metadata()
2308+
spectral := extractSpectralMetrics(metadata)
2309+
23072310
// Extract measurements from frame metadata (whole-file accumulators)
2308-
extractFrameMetadata(filteredFrame.Metadata(), acc)
2311+
extractFrameMetadata(metadata, acc, spectral)
23092312

23102313
// Also accumulate into current interval for per-interval spectral data
23112314
// Filtered frames roughly correspond to input timing (just at higher sample rate)
2312-
intervalAcc.add(extractIntervalFrameMetrics(filteredFrame.Metadata()))
2315+
intervalAcc.add(extractIntervalFrameMetrics(metadata, spectral))
23132316

23142317
ffmpeg.AVFrameUnref(filteredFrame)
23152318
}
@@ -2329,11 +2332,15 @@ func AnalyzeAudio(filename string, config *FilterChainConfig, progressCallback f
23292332
return nil, fmt.Errorf("failed to get filtered frame: %w", err)
23302333
}
23312334

2335+
// Extract spectral metrics once, reuse for both whole-file and interval accumulators
2336+
metadata := filteredFrame.Metadata()
2337+
spectral := extractSpectralMetrics(metadata)
2338+
23322339
// Extract measurements from remaining frames
2333-
extractFrameMetadata(filteredFrame.Metadata(), acc)
2340+
extractFrameMetadata(metadata, acc, spectral)
23342341

23352342
// Also accumulate into current interval for per-interval spectral data
2336-
intervalAcc.add(extractIntervalFrameMetrics(filteredFrame.Metadata()))
2343+
intervalAcc.add(extractIntervalFrameMetrics(metadata, spectral))
23372344

23382345
ffmpeg.AVFrameUnref(filteredFrame)
23392346
}

0 commit comments

Comments
 (0)