@remotion/media-parser
Version:
A pure JavaScript library for parsing video files
101 lines (100 loc) • 3.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.bufferManager = void 0;
const makeBufferWithMaxBytes = (initialData, maxBytes) => {
const maxByteLength = Math.min(maxBytes, 2 ** 31);
try {
const buf = new ArrayBuffer(initialData.byteLength, {
maxByteLength,
});
return buf;
}
catch (e) {
// Cloudflare Workers have a limit of 128MB max array buffer size
if (e instanceof RangeError && maxBytes > 2 ** 27) {
return new ArrayBuffer(initialData.byteLength, {
maxByteLength: 2 ** 27,
});
}
throw e;
}
};
const bufferManager = ({ initialData, maxBytes, counter, }) => {
const buf = makeBufferWithMaxBytes(initialData, maxBytes);
if (!buf.resize) {
throw new Error('`ArrayBuffer.resize` is not supported in this Runtime. On the server: Use at least Node.js 20 or Bun. In the browser: Chrome 111, Edge 111, Safari 16.4, Firefox 128, Opera 111');
}
let uintArray = new Uint8Array(buf);
uintArray.set(initialData);
let view = new DataView(uintArray.buffer);
const destroy = () => {
uintArray = new Uint8Array(0);
buf.resize(0);
};
const flushBytesRead = (force, mode) => {
const bytesToRemove = counter.getDiscardedOffset();
// Only do this operation if it is really worth it 😇
// let's set the threshold to 3MB
if (bytesToRemove < 3000000 && !force) {
return { bytesRemoved: 0, removedData: null };
}
// Don't remove if the data is not even available
if (view.byteLength < bytesToRemove && !force) {
return { bytesRemoved: 0, removedData: null };
}
counter.discardBytes(bytesToRemove);
const removedData = mode === 'download' ? uintArray.slice(0, bytesToRemove) : null;
const newData = uintArray.slice(bytesToRemove);
uintArray.set(newData);
buf.resize(newData.byteLength);
view = new DataView(uintArray.buffer);
return { bytesRemoved: bytesToRemove, removedData };
};
const skipTo = (offset) => {
const becomesSmaller = offset < counter.getOffset();
if (becomesSmaller) {
const toDecrement = counter.getOffset() - offset;
if (toDecrement > counter.getDiscardedOffset()) {
throw new Error('Cannot count backwards, data has already been flushed');
}
counter.decrement(toDecrement);
}
const currentOffset = counter.getOffset();
counter.increment(offset - currentOffset);
};
const addData = (newData) => {
const oldLength = buf.byteLength;
const newLength = oldLength + newData.byteLength;
if (newLength < oldLength) {
throw new Error('Cannot decrement size');
}
if (newLength > (maxBytes !== null && maxBytes !== void 0 ? maxBytes : Infinity)) {
throw new Error(`Exceeded maximum byte length ${maxBytes} with ${newLength}`);
}
buf.resize(newLength);
uintArray = new Uint8Array(buf);
uintArray.set(newData, oldLength);
view = new DataView(uintArray.buffer);
};
const replaceData = (newData, seekTo) => {
buf.resize(newData.byteLength);
uintArray = new Uint8Array(buf);
uintArray.set(newData);
view = new DataView(uintArray.buffer);
counter.setDiscardedOffset(seekTo);
// reset counter to 0
counter.decrement(counter.getOffset());
// seek to the new position
counter.increment(seekTo);
};
return {
view,
uintArray,
destroy,
addData,
skipTo,
removeBytesRead: flushBytesRead,
replaceData,
};
};
exports.bufferManager = bufferManager;