remotion
Version:
Make videos programmatically
166 lines (165 loc) • 6.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnimatedImage = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const cancel_render_js_1 = require("../cancel-render.js");
const use_memoized_effects_js_1 = require("../effects/use-memoized-effects.js");
const enable_sequence_stack_traces_js_1 = require("../enable-sequence-stack-traces.js");
const sequence_field_schema_js_1 = require("../sequence-field-schema.js");
const Sequence_js_1 = require("../Sequence.js");
const use_current_frame_js_1 = require("../use-current-frame.js");
const use_delay_render_js_1 = require("../use-delay-render.js");
const use_video_config_js_1 = require("../use-video-config.js");
const wrap_in_schema_js_1 = require("../wrap-in-schema.js");
const canvas_1 = require("./canvas");
const decode_image_js_1 = require("./decode-image.js");
const resolve_image_source_1 = require("./resolve-image-source");
const animatedImageSchema = {
playbackRate: {
type: 'number',
min: 0,
max: 10,
step: 0.1,
default: 1,
description: 'Playback Rate',
},
...sequence_field_schema_js_1.sequenceVisualStyleSchema,
hidden: sequence_field_schema_js_1.hiddenField,
};
const AnimatedImageContent = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', effects, controls, ...props }, canvasRef) => {
var _a;
const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
const [imageDecoder, setImageDecoder] = (0, react_1.useState)(null);
const { delayRender, continueRender } = (0, use_delay_render_js_1.useDelayRender)();
const [decodeHandle] = (0, react_1.useState)(() => delayRender(`Rendering <AnimatedImage/> with src="${resolvedSrc}"`));
const frame = (0, use_current_frame_js_1.useCurrentFrame)();
const { fps } = (0, use_video_config_js_1.useVideoConfig)();
const currentTime = frame / playbackRate / fps;
const currentTimeRef = (0, react_1.useRef)(currentTime);
currentTimeRef.current = currentTime;
const ref = (0, react_1.useRef)(null);
const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
effects,
overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
});
(0, react_1.useImperativeHandle)(canvasRef, () => {
var _a;
const c = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.getCanvas();
if (!c) {
throw new Error('Canvas ref is not set');
}
return c;
}, []);
const [initialLoopBehavior] = (0, react_1.useState)(() => loopBehavior);
(0, react_1.useEffect)(() => {
const controller = new AbortController();
(0, decode_image_js_1.decodeImage)({
resolvedSrc,
signal: controller.signal,
currentTime: currentTimeRef.current,
initialLoopBehavior,
})
.then((d) => {
setImageDecoder(d);
continueRender(decodeHandle);
})
.catch((err) => {
if (err.name === 'AbortError') {
continueRender(decodeHandle);
return;
}
if (onError) {
onError === null || onError === void 0 ? void 0 : onError(err);
continueRender(decodeHandle);
}
else {
(0, cancel_render_js_1.cancelRender)(err);
}
});
return () => {
controller.abort();
};
}, [
resolvedSrc,
decodeHandle,
onError,
initialLoopBehavior,
continueRender,
]);
(0, react_1.useLayoutEffect)(() => {
if (!imageDecoder) {
return;
}
const delay = delayRender(`Rendering frame at ${currentTime} of <AnimatedImage src="${src}"/>`);
let cancelled = false;
imageDecoder
.getFrame(currentTime, loopBehavior)
.then(async (videoFrame) => {
var _a, _b;
if (cancelled) {
return;
}
if (videoFrame === null) {
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.clear();
continueRender(delay);
return;
}
const completed = await ((_b = ref.current) === null || _b === void 0 ? void 0 : _b.draw(videoFrame.frame));
if (completed && !cancelled) {
continueRender(delay);
}
})
.catch((err) => {
if (cancelled) {
return;
}
if (onError) {
onError(err);
continueRender(delay);
}
else {
(0, cancel_render_js_1.cancelRender)(err);
}
});
return () => {
cancelled = true;
continueRender(delay);
};
}, [
currentTime,
imageDecoder,
loopBehavior,
onError,
src,
continueRender,
delayRender,
memoizedEffects,
fit,
width,
height,
]);
return ((0, jsx_runtime_1.jsx)(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, effects: memoizedEffects, ...props }));
});
AnimatedImageContent.displayName = 'AnimatedImageContent';
const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, loopBehavior, id, className, style, durationInFrames, effects = [], _experimentalControls: controls, ref, ...sequenceProps }) => {
const { durationInFrames: videoDuration } = (0, use_video_config_js_1.useVideoConfig)();
const resolvedDuration = durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : videoDuration;
const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
const animatedImageProps = {
src,
width,
height,
onError,
fit,
playbackRate,
loopBehavior,
id,
className,
style,
};
return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", durationInFrames: resolvedDuration, name: "<AnimatedImage>", _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/animatedimage", _experimentalControls: controls, _remotionInternalEffects: memoizedEffectDefinitions, ...sequenceProps, children: (0, jsx_runtime_1.jsx)(AnimatedImageContent, { ...animatedImageProps, ref: ref, effects: effects, controls: controls }) }));
};
exports.AnimatedImage = (0, wrap_in_schema_js_1.wrapInSchema)(AnimatedImageInner, animatedImageSchema);
exports.AnimatedImage.displayName = 'AnimatedImage';
(0, enable_sequence_stack_traces_js_1.addSequenceStackTraces)(exports.AnimatedImage);