@remotion/studio
Version:
APIs for interacting with the Remotion Studio
68 lines (67 loc) • 2.42 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TARGET_SAMPLE_RATE = void 0;
exports.loadWaveformPeaks = loadWaveformPeaks;
const mediabunny_1 = require("mediabunny");
const TARGET_SAMPLE_RATE = 100;
exports.TARGET_SAMPLE_RATE = TARGET_SAMPLE_RATE;
const peaksCache = new Map();
async function loadWaveformPeaks(url, signal) {
const cached = peaksCache.get(url);
if (cached)
return cached;
const input = new mediabunny_1.Input({
formats: mediabunny_1.ALL_FORMATS,
source: new mediabunny_1.UrlSource(url),
});
try {
const audioTrack = await input.getPrimaryAudioTrack();
if (!audioTrack) {
return new Float32Array(0);
}
const { sampleRate } = audioTrack;
const durationInSeconds = await audioTrack.computeDuration();
const totalPeaks = Math.ceil(durationInSeconds * TARGET_SAMPLE_RATE);
const samplesPerPeak = Math.floor(sampleRate / TARGET_SAMPLE_RATE);
const peaks = new Float32Array(totalPeaks);
let peakIndex = 0;
let peakMax = 0;
let sampleInPeak = 0;
const sink = new mediabunny_1.AudioSampleSink(audioTrack);
for await (const sample of sink.samples()) {
if (signal.aborted) {
sample.close();
return new Float32Array(0);
}
const bytesNeeded = sample.allocationSize({
format: 'f32',
planeIndex: 0,
});
const floats = new Float32Array(bytesNeeded / 4);
sample.copyTo(floats, { format: 'f32', planeIndex: 0 });
sample.close();
for (let i = 0; i < floats.length; i++) {
const abs = Math.abs(floats[i]);
if (abs > peakMax)
peakMax = abs;
sampleInPeak++;
if (sampleInPeak >= samplesPerPeak) {
if (peakIndex < totalPeaks) {
peaks[peakIndex] = peakMax;
}
peakIndex++;
peakMax = 0;
sampleInPeak = 0;
}
}
}
if (sampleInPeak > 0 && peakIndex < totalPeaks) {
peaks[peakIndex] = peakMax;
}
peaksCache.set(url, peaks);
return peaks;
}
finally {
input.dispose();
}
}