@remotion/studio
Version:
APIs for interacting with the Remotion Studio
63 lines (62 loc) • 2.02 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractFrames = extractFrames;
const mediabunny_1 = require("mediabunny");
async function extractFrames({ src, timestampsInSeconds, onFrame, signal, }) {
const input = new mediabunny_1.Input({
formats: mediabunny_1.ALL_FORMATS,
source: new mediabunny_1.UrlSource(src),
});
const dispose = () => {
input.dispose();
};
if (signal) {
signal.addEventListener('abort', dispose, { once: true });
}
try {
const [durationInSeconds, format, videoTrack] = await Promise.all([
input.computeDuration(),
input.getFormat(),
input.getPrimaryVideoTrack(),
]);
if (!videoTrack) {
throw new Error('No video track found in the input');
}
const timestamps = typeof timestampsInSeconds === 'function'
? await timestampsInSeconds({
track: {
width: videoTrack.displayWidth,
height: videoTrack.displayHeight,
},
container: format.name,
durationInSeconds,
})
: timestampsInSeconds;
if (timestamps.length === 0) {
return;
}
const sink = new mediabunny_1.VideoSampleSink(videoTrack);
for await (const videoSample of sink.samplesAtTimestamps(timestamps)) {
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
break;
}
if (!videoSample) {
continue;
}
const videoFrame = videoSample.toVideoFrame();
onFrame(videoFrame);
}
}
catch (error) {
if (error instanceof mediabunny_1.InputDisposedError) {
return;
}
throw error;
}
finally {
dispose();
if (signal) {
signal.removeEventListener('abort', dispose);
}
}
}