UNPKG

@remotion/media-utils

Version:

Utilities for working with media files

51 lines (50 loc) 2.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPartialAudioData = void 0; const mediabunny_1 = require("mediabunny"); // Audio frames might have dependencies on previous and next frames so we need to decode a bit more and then discard it. // The worst case seems to be FLAC files with a 65'535 sample window, which would be 1486.0ms at 44.1Khz. // So let's set a threshold of 1.5 seconds. const EXTRA_THRESHOLD_IN_SECONDS = 1.5; const getPartialAudioData = async ({ track, fromSeconds, toSeconds, channelIndex, signal, isMatroska = false, }) => { if (signal.aborted) { throw new Error('Operation was aborted'); } const audioSamples = []; // matroska must be decoded from the start due to limitation // https://www.remotion.dev/docs/media/support#matroska-limitation // Also request extra data beforehand to handle audio frame dependencies const actualFromSeconds = isMatroska ? 0 : Math.max(0, fromSeconds - EXTRA_THRESHOLD_IN_SECONDS); // mediabunny docs: constructing the sink is virtually free and does not perform any media data reads. const sink = new mediabunny_1.AudioBufferSink(track); const iterator = sink.buffers(actualFromSeconds, toSeconds); for await (const { buffer, timestamp, duration } of iterator) { if (signal.aborted) { break; } const channelData = buffer.getChannelData(channelIndex); const bufferStartSeconds = timestamp; const bufferEndSeconds = timestamp + duration; const overlapStartSecond = Math.max(bufferStartSeconds, fromSeconds); const overlapEndSecond = Math.min(bufferEndSeconds, toSeconds); if (overlapStartSecond >= overlapEndSecond) { continue; } const startSampleInBuffer = Math.floor((overlapStartSecond - bufferStartSeconds) * buffer.sampleRate); const endSampleInBuffer = Math.ceil((overlapEndSecond - bufferStartSeconds) * buffer.sampleRate); const trimmedData = channelData.slice(startSampleInBuffer, endSampleInBuffer); audioSamples.push(trimmedData); } await iterator.return(); const totalSamples = audioSamples.reduce((sum, sample) => sum + sample.length, 0); const result = new Float32Array(totalSamples); let offset = 0; for (const audioSample of audioSamples) { result.set(audioSample, offset); offset += audioSample.length; } return result; }; exports.getPartialAudioData = getPartialAudioData;