remotion
Advanced tools
Comparing version 1.6.0-alpha.0985ca71 to 1.6.0-alpha.1aea6849
import React from 'react'; | ||
import { RemotionAudioProps } from './props'; | ||
export declare const Audio: React.FC<RemotionAudioProps>; | ||
import { RemotionAudioProps, RemotionMainAudioProps } from './props'; | ||
export declare const Audio: React.FC<RemotionAudioProps & RemotionMainAudioProps>; | ||
//# sourceMappingURL=Audio.d.ts.map |
@@ -5,10 +5,22 @@ "use strict"; | ||
const jsx_runtime_1 = require("react/jsx-runtime"); | ||
const sequencing_1 = require("../sequencing"); | ||
const validate_media_props_1 = require("../validate-media-props"); | ||
const validate_start_from_props_1 = require("../validate-start-from-props"); | ||
const AudioForDevelopment_1 = require("./AudioForDevelopment"); | ||
const AudioForRendering_1 = require("./AudioForRendering"); | ||
const Audio = (props) => { | ||
const { startAt, endAt, ...otherProps } = props; | ||
if (typeof startAt !== 'undefined' || typeof endAt !== 'undefined') { | ||
validate_start_from_props_1.validateStartFromProps(startAt, endAt); | ||
const startAtFrameNo = startAt !== null && startAt !== void 0 ? startAt : 0; | ||
const endAtFrameNo = endAt !== null && endAt !== void 0 ? endAt : Infinity; | ||
return (jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: 0 - startAtFrameNo, showInTimeline: false, durationInFrames: endAtFrameNo }, { children: jsx_runtime_1.jsx(exports.Audio, Object.assign({}, otherProps), void 0) }), void 0)); | ||
} | ||
validate_media_props_1.validateMediaProps(props, 'Audio'); | ||
if (process.env.NODE_ENV === 'development') { | ||
return jsx_runtime_1.jsx(AudioForDevelopment_1.AudioForDevelopment, Object.assign({}, props), void 0); | ||
} | ||
return null; | ||
return jsx_runtime_1.jsx(AudioForRendering_1.AudioForRendering, Object.assign({}, props), void 0); | ||
}; | ||
exports.Audio = Audio; | ||
//# sourceMappingURL=Audio.js.map |
@@ -6,11 +6,56 @@ "use strict"; | ||
const react_1 = require("react"); | ||
const CompositionManager_1 = require("../CompositionManager"); | ||
const get_asset_file_name_1 = require("../get-asset-file-name"); | ||
const is_approximately_the_same_1 = require("../is-approximately-the-same"); | ||
const nonce_1 = require("../nonce"); | ||
const sequencing_1 = require("../sequencing"); | ||
const timeline_position_state_1 = require("../timeline-position-state"); | ||
const use_frame_1 = require("../use-frame"); | ||
const use_unsafe_video_config_1 = require("../use-unsafe-video-config"); | ||
const volume_prop_1 = require("../volume-prop"); | ||
const use_audio_frame_1 = require("./use-audio-frame"); | ||
const AudioForDevelopment = (props) => { | ||
const audioRef = react_1.useRef(null); | ||
const currentFrame = use_frame_1.useCurrentFrame(); | ||
const frame = use_frame_1.useCurrentFrame(); | ||
const absoluteFrame = use_frame_1.useAbsoluteCurrentFrame(); | ||
const [actualVolume, setActualVolume] = react_1.useState(1); | ||
const nonce = nonce_1.useNonce(); | ||
const audioFrame = use_audio_frame_1.useAudioFrame(); | ||
const videoConfig = use_unsafe_video_config_1.useUnsafeVideoConfig(); | ||
const [playing] = timeline_position_state_1.usePlayingState(); | ||
const { rootId } = react_1.useContext(timeline_position_state_1.TimelineContext); | ||
const parentSequence = react_1.useContext(sequencing_1.SequenceContext); | ||
const actualFrom = parentSequence | ||
? parentSequence.relativeFrom + parentSequence.cumulatedFrom | ||
: 0; | ||
const startsAt = use_audio_frame_1.useAudioStartsAt(); | ||
const { registerSequence, unregisterSequence } = react_1.useContext(CompositionManager_1.CompositionManager); | ||
const [id] = react_1.useState(() => String(Math.random())); | ||
const { volume, ...nativeProps } = props; | ||
react_1.useEffect(() => { | ||
const ref = audioRef.current; | ||
if (!ref) { | ||
return; | ||
} | ||
if (ref.volume !== actualVolume) { | ||
setActualVolume(ref.volume); | ||
return; | ||
} | ||
const onChange = () => { | ||
setActualVolume(ref.volume); | ||
}; | ||
ref.addEventListener('volumechange', onChange); | ||
return () => ref.removeEventListener('volumechange', onChange); | ||
}, [actualVolume]); | ||
react_1.useEffect(() => { | ||
const userPreferredVolume = volume_prop_1.evaluateVolume({ | ||
frame: audioFrame, | ||
volume, | ||
}); | ||
if (!is_approximately_the_same_1.isApproximatelyTheSame(userPreferredVolume, actualVolume) && | ||
audioRef.current) { | ||
audioRef.current.volume = userPreferredVolume; | ||
} | ||
}, [actualVolume, audioFrame, frame, props.volume, volume]); | ||
react_1.useEffect(() => { | ||
var _a, _b; | ||
@@ -24,28 +69,94 @@ if (playing) { | ||
}, [playing]); | ||
const duration = (() => { | ||
if (!videoConfig) { | ||
return 0; | ||
} | ||
return parentSequence | ||
? Math.min(parentSequence.durationInFrames, videoConfig.durationInFrames) | ||
: videoConfig.durationInFrames; | ||
})(); | ||
const volumes = react_1.useMemo(() => { | ||
var _a; | ||
if (typeof props.volume === 'number') { | ||
return props.volume; | ||
} | ||
const negativeShift = Math.min(0, (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.parentFrom) !== null && _a !== void 0 ? _a : 0); | ||
return new Array(duration + startsAt + negativeShift) | ||
.fill(true) | ||
.map((_, i) => { | ||
return volume_prop_1.evaluateVolume({ | ||
frame: i - negativeShift, | ||
volume, | ||
}); | ||
}) | ||
.join(','); | ||
}, [duration, parentSequence, props.volume, startsAt, volume]); | ||
react_1.useEffect(() => { | ||
var _a; | ||
if (!audioRef.current) { | ||
return; | ||
} | ||
if (!videoConfig) { | ||
return; | ||
} | ||
if (!props.src) { | ||
throw new Error('No src passed'); | ||
} | ||
registerSequence({ | ||
type: 'audio', | ||
src: props.src, | ||
id, | ||
// TODO: Cap to audio duration | ||
duration, | ||
from: 0, | ||
parent: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id) !== null && _a !== void 0 ? _a : null, | ||
displayName: get_asset_file_name_1.getAssetFileName(props.src), | ||
rootId, | ||
volume: volumes, | ||
showInTimeline: true, | ||
nonce, | ||
}); | ||
return () => unregisterSequence(id); | ||
}, [ | ||
actualFrom, | ||
duration, | ||
id, | ||
parentSequence, | ||
props.src, | ||
registerSequence, | ||
rootId, | ||
unregisterSequence, | ||
videoConfig, | ||
volumes, | ||
nonce, | ||
]); | ||
react_1.useEffect(() => { | ||
if (!audioRef.current) { | ||
throw new Error('No audio ref found'); | ||
} | ||
if (!videoConfig) { | ||
throw new Error('No video config found'); | ||
throw new Error('No video config found. <Audio> must be placed inside a composition.'); | ||
} | ||
const shouldBeTime = currentFrame / videoConfig.fps; | ||
const shouldBeTime = frame / videoConfig.fps; | ||
const isTime = audioRef.current.currentTime; | ||
const timeShift = Math.abs(shouldBeTime - isTime); | ||
if (timeShift > 0.5) { | ||
if (timeShift > 0.2 && !audioRef.current.ended) { | ||
console.log('Time has shifted by', timeShift, 'sec. Fixing...'); | ||
// If scrubbing around, adjust timing | ||
// or if time shift is bigger than 0.2sec | ||
audioRef.current.currentTime = shouldBeTime; | ||
} | ||
if (!playing /**1 */ || timeShift > 0.5 /**2 */) { | ||
if (!playing || absoluteFrame === 0) { | ||
// If scrubbing around, adjust timing | ||
// or if time shift is bigger than 0.2sec | ||
audioRef.current.currentTime = currentFrame / videoConfig.fps; | ||
audioRef.current.currentTime = shouldBeTime; | ||
} | ||
if (currentFrame === 0 && playing) { | ||
// If video ended, play it again | ||
if (audioRef.current.paused && !audioRef.current.ended && playing) { | ||
// Play audio | ||
audioRef.current.play(); | ||
} | ||
}, [currentFrame, playing, videoConfig]); | ||
return jsx_runtime_1.jsx("audio", Object.assign({ ref: audioRef }, props), void 0); | ||
}, [absoluteFrame, frame, playing, videoConfig]); | ||
return jsx_runtime_1.jsx("audio", Object.assign({ ref: audioRef }, nativeProps), void 0); | ||
}; | ||
exports.AudioForDevelopment = AudioForDevelopment; | ||
//# sourceMappingURL=AudioForDevelopment.js.map |
@@ -6,8 +6,24 @@ "use strict"; | ||
const CompositionManager_1 = require("../CompositionManager"); | ||
const is_remote_asset_1 = require("../is-remote-asset"); | ||
const random_1 = require("../random"); | ||
const sequencing_1 = require("../sequencing"); | ||
const use_frame_1 = require("../use-frame"); | ||
const volume_prop_1 = require("../volume-prop"); | ||
const use_audio_frame_1 = require("./use-audio-frame"); | ||
const AudioForRendering = (props) => { | ||
const absoluteFrame = use_frame_1.useAbsoluteCurrentFrame(); | ||
const sequenceFrame = use_frame_1.useCurrentFrame(); | ||
const audioFrame = use_audio_frame_1.useAudioFrame(); | ||
const frame = use_frame_1.useCurrentFrame(); | ||
const sequenceContext = react_1.useContext(sequencing_1.SequenceContext); | ||
const { registerAsset, unregisterAsset } = react_1.useContext(CompositionManager_1.CompositionManager); | ||
const [id] = react_1.useState(() => String(Math.random())); | ||
// Generate a string that's as unique as possible for this asset | ||
// but at the same time the same on all threads | ||
const id = react_1.useMemo(() => { | ||
var _a; | ||
return `audio-${random_1.random((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}-muted:${props.muted}`; | ||
}, [props.muted, props.src, sequenceContext]); | ||
const volume = volume_prop_1.evaluateVolume({ | ||
volume: props.volume, | ||
frame: audioFrame, | ||
}); | ||
react_1.useEffect(() => { | ||
@@ -17,2 +33,5 @@ if (!props.src) { | ||
} | ||
if (props.muted) { | ||
return; | ||
} | ||
registerAsset({ | ||
@@ -22,6 +41,10 @@ type: 'audio', | ||
id, | ||
sequenceFrame, | ||
frame: absoluteFrame, | ||
volume, | ||
isRemote: is_remote_asset_1.isRemoteAsset(props.src), | ||
mediaFrame: frame, | ||
}); | ||
return () => unregisterAsset(id); | ||
}, [ | ||
props.muted, | ||
props.src, | ||
@@ -32,3 +55,5 @@ registerAsset, | ||
unregisterAsset, | ||
sequenceFrame, | ||
volume, | ||
audioFrame, | ||
frame, | ||
]); | ||
@@ -35,0 +60,0 @@ return null; |
/// <reference types="react" /> | ||
export declare type RemotionAudioProps = Omit<React.DetailedHTMLProps<React.AudioHTMLAttributes<HTMLAudioElement>, HTMLAudioElement>, 'autoplay' | 'controls'>; | ||
import { VolumeProp } from '../volume-prop'; | ||
export declare type RemotionMainAudioProps = { | ||
startAt?: number; | ||
endAt?: number; | ||
}; | ||
export declare type RemotionAudioProps = Omit<React.DetailedHTMLProps<React.AudioHTMLAttributes<HTMLAudioElement>, HTMLAudioElement>, 'autoplay' | 'controls'> & { | ||
volume?: VolumeProp; | ||
}; | ||
//# sourceMappingURL=props.d.ts.map |
@@ -25,5 +25,7 @@ "use strict"; | ||
const CompositionManager_1 = require("./CompositionManager"); | ||
const nonce_1 = require("./nonce"); | ||
const register_root_1 = require("./register-root"); | ||
const Composition = ({ width, height, fps, durationInFrames, id, defaultProps: props, ...compProps }) => { | ||
const { registerComposition, unregisterComposition } = react_1.useContext(CompositionManager_1.CompositionManager); | ||
const nonce = nonce_1.useNonce(); | ||
const lazy = react_1.useMemo(() => { | ||
@@ -80,2 +82,3 @@ if ('lazyComponent' in compProps) { | ||
props, | ||
nonce, | ||
}); | ||
@@ -90,2 +93,3 @@ if (register_root_1.getIsEvaluation()) { | ||
width, | ||
nonce, | ||
}); | ||
@@ -107,2 +111,3 @@ } | ||
width, | ||
nonce, | ||
]); | ||
@@ -109,0 +114,0 @@ return null; |
@@ -10,4 +10,15 @@ /// <reference types="react" /> | ||
props?: T; | ||
nonce: number; | ||
}; | ||
export declare type TCompMetadata = Pick<TComposition, 'id' | 'height' | 'width' | 'fps' | 'durationInFrames'>; | ||
declare type EnhancedTSequenceData = { | ||
type: 'sequence'; | ||
} | { | ||
type: 'audio'; | ||
src: string; | ||
volume: string | number; | ||
} | { | ||
type: 'video'; | ||
src: string; | ||
}; | ||
export declare type TSequence = { | ||
@@ -19,3 +30,19 @@ from: number; | ||
parent: string | null; | ||
rootId: string; | ||
showInTimeline: boolean; | ||
nonce: number; | ||
} & EnhancedTSequenceData; | ||
export declare type TAsset = { | ||
type: 'audio' | 'video'; | ||
src: string; | ||
id: string; | ||
frame: number; | ||
volume: number; | ||
isRemote: boolean; | ||
mediaFrame: number; | ||
}; | ||
export declare type RenderAssetInfo = { | ||
assets: TAsset[][]; | ||
bundleDir: string; | ||
}; | ||
export declare type CompositionManagerContext = { | ||
@@ -29,5 +56,9 @@ compositions: TComposition[]; | ||
unregisterSequence: (id: string) => void; | ||
registerAsset: (asset: TAsset) => void; | ||
unregisterAsset: (id: string) => void; | ||
sequences: TSequence[]; | ||
assets: TAsset[]; | ||
}; | ||
export declare const CompositionManager: import("react").Context<CompositionManagerContext>; | ||
export {}; | ||
//# sourceMappingURL=CompositionManager.d.ts.map |
@@ -13,4 +13,7 @@ "use strict"; | ||
unregisterSequence: () => void 0, | ||
registerAsset: () => void 0, | ||
unregisterAsset: () => void 0, | ||
sequences: [], | ||
assets: [], | ||
}); | ||
//# sourceMappingURL=CompositionManager.js.map |
export declare type Browser = 'chrome' | 'firefox'; | ||
export declare const DEFAULT_BROWSER: Browser; | ||
export declare const FEATURE_FLAG_FIREFOX_SUPPORT = false; | ||
export declare const setBrowser: (browser: Browser) => void; | ||
export declare const getBrowser: () => "chrome" | "firefox" | null; | ||
//# sourceMappingURL=browser.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getBrowser = exports.setBrowser = exports.FEATURE_FLAG_FIREFOX_SUPPORT = exports.DEFAULT_BROWSER = void 0; | ||
exports.getBrowser = exports.setBrowser = exports.DEFAULT_BROWSER = void 0; | ||
exports.DEFAULT_BROWSER = 'chrome'; | ||
// There is no Firefox support yet, the waitForFunction method | ||
// does not yet work and downloading has a bug. | ||
// Disabling this for now! | ||
exports.FEATURE_FLAG_FIREFOX_SUPPORT = false; | ||
let currentBrowser = null; | ||
@@ -10,0 +6,0 @@ const setBrowser = (browser) => { |
@@ -1,2 +0,2 @@ | ||
declare const validCodecs: readonly ["h264", "h265", "vp8", "vp9"]; | ||
declare const validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav"]; | ||
export declare type Codec = typeof validCodecs[number]; | ||
@@ -3,0 +3,0 @@ export declare type CodecOrUndefined = Codec | undefined; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setCodec = exports.setOutputFormat = exports.getFinalOutputCodec = exports.DEFAULT_CODEC = exports.getOutputCodecOrUndefined = void 0; | ||
const validCodecs = ['h264', 'h265', 'vp8', 'vp9']; | ||
const validCodecs = [ | ||
'h264', | ||
'h265', | ||
'vp8', | ||
'vp9', | ||
'mp3', | ||
'aac', | ||
'wav', | ||
]; | ||
const validLegacyFormats = ['mp4', 'png-sequence']; | ||
@@ -21,6 +29,30 @@ let codec = undefined; | ||
if (emitWarning) { | ||
console.info('You have specified a .hevc extension, using it using H265 encoder.'); | ||
console.info('You have specified a .hevc extension, using the H265 encoder.'); | ||
} | ||
return 'h265'; | ||
} | ||
if (inputCodec === undefined && fileExtension === 'mp3') { | ||
if (emitWarning) { | ||
console.info('You have specified a .mp3 extension, using the MP3 encoder.'); | ||
} | ||
return 'mp3'; | ||
} | ||
if (inputCodec === undefined && fileExtension === 'wav') { | ||
if (emitWarning) { | ||
console.info('You have specified a .wav extension, using the WAV encoder.'); | ||
} | ||
return 'wav'; | ||
} | ||
if (inputCodec === undefined && fileExtension === 'aac') { | ||
if (emitWarning) { | ||
console.info('You have specified a .aac extension, using the AAC encoder.'); | ||
} | ||
return 'aac'; | ||
} | ||
if (inputCodec === undefined && fileExtension === 'm4a') { | ||
if (emitWarning) { | ||
console.info('You have specified a .m4a extension, using the AAC encoder.'); | ||
} | ||
return 'aac'; | ||
} | ||
return inputCodec !== null && inputCodec !== void 0 ? inputCodec : exports.DEFAULT_CODEC; | ||
@@ -27,0 +59,0 @@ }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getActualCrf = exports.validateSelectedCrfAndCodecCombination = exports.getValidCrfRanges = exports.getDefaultCrfForCodec = exports.getCrfOrUndefined = exports.setCrf = void 0; | ||
const is_audio_codec_1 = require("../is-audio-codec"); | ||
let currentCrf = undefined; | ||
@@ -17,2 +18,5 @@ const setCrf = (newCrf) => { | ||
const getDefaultCrfForCodec = (codec) => { | ||
if (is_audio_codec_1.isAudioCodec(codec)) { | ||
return 0; | ||
} | ||
if (codec === 'h264') { | ||
@@ -34,2 +38,5 @@ return 18; // FFMPEG default 23 | ||
const getValidCrfRanges = (codec) => { | ||
if (is_audio_codec_1.isAudioCodec(codec)) { | ||
return [0, 0]; | ||
} | ||
if (codec === 'h264') { | ||
@@ -59,5 +66,7 @@ return [0, 51]; | ||
var _a; | ||
return (_a = exports.getCrfOrUndefined()) !== null && _a !== void 0 ? _a : exports.getDefaultCrfForCodec(codec); | ||
const crf = (_a = exports.getCrfOrUndefined()) !== null && _a !== void 0 ? _a : exports.getDefaultCrfForCodec(codec); | ||
exports.validateSelectedCrfAndCodecCombination(crf, codec); | ||
return crf; | ||
}; | ||
exports.getActualCrf = getActualCrf; | ||
//# sourceMappingURL=crf.js.map |
@@ -71,3 +71,3 @@ "use strict"; | ||
for (const value of parsed) { | ||
if (typeof value !== 'number') { | ||
if (isNaN(value)) { | ||
throw new Error('--frames flag must be a single number, or 2 numbers separated by `-`'); | ||
@@ -74,0 +74,0 @@ } |
import { PixelFormat } from '.'; | ||
declare const validOptions: readonly ["png", "jpeg"]; | ||
declare const validOptions: readonly ["png", "jpeg", "none"]; | ||
export declare type ImageFormat = typeof validOptions[number]; | ||
export declare const setImageFormat: (format: ImageFormat) => void; | ||
export declare const getUserPreferredImageFormat: () => "png" | "jpeg" | undefined; | ||
export declare const getUserPreferredImageFormat: () => "none" | "png" | "jpeg" | undefined; | ||
export declare const validateSelectedPixelFormatAndImageFormatCombination: (pixelFormat: PixelFormat, imageFormat: ImageFormat) => void; | ||
export {}; | ||
//# sourceMappingURL=image-format.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validateSelectedPixelFormatAndImageFormatCombination = exports.getUserPreferredImageFormat = exports.setImageFormat = void 0; | ||
const validOptions = ['png', 'jpeg']; | ||
const validOptions = ['png', 'jpeg', 'none']; | ||
let currentImageFormat = undefined; | ||
@@ -22,2 +22,8 @@ const setImageFormat = (format) => { | ||
const validateSelectedPixelFormatAndImageFormatCombination = (pixelFormat, imageFormat) => { | ||
if (imageFormat === 'none') { | ||
return; | ||
} | ||
if (!validOptions.includes(imageFormat)) { | ||
throw new TypeError(`Value ${imageFormat} is not valid as an image format.`); | ||
} | ||
if (pixelFormat !== 'yuva420p') { | ||
@@ -24,0 +30,0 @@ return; |
@@ -46,3 +46,3 @@ import { Browser } from './browser'; | ||
*/ | ||
readonly setImageFormat: (format: "png" | "jpeg") => void; | ||
readonly setImageFormat: (format: "none" | "png" | "jpeg") => void; | ||
/** | ||
@@ -49,0 +49,0 @@ * Render only a subset of a video. |
@@ -27,2 +27,5 @@ "use strict"; | ||
const validateSelectedPixelFormatAndCodecCombination = (pixelFormat, codec) => { | ||
if (!validOptions.includes(pixelFormat)) { | ||
throw new TypeError(`Value ${pixelFormat} is not valid as a pixel format.`); | ||
} | ||
if (pixelFormat !== 'yuva420p') { | ||
@@ -32,3 +35,3 @@ return; | ||
if (codec !== 'vp8' && codec !== 'vp9') { | ||
throw new TypeError("Pixel format was set to 'yuva420p' but codec is not 'vp8' or 'vp8'. To render videos with alpha channel, you must choose a codec that supports it."); | ||
throw new TypeError("Pixel format was set to 'yuva420p' but codec is not 'vp8' or 'vp9'. To render videos with alpha channel, you must choose a codec that supports it."); | ||
} | ||
@@ -35,0 +38,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
export declare const getTimelineClipName: (children: React.ReactNode, i?: number) => string; | ||
export declare const getTimelineClipName: (children: React.ReactNode) => string; | ||
//# sourceMappingURL=get-timeline-clip-name.d.ts.map |
@@ -5,18 +5,21 @@ "use strict"; | ||
const react_1 = require("react"); | ||
const getTimelineClipName = (children, i = 0) => { | ||
const tree = react_1.Children.map(children, (ch) => { | ||
const getTimelineClipName = (children) => { | ||
var _a; | ||
const tree = (_a = react_1.Children.map(children, (ch) => { | ||
if (!react_1.isValidElement(ch)) | ||
return ''; | ||
return null; | ||
// Must be name, not ID | ||
const name = typeof ch.type !== 'string' && ch.type.name; | ||
const root = name ? ' '.repeat(i) + name : null; | ||
if (name) { | ||
return name; | ||
} | ||
if (ch.props.children) { | ||
const chName = exports.getTimelineClipName(ch.props.children, i + 1); | ||
return [root, chName].filter(Boolean).join('\n'); | ||
const chName = exports.getTimelineClipName(ch.props.children); | ||
return chName; | ||
} | ||
return root; | ||
}); | ||
return tree ? tree.filter(Boolean).join('\n') : ''; | ||
return null; | ||
})) === null || _a === void 0 ? void 0 : _a.filter(Boolean); | ||
return (tree === null || tree === void 0 ? void 0 : tree.length) ? tree[0] : ''; | ||
}; | ||
exports.getTimelineClipName = getTimelineClipName; | ||
//# sourceMappingURL=get-timeline-clip-name.js.map |
import React from 'react'; | ||
export declare const IFrame: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.IframeHTMLAttributes<HTMLIFrameElement>, HTMLIFrameElement>, "style" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "slot" | "spellCheck" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "height" | "width" | "key" | "allow" | "allowFullScreen" | "allowTransparency" | "frameBorder" | "loading" | "marginHeight" | "marginWidth" | "name" | "referrerPolicy" | "sandbox" | "scrolling" | "seamless" | "src" | "srcDoc"> & React.RefAttributes<HTMLIFrameElement>>; | ||
export declare const IFrame: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.IframeHTMLAttributes<HTMLIFrameElement>, HTMLIFrameElement>, "id" | "height" | "width" | "children" | "key" | "src" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "name" | "allow" | "allowFullScreen" | "allowTransparency" | "frameBorder" | "loading" | "marginHeight" | "marginWidth" | "referrerPolicy" | "sandbox" | "scrolling" | "seamless" | "srcDoc"> & React.RefAttributes<HTMLIFrameElement>>; | ||
//# sourceMappingURL=IFrame.d.ts.map |
import React from 'react'; | ||
export declare const Img: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "style" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "slot" | "spellCheck" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "height" | "width" | "key" | "loading" | "referrerPolicy" | "src" | "alt" | "crossOrigin" | "decoding" | "sizes" | "srcSet" | "useMap"> & React.RefAttributes<HTMLImageElement>>; | ||
export declare const Img: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "id" | "height" | "width" | "children" | "key" | "crossOrigin" | "src" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "loading" | "referrerPolicy" | "alt" | "decoding" | "sizes" | "srcSet" | "useMap"> & React.RefAttributes<HTMLImageElement>>; | ||
//# sourceMappingURL=Img.d.ts.map |
@@ -9,2 +9,8 @@ "use strict"; | ||
const [handle] = react_1.useState(() => ready_manager_1.delayRender()); | ||
react_1.useEffect(() => { | ||
if (ref && | ||
ref.current.complete) { | ||
ready_manager_1.continueRender(handle); | ||
} | ||
}, [handle, ref]); | ||
const didLoad = react_1.useCallback((e) => { | ||
@@ -11,0 +17,0 @@ ready_manager_1.continueRender(handle); |
@@ -5,3 +5,5 @@ import './asset-types'; | ||
export * from './Composition'; | ||
export { TAsset } from './CompositionManager'; | ||
export * from './config'; | ||
export { getInputProps } from './config/input-props'; | ||
export * from './easing'; | ||
@@ -8,0 +10,0 @@ export * from './IFrame'; |
@@ -13,3 +13,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Sequence = exports.registerRoot = void 0; | ||
exports.Sequence = exports.registerRoot = exports.getInputProps = void 0; | ||
require("./asset-types"); | ||
@@ -20,2 +20,4 @@ __exportStar(require("./AbsoluteFill"), exports); | ||
__exportStar(require("./config"), exports); | ||
var input_props_1 = require("./config/input-props"); | ||
Object.defineProperty(exports, "getInputProps", { enumerable: true, get: function () { return input_props_1.getInputProps; } }); | ||
__exportStar(require("./easing"), exports); | ||
@@ -22,0 +24,0 @@ __exportStar(require("./IFrame"), exports); |
/// <reference types="react" /> | ||
import { TCompMetadata, TComposition, TSequence } from './CompositionManager'; | ||
import { RenderAssetInfo, TAsset, TCompMetadata, TComposition, TSequence } from './CompositionManager'; | ||
import { WebpackOverrideFn } from './config/override-webpack'; | ||
import * as perf from './perf'; | ||
import * as Timeline from './timeline-position-state'; | ||
import { TimelineContextValue } from './timeline-position-state'; | ||
import { truthy } from './truthy'; | ||
export declare const Internals: { | ||
@@ -25,3 +27,3 @@ perf: typeof perf; | ||
getShouldOutputImageSequence: () => boolean; | ||
validateSelectedCrfAndCodecCombination: (crf: number, codec: "h264" | "h265" | "vp8" | "vp9") => void; | ||
validateSelectedCrfAndCodecCombination: (crf: number, codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav") => void; | ||
getFinalOutputCodec: ({ codec: inputCodec, fileExtension, emitWarning, }: { | ||
@@ -31,19 +33,22 @@ codec: import("./config/codec").CodecOrUndefined; | ||
emitWarning: boolean; | ||
}) => "h264" | "h265" | "vp8" | "vp9"; | ||
DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9"; | ||
}) => "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav"; | ||
DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav"; | ||
DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le"; | ||
FEATURE_FLAG_FIREFOX_SUPPORT: boolean; | ||
DEFAULT_WEBPACK_CACHE_ENABLED: boolean; | ||
FEATURE_FLAG_V2_BREAKING_CHANGES: boolean; | ||
getBrowser: () => "chrome" | "firefox" | null; | ||
DEFAULT_BROWSER: import("./config/browser").Browser; | ||
getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9") => number; | ||
getActualCrf: (codec: "h264" | "h265" | "vp8" | "vp9") => number; | ||
getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav") => number; | ||
getActualCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav") => number; | ||
setFrameRangeFromCli: (newFrameRange: string | number) => void; | ||
getUserPreferredImageFormat: () => "png" | "jpeg" | undefined; | ||
validateSelectedPixelFormatAndImageFormatCombination: (pixelFormat: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le", imageFormat: "png" | "jpeg") => void; | ||
validateSelectedPixelFormatAndCodecCombination: (pixelFormat: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le", codec: "h264" | "h265" | "vp8" | "vp9") => void; | ||
getUserPreferredImageFormat: () => "png" | "jpeg" | "none" | undefined; | ||
validateSelectedPixelFormatAndImageFormatCombination: (pixelFormat: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le", imageFormat: "png" | "jpeg" | "none") => void; | ||
validateSelectedPixelFormatAndCodecCombination: (pixelFormat: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le", codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav") => void; | ||
validateFrameRange: (frameRange: number | [number, number] | null) => void; | ||
getWebpackCaching: () => boolean; | ||
truthy: typeof truthy; | ||
isAudioCodec: (codec: import("./config/codec").CodecOrUndefined) => boolean; | ||
}; | ||
export type { TComposition, Timeline, TCompMetadata, TSequence, WebpackOverrideFn, }; | ||
export type { TComposition, Timeline, TCompMetadata, TSequence, WebpackOverrideFn, TAsset, RenderAssetInfo, TimelineContextValue, }; | ||
//# sourceMappingURL=internals.d.ts.map |
@@ -37,2 +37,4 @@ "use strict"; | ||
const webpack_caching_1 = require("./config/webpack-caching"); | ||
const feature_flags_1 = require("./feature-flags"); | ||
const is_audio_codec_1 = require("./is-audio-codec"); | ||
const perf = __importStar(require("./perf")); | ||
@@ -42,2 +44,3 @@ const register_root_1 = require("./register-root"); | ||
const Timeline = __importStar(require("./timeline-position-state")); | ||
const truthy_1 = require("./truthy"); | ||
const use_unsafe_video_config_1 = require("./use-unsafe-video-config"); | ||
@@ -70,4 +73,5 @@ const use_video_1 = require("./use-video"); | ||
DEFAULT_PIXEL_FORMAT: pixel_format_1.DEFAULT_PIXEL_FORMAT, | ||
FEATURE_FLAG_FIREFOX_SUPPORT: browser_1.FEATURE_FLAG_FIREFOX_SUPPORT, | ||
FEATURE_FLAG_FIREFOX_SUPPORT: feature_flags_1.FEATURE_FLAG_FIREFOX_SUPPORT, | ||
DEFAULT_WEBPACK_CACHE_ENABLED: webpack_caching_1.DEFAULT_WEBPACK_CACHE_ENABLED, | ||
FEATURE_FLAG_V2_BREAKING_CHANGES: feature_flags_1.FEATURE_FLAG_V2_BREAKING_CHANGES, | ||
getBrowser: browser_1.getBrowser, | ||
@@ -83,3 +87,5 @@ DEFAULT_BROWSER: browser_1.DEFAULT_BROWSER, | ||
getWebpackCaching: webpack_caching_1.getWebpackCaching, | ||
truthy: truthy_1.truthy, | ||
isAudioCodec: is_audio_codec_1.isAudioCodec, | ||
}; | ||
//# sourceMappingURL=internals.js.map |
@@ -79,4 +79,4 @@ "use strict"; | ||
for (let i = 1; i < arr.length; ++i) { | ||
if (!(arr[i] >= arr[i - 1])) { | ||
throw new Error(`inputRange must be monotonically non-decreasing but got [${arr.join(',')}]`); | ||
if (!(arr[i] > arr[i - 1])) { | ||
throw new Error(`inputRange must be strictly monotonically non-decreasing but got [${arr.join(',')}]`); | ||
} | ||
@@ -83,0 +83,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { TCompMetadata } from './CompositionManager'; | ||
import { TAsset, TCompMetadata } from './CompositionManager'; | ||
export declare const delayRender: () => number; | ||
@@ -9,4 +9,5 @@ export declare const continueRender: (handle: number) => void; | ||
remotion_setFrame: (frame: number) => void; | ||
remotion_collectAssets: () => TAsset[]; | ||
} | ||
} | ||
//# sourceMappingURL=ready-manager.d.ts.map |
@@ -7,4 +7,6 @@ "use strict"; | ||
const CompositionManager_1 = require("./CompositionManager"); | ||
const nonce_1 = require("./nonce"); | ||
const random_1 = require("./random"); | ||
const ready_manager_1 = require("./ready-manager"); | ||
const timeline_position_state_1 = require("./timeline-position-state"); | ||
const ready_manager_1 = require("./ready-manager"); | ||
const RemotionRoot = ({ children }) => { | ||
@@ -15,5 +17,8 @@ // Wontfix, expected to have | ||
const [currentComposition, setCurrentComposition] = react_1.useState(typeof window !== 'undefined' ? window.location.pathname.substr(1) : null); | ||
const [remotionRootId] = react_1.useState(() => String(random_1.random(null))); | ||
const [sequences, setSequences] = react_1.useState([]); | ||
const [assets, setAssets] = react_1.useState([]); | ||
const [frame, setFrame] = react_1.useState(0); | ||
const [playing, setPlaying] = react_1.useState(false); | ||
const [fastRefreshes, setFastRefreshes] = react_1.useState(0); | ||
react_1.useLayoutEffect(() => { | ||
@@ -28,2 +33,10 @@ if (typeof window !== 'undefined') { | ||
}, []); | ||
react_1.useLayoutEffect(() => { | ||
if (typeof window !== 'undefined') { | ||
window.remotion_collectAssets = () => { | ||
setAssets([]); // clear assets at next render | ||
return assets; | ||
}; | ||
} | ||
}, [assets]); | ||
const registerComposition = react_1.useCallback((comp) => { | ||
@@ -34,3 +47,3 @@ setCompositions((comps) => { | ||
} | ||
return [...comps, comp]; | ||
return [...comps, comp].slice().sort((a, b) => a.nonce - b.nonce); | ||
}); | ||
@@ -51,2 +64,12 @@ }, []); | ||
}, []); | ||
const registerAsset = react_1.useCallback((asset) => { | ||
setAssets((assts) => { | ||
return [...assts, asset]; | ||
}); | ||
}, []); | ||
const unregisterAsset = react_1.useCallback((id) => { | ||
setAssets((assts) => { | ||
return assts.filter((a) => a.id !== id); | ||
}); | ||
}, []); | ||
const contextValue = react_1.useMemo(() => { | ||
@@ -61,3 +84,6 @@ return { | ||
unregisterSequence, | ||
registerAsset, | ||
unregisterAsset, | ||
sequences, | ||
assets, | ||
}; | ||
@@ -69,5 +95,8 @@ }, [ | ||
registerSequence, | ||
sequences, | ||
unregisterComposition, | ||
unregisterSequence, | ||
registerAsset, | ||
unregisterAsset, | ||
sequences, | ||
assets, | ||
]); | ||
@@ -78,4 +107,5 @@ const timelineContextValue = react_1.useMemo(() => { | ||
playing, | ||
rootId: remotionRootId, | ||
}; | ||
}, [frame, playing]); | ||
}, [frame, playing, remotionRootId]); | ||
const setTimelineContextValue = react_1.useMemo(() => { | ||
@@ -87,5 +117,21 @@ return { | ||
}, []); | ||
return (jsx_runtime_1.jsx(timeline_position_state_1.TimelineContext.Provider, Object.assign({ value: timelineContextValue }, { children: jsx_runtime_1.jsx(timeline_position_state_1.SetTimelineContext.Provider, Object.assign({ value: setTimelineContextValue }, { children: jsx_runtime_1.jsx(CompositionManager_1.CompositionManager.Provider, Object.assign({ value: contextValue }, { children: children }), void 0) }), void 0) }), void 0)); | ||
const nonceContext = react_1.useMemo(() => { | ||
let counter = 0; | ||
return { | ||
getNonce: () => counter++, | ||
fastRefreshes, | ||
}; | ||
}, [fastRefreshes]); | ||
react_1.useEffect(() => { | ||
if (module.hot) { | ||
module.hot.addStatusHandler((status) => { | ||
if (status === 'idle') { | ||
setFastRefreshes((i) => i + 1); | ||
} | ||
}); | ||
} | ||
}, []); | ||
return (jsx_runtime_1.jsx(nonce_1.NonceContext.Provider, Object.assign({ value: nonceContext }, { children: jsx_runtime_1.jsx(timeline_position_state_1.TimelineContext.Provider, Object.assign({ value: timelineContextValue }, { children: jsx_runtime_1.jsx(timeline_position_state_1.SetTimelineContext.Provider, Object.assign({ value: setTimelineContextValue }, { children: jsx_runtime_1.jsx(CompositionManager_1.CompositionManager.Provider, Object.assign({ value: contextValue }, { children: children }), void 0) }), void 0) }), void 0) }), void 0)); | ||
}; | ||
exports.RemotionRoot = RemotionRoot; | ||
//# sourceMappingURL=RemotionRoot.js.map |
import React from 'react'; | ||
declare type SequenceContextType = { | ||
from: number; | ||
cumulatedFrom: number; | ||
relativeFrom: number; | ||
parentFrom: number; | ||
durationInFrames: number; | ||
@@ -14,4 +16,5 @@ id: string; | ||
layout?: 'absolute-fill' | 'none'; | ||
showInTimeline?: boolean; | ||
}>; | ||
export {}; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -7,14 +7,20 @@ "use strict"; | ||
const CompositionManager_1 = require("../CompositionManager"); | ||
const feature_flags_1 = require("../feature-flags"); | ||
const get_timeline_clip_name_1 = require("../get-timeline-clip-name"); | ||
const nonce_1 = require("../nonce"); | ||
const timeline_position_state_1 = require("../timeline-position-state"); | ||
const use_frame_1 = require("../use-frame"); | ||
const use_unsafe_video_config_1 = require("../use-unsafe-video-config"); | ||
exports.SequenceContext = react_1.createContext(null); | ||
const Sequence = ({ from, durationInFrames, children, name, layout = 'absolute-fill' }) => { | ||
var _a; | ||
const Sequence = ({ from, durationInFrames, children, name, layout = 'absolute-fill', showInTimeline = true, }) => { | ||
const [id] = react_1.useState(() => String(Math.random())); | ||
const absoluteFrame = use_frame_1.useAbsoluteCurrentFrame(); | ||
const parentSequence = react_1.useContext(exports.SequenceContext); | ||
const actualFrom = ((_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.from) !== null && _a !== void 0 ? _a : 0) + from; | ||
const { registerSequence, unregisterSequence } = react_1.useContext(CompositionManager_1.CompositionManager); | ||
const { rootId } = react_1.useContext(timeline_position_state_1.TimelineContext); | ||
const cumulatedFrom = parentSequence | ||
? parentSequence.cumulatedFrom + parentSequence.relativeFrom | ||
: 0; | ||
const actualFrom = cumulatedFrom + from; | ||
const nonce = nonce_1.useNonce(); | ||
if (layout !== 'absolute-fill' && layout !== 'none') { | ||
throw new TypeError(`The layout prop of <Composition /> expects either "absolute-fill" or "none", but you passed: ${layout}`); | ||
throw new TypeError(`The layout prop of <Sequence /> expects either "absolute-fill" or "none", but you passed: ${layout}`); | ||
} | ||
@@ -30,9 +36,29 @@ if (typeof durationInFrames !== 'number') { | ||
} | ||
const absoluteFrame = use_frame_1.useAbsoluteCurrentFrame(); | ||
const unsafeVideoConfig = use_unsafe_video_config_1.useUnsafeVideoConfig(); | ||
const compositionDuration = unsafeVideoConfig | ||
? unsafeVideoConfig.durationInFrames | ||
: 0; | ||
const actualDurationInFrames = Math.min(compositionDuration - from, parentSequence | ||
? Math.min(parentSequence.durationInFrames + | ||
(parentSequence.cumulatedFrom + parentSequence.relativeFrom) - | ||
actualFrom, durationInFrames) | ||
: durationInFrames); | ||
const { registerSequence, unregisterSequence } = react_1.useContext(CompositionManager_1.CompositionManager); | ||
const contextValue = react_1.useMemo(() => { | ||
var _a; | ||
return { | ||
from: actualFrom, | ||
durationInFrames, | ||
cumulatedFrom, | ||
relativeFrom: from, | ||
durationInFrames: actualDurationInFrames, | ||
parentFrom: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom) !== null && _a !== void 0 ? _a : 0, | ||
id, | ||
}; | ||
}, [actualFrom, durationInFrames, id]); | ||
}, [ | ||
cumulatedFrom, | ||
from, | ||
actualDurationInFrames, | ||
parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom, | ||
id, | ||
]); | ||
const timelineClipName = react_1.useMemo(() => { | ||
@@ -44,7 +70,11 @@ return name !== null && name !== void 0 ? name : get_timeline_clip_name_1.getTimelineClipName(children); | ||
registerSequence({ | ||
from: actualFrom, | ||
duration: durationInFrames, | ||
from, | ||
duration: actualDurationInFrames, | ||
id, | ||
displayName: timelineClipName, | ||
parent: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id) !== null && _a !== void 0 ? _a : null, | ||
type: 'sequence', | ||
rootId, | ||
showInTimeline, | ||
nonce, | ||
}); | ||
@@ -63,6 +93,17 @@ return () => { | ||
parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id, | ||
actualDurationInFrames, | ||
rootId, | ||
from, | ||
showInTimeline, | ||
nonce, | ||
]); | ||
const endThreshold = (() => { | ||
if (feature_flags_1.FEATURE_FLAG_V2_BREAKING_CHANGES) { | ||
return actualFrom + durationInFrames - 1; | ||
} | ||
return actualFrom + durationInFrames; | ||
})(); | ||
const content = absoluteFrame < actualFrom | ||
? null | ||
: absoluteFrame > actualFrom + durationInFrames | ||
: absoluteFrame > endThreshold | ||
? null | ||
@@ -69,0 +110,0 @@ : children; |
@@ -12,5 +12,64 @@ "use strict"; | ||
}); | ||
test('It should throw if multiple components have the same id', () => { | ||
test('It should throw if height is a negative number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: -100, width: 100, id: "id" }, void 0) }, void 0)), /The "height" of a composition must be positive, but got -100./); | ||
}); | ||
test('It should throw if height=0 is boundary off-point', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 0, width: 100, id: "id" }, void 0) }, void 0)), /The "height" of a composition must be positive, but got 0./); | ||
}); | ||
test('It should not throw if height is a positive number', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 100, width: 100, id: "id" }, void 0))).not.toThrow(); | ||
}); | ||
test('It should not throw if height=1 is boundary on-point', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 1, width: 100, id: "id" }, void 0))).not.toThrow(); | ||
}); | ||
test('It should throw if height is not a number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, | ||
// @ts-expect-error | ||
height: '100', width: 100, id: "id" }, void 0) }, void 0)), /The "height" of a composition must be a number, but you passed a string/); | ||
}); | ||
test('It should throw if width is a negative number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 100, width: -100, id: "id" }, void 0) }, void 0)), /The "width" of a composition must be positive, but got -100./); | ||
}); | ||
test('It should throw if width=0 is boundary off-point', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 100, width: 0, id: "id" }, void 0) }, void 0)), /The "width" of a composition must be positive, but got 0./); | ||
}); | ||
test('It should not throw if width is a positive number', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 100, width: 100, id: "id" }, void 0))).not.toThrow(); | ||
}); | ||
test('It should not throw if width=1 is boundary on-point', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 100, width: 1, id: "id" }, void 0))).not.toThrow(); | ||
}); | ||
test('It should throw if width is not a number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 30, height: 100, | ||
// @ts-expect-error | ||
width: '100', id: "id" }, void 0) }, void 0)), /The "width" of a composition must be a number, but you passed a string/); | ||
}); | ||
test('It should throw if durationInFrames of a composition is a negative number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: -100, fps: 30, height: 100, width: 100, id: "id" }, void 0) }, void 0)), /The "durationInFrames" of a composition must be positive, but got -100./); | ||
}); | ||
test('It should throw if durationInFrames=0 of a composition is boundary off-point', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 0, fps: 30, height: 100, width: 100, id: "id" }, void 0) }, void 0)), /The "durationInFrames" of a composition must be positive, but got 0./); | ||
}); | ||
test('It should not throw if durationInFrames=1 of a composition is boundary on-point', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 1, fps: 30, height: 100, width: 100, id: "id" }, void 0))).not.toThrow(); | ||
}); | ||
test('It should throw if durationInFrames of a composition is not a number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), | ||
// @ts-expect-error | ||
durationInFrames: '100', fps: 30, height: 100, width: 100, id: "id" }, void 0) }, void 0)), /The "durationInFrames" of a composition must be a number, but you passed a string/); | ||
}); | ||
test('It should throw if fps is of a composition is negative', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: -30, height: 100, width: 100, id: "id" }, void 0) }, void 0)), /The "fps" of a composition must be positive, but got -30./); | ||
}); | ||
test('It should throw if fps=0 of a composition is boundary off-point', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 0, height: 100, width: 100, id: "id" }, void 0) }, void 0)), /The "fps" of a composition must be positive, but got 0./); | ||
}); | ||
test('It should not throw if fps=1 of a composition is boundary on-point', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, fps: 1, height: 100, width: 100, id: "id" }, void 0))).not.toThrow(); | ||
}); | ||
test('It should throw if fps of a composition is not a number', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render(jsx_runtime_1.jsx(RemotionRoot_1.RemotionRoot, { children: jsx_runtime_1.jsx(__1.Composition, { lazyComponent: () => Promise.resolve({ default: AnyComp }), durationInFrames: 100, | ||
// @ts-expect-error | ||
fps: '30', height: 100, width: 100, id: "id" }, void 0) }, void 0)), /The "fps" of a composition must be a number, but you passed a string/); | ||
}); | ||
//# sourceMappingURL=composition-validation.test.js.map |
@@ -9,2 +9,4 @@ "use strict"; | ||
expect(interpolate_1.interpolate(Math.PI, [0, 1, 4, 9], [0, 2, 1000, -1000])).toEqual(714.4364894275378); | ||
expect(interpolate_1.interpolate(Infinity, [0, 1], [0, 2])).toEqual(Infinity); | ||
expect(interpolate_1.interpolate(Infinity, [0, 1], [1, 0])).toEqual(-Infinity); | ||
}); | ||
@@ -16,29 +18,41 @@ test('Must be the same length', () => { | ||
}); | ||
test('Test against Infinity values', () => { | ||
test('Must pass at least 2 elements for input range', () => { | ||
expect_to_throw_1.expectToThrow(() => { | ||
interpolate_1.interpolate(1, [-Infinity, Infinity], [0, 2]); | ||
}, /inputRange must contain only finite numbers, but got \[-Infinity,Infinity\]/); | ||
}); | ||
test('Must pass at least 2 elements', () => { | ||
expect_to_throw_1.expectToThrow(() => { | ||
interpolate_1.interpolate(1, [0], [9]); | ||
}, /inputRange must have at least 2 elements/); | ||
}); | ||
test('Input range must be monotonically non-decreasing', () => { | ||
test('Input range must be strictly monotonically non-decreasing', () => { | ||
expect_to_throw_1.expectToThrow(() => { | ||
interpolate_1.interpolate(1, [0, 1, 0.5], [0, 2, 0.2]); | ||
}, /inputRange must be monotonically non-decreasing/); | ||
}, /inputRange must be strictly monotonically non-decreasing/); | ||
expect_to_throw_1.expectToThrow(() => { | ||
interpolate_1.interpolate(0.75, [0, 1, 1], [0, 2, 0]); | ||
}, /inputRange must be strictly monotonically non-decreasing/); | ||
}); | ||
test('Output range can be monotonically decreasing', () => { | ||
test('Output range can be non-monotonic', () => { | ||
expect(interpolate_1.interpolate(0.75, [0, 0.5, 1], [0, 2, 0])).toEqual(1); | ||
}); | ||
test('Output range monotonically decreasing', () => { | ||
expect(interpolate_1.interpolate(0.75, [0, 0.5, 1], [0, 2, 2])).toEqual(2); | ||
}); | ||
test('Cannot have Infinity in input range', () => { | ||
expect_to_throw_1.expectToThrow(() => { | ||
interpolate_1.interpolate(1, [-Infinity, 0], [0, 2]); | ||
}, /inputRange must contain only finite numbers, but got \[-Infinity,0\]/); | ||
}); | ||
test('Cannot have Infinity in output Range', () => { | ||
expect_to_throw_1.expectToThrow(() => interpolate_1.interpolate(1, [0, 1], [Infinity, 2]), /outputRange must contain only finite numbers, but got \[Infinity,2\]/); | ||
}); | ||
test('Should throw if passing 2x infinity', () => { | ||
test('Should throw if passing 2x infinity input range', () => { | ||
expect_to_throw_1.expectToThrow(() => interpolate_1.interpolate(1, [Infinity, Infinity], [0, 2]), /inputRange must contain only finite numbers, but got \[Infinity,Infinity\]/); | ||
}); | ||
test('Should throw if passing 2x infinity output range', () => { | ||
expect_to_throw_1.expectToThrow(() => interpolate_1.interpolate(1, [0, 1], [-Infinity, Infinity]), /outputRange must contain only finite numbers, but got \[-Infinity,Infinity\]/); | ||
}); | ||
test('Should throw on Infinity as third argument', () => { | ||
expect_to_throw_1.expectToThrow(() => interpolate_1.interpolate(1, [0, 1, Infinity], [0, 2, 3]), /inputRange must contain only finite numbers, but got \[0,1,Infinity\]/); | ||
}); | ||
test('Should throw on Infinity as third argument', () => { | ||
expect_to_throw_1.expectToThrow(() => interpolate_1.interpolate(1, [0, 1, Infinity], [0, 2, 3]), /inputRange must contain only finite numbers, but got \[0,1,Infinity\]/); | ||
}); | ||
test('Easing test', () => { | ||
@@ -50,17 +64,25 @@ expect(interpolate_1.interpolate(0.5, [0, 1], [0, 1], { | ||
test('Extrapolation left test', () => { | ||
expect(interpolate_1.interpolate(-3, [0, 1, 2], [0, 0.5, 1], { | ||
extrapolateRight: 'extend', | ||
})).toEqual(-1.5); | ||
expect(interpolate_1.interpolate(-3, [0, 1, 2], [0, 0.5, 1])).toEqual(-1.5); | ||
const testValues = ['extend', undefined]; | ||
testValues.forEach((entry) => { | ||
expect(interpolate_1.interpolate(-3, [0, 1, 2], [0, 0.5, 1], { | ||
extrapolateRight: entry, | ||
})).toEqual(-1.5); | ||
}); | ||
}); | ||
test('Extrapolation right test', () => { | ||
expect(interpolate_1.interpolate(3, [0, 1, 2], [0, 0.5, 1], { | ||
extrapolateRight: 'extend', | ||
})).toEqual(1.5); | ||
expect(interpolate_1.interpolate(3, [0, 1, 2], [0, 0.5, 1])).toEqual(1.5); | ||
const testValues = ['extend', undefined]; | ||
testValues.forEach((entry) => { | ||
expect(interpolate_1.interpolate(3, [0, 1, 2], [0, 0.5, 1], { | ||
extrapolateRight: entry, | ||
})).toEqual(1.5); | ||
}); | ||
}); | ||
test('Extrapolation identity', () => { | ||
expect(interpolate_1.interpolate(1000, [0, 1, 2], [0, 2, 4], { | ||
extrapolateRight: 'identity', | ||
})).toBe(1000); | ||
const testValues = [ | ||
[1000, { extrapolateRight: 'identity' }], | ||
[-1000, { extrapolateLeft: 'identity' }], | ||
]; | ||
testValues.forEach((entry) => { | ||
expect(interpolate_1.interpolate(entry[0], [0, 1, 2], [0, 2, 4], entry[1])).toBe(entry[0]); | ||
}); | ||
}); | ||
@@ -78,6 +100,11 @@ test('Clamp right test', () => { | ||
test('Zig-zag test', () => { | ||
expect(interpolate_1.interpolate(3.5, [1, 2, 3, 4, 5], [0, 1000, 0, -1000, 1000])).toBe(-500); | ||
expect(interpolate_1.interpolate(4, [1, 2, 3, 4, 5], [0, 1000, 0, -1000, 1000])).toBe(-1000); | ||
expect(interpolate_1.interpolate(6, [1, 2, 3, 4, 5], [0, 1000, 0, -1000, 1000])).toBe(3000); | ||
expect(interpolate_1.interpolate(-0.1, [1, 2, 3, 4, 5], [0, 1000, 0, -1000, 1000])).toBe(-1100); | ||
const testValues = [ | ||
[3.5, -500], | ||
[4, -1000], | ||
[6, 3000], | ||
[-0.1, -1100], | ||
]; | ||
testValues.forEach((entry) => { | ||
expect(interpolate_1.interpolate(entry[0], [1, 2, 3, 4, 5], [0, 1000, 0, -1000, 1000])).toBe(entry[1]); | ||
}); | ||
}); | ||
@@ -90,2 +117,4 @@ test('Handle bad types', () => { | ||
// @ts-expect-error | ||
expect(() => interpolate_1.interpolate('1', [0, 1], [1, 0])).toThrowError(/Cannot interpolation an input which is not a number/); | ||
// @ts-expect-error | ||
expect(() => interpolate_1.interpolate(1, 'string', 'string')).toThrowError(/inputRange must contain only numbers/); | ||
@@ -92,0 +121,0 @@ // @ts-expect-error |
@@ -20,2 +20,3 @@ "use strict"; | ||
const { queryByText } = react_1.render(jsx_runtime_1.jsx(timeline_position_state_1.TimelineContext.Provider, Object.assign({ value: { | ||
rootId: 'hi', | ||
frame: 40, | ||
@@ -26,2 +27,62 @@ playing: false, | ||
}); | ||
test('Negative offset test', () => { | ||
const NestedChild = () => { | ||
const frame = use_frame_1.useCurrentFrame(); | ||
return jsx_runtime_1.jsx("div", { children: 'frame' + frame }, void 0); | ||
}; | ||
const { queryByText } = react_1.render(jsx_runtime_1.jsx(timeline_position_state_1.TimelineContext.Provider, Object.assign({ value: { | ||
frame: 40, | ||
playing: false, | ||
rootId: 'hi', | ||
} }, { children: jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: -200, durationInFrames: 300 }, { children: jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: 10, durationInFrames: 300 }, { children: jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: 10, durationInFrames: 300 }, { children: jsx_runtime_1.jsx(NestedChild, {}, void 0) }), void 0) }), void 0) }), void 0) }), void 0)); | ||
const result = queryByText(/^frame220/i); | ||
expect(result).not.toBe(null); | ||
}); | ||
test('Nested negative offset test', () => { | ||
const NestedChild = () => { | ||
const frame = use_frame_1.useCurrentFrame(); | ||
return jsx_runtime_1.jsx("div", { children: 'frame' + frame }, void 0); | ||
}; | ||
const startAt = 40; | ||
const endAt = 90; | ||
const content = (jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: 0 - startAt, durationInFrames: endAt }, { children: jsx_runtime_1.jsx(NestedChild, {}, void 0) }), void 0)); | ||
const getForFrame = (frame) => { | ||
const { queryByText } = react_1.render(jsx_runtime_1.jsx(timeline_position_state_1.TimelineContext.Provider, Object.assign({ value: { | ||
frame, | ||
playing: false, | ||
rootId: 'hi', | ||
} }, { children: content }), void 0)); | ||
return queryByText; | ||
}; | ||
const frame0 = getForFrame(0); | ||
expect(frame0(/^frame40$/i)).not.toBe(null); | ||
const frame39 = getForFrame(39); | ||
expect(frame39(/^frame79$/i)).not.toBe(null); | ||
const frame50 = getForFrame(50); | ||
expect(frame50(/^frame90$/i)).toBe(null); | ||
}); | ||
test('Negative offset edge case', () => { | ||
const NestedChild = () => { | ||
const frame = use_frame_1.useCurrentFrame(); | ||
return jsx_runtime_1.jsx("div", { children: 'frame' + frame }, void 0); | ||
}; | ||
const startAt = 40; | ||
const endAt = 90; | ||
const content = (jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: 40, durationInFrames: Infinity }, { children: jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ from: 0 - startAt, durationInFrames: endAt }, { children: jsx_runtime_1.jsx(NestedChild, {}, void 0) }), void 0) }), void 0)); | ||
const getForFrame = (frame) => { | ||
const { queryByText } = react_1.render(jsx_runtime_1.jsx(timeline_position_state_1.TimelineContext.Provider, Object.assign({ value: { | ||
frame, | ||
playing: false, | ||
rootId: 'hi', | ||
} }, { children: content }), void 0)); | ||
return queryByText; | ||
}; | ||
expect(getForFrame(0)(/^frame/i)).toBe(null); | ||
expect(getForFrame(10)(/^frame/i)).toBe(null); | ||
expect(getForFrame(40)(/^frame40$/i)).not.toBe(null); | ||
const atFrame80 = getForFrame(80)(/^frame80$/i); | ||
expect(atFrame80).not.toBe(null); | ||
const atFrame90 = getForFrame(90)(/^frame90$/i); | ||
expect(atFrame90).toBe(null); | ||
}); | ||
//# sourceMappingURL=nested-sequences.test.js.map |
@@ -6,3 +6,3 @@ "use strict"; | ||
const expect_to_throw_1 = require("./expect-to-throw"); | ||
test('Frame range tests', () => { | ||
test('Frame range should throw exception with invalid inputs', () => { | ||
expect_to_throw_1.expectToThrow(() => frame_range_1.setFrameRange(-1), /non-negative/); | ||
@@ -27,2 +27,4 @@ expect_to_throw_1.expectToThrow(() => frame_range_1.setFrameRange(1.111), /Frame must be an integer, but got a float \(1.111\)/); | ||
() => frame_range_1.setFrameRange('10'), /Frame range must be a number or a tuple of numbers, but got object of type string/); | ||
}); | ||
test('Frame range tests with valid inputs', () => { | ||
frame_range_1.setFrameRange(null); | ||
@@ -32,3 +34,21 @@ expect(internals_1.Internals.getRange()).toEqual(null); | ||
expect(internals_1.Internals.getRange()).toEqual([10, 20]); | ||
frame_range_1.setFrameRange(10); | ||
expect(internals_1.Internals.getRange()).toBe(10); | ||
frame_range_1.setFrameRange(0); | ||
expect(internals_1.Internals.getRange()).toBe(0); | ||
}); | ||
test('Frame range CLI should throw exception with invalid inputs', () => { | ||
expect_to_throw_1.expectToThrow(() => frame_range_1.setFrameRangeFromCli('1-2-3'), /--frames flag must be a number or 2 numbers separated by '-', instead got 3 numbers/); | ||
expect_to_throw_1.expectToThrow(() => frame_range_1.setFrameRangeFromCli('2-1'), /The second number of the --frames flag number should be greater or equal than first number/); | ||
expect_to_throw_1.expectToThrow(() => frame_range_1.setFrameRangeFromCli('one-two'), /--frames flag must be a single number, or 2 numbers separated by `-`/); | ||
}); | ||
test('Frame range CLI tests with valid inputs', () => { | ||
frame_range_1.setFrameRange(null); | ||
frame_range_1.setFrameRangeFromCli(0); | ||
expect(internals_1.Internals.getRange()).toEqual(0); | ||
frame_range_1.setFrameRangeFromCli(10); | ||
expect(internals_1.Internals.getRange()).toEqual(10); | ||
frame_range_1.setFrameRangeFromCli('1-10'); | ||
expect(internals_1.Internals.getRange()).toEqual([1, 10]); | ||
}); | ||
//# sourceMappingURL=range.test.js.map |
@@ -7,2 +7,7 @@ "use strict"; | ||
const expect_to_throw_1 = require("./expect-to-throw"); | ||
test('It should throw if "from" props is not a number', () => { | ||
expect_to_throw_1.expectToThrow( | ||
// @ts-expect-error | ||
() => react_1.render(jsx_runtime_1.jsx(sequencing_1.Sequence, { from: '0', durationInFrames: 30 }, void 0)), /You passed to the "from" props of your <Sequence> an argument of type string, but it must be a number./); | ||
}); | ||
test('It should throw if Sequence has missing duration', () => { | ||
@@ -13,10 +18,18 @@ expect_to_throw_1.expectToThrow( | ||
}); | ||
test('It should throw if Sequence has negative duration', () => { | ||
expect_to_throw_1.expectToThrow( | ||
// @ts-expect-error | ||
() => react_1.render(jsx_runtime_1.jsx(sequencing_1.Sequence, { from: 0, durationInFrames: -1 }, void 0)), /durationInFrames must be positive, but got -1/); | ||
}); | ||
test('It should allow null as children', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ durationInFrames: 100, from: 0 }, { children: null }), void 0))).not.toThrow(); | ||
}); | ||
test('It should not allow no children at all', () => { | ||
expect_to_throw_1.expectToThrow( | ||
test('It should allow undefined as children', () => { | ||
expect(() => react_1.render(jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ durationInFrames: 100, from: 0 }, { children: undefined }), void 0))).not.toThrow(); | ||
}); | ||
test('It should throw for invalid layout value', () => { | ||
expect_to_throw_1.expectToThrow(() => react_1.render( | ||
// @ts-expect-error | ||
() => react_1.render(jsx_runtime_1.jsx(sequencing_1.Sequence, { from: 0 }, void 0)), /You passed to durationInFrames an argument of type undefined, but it must be a number./); | ||
jsx_runtime_1.jsx(sequencing_1.Sequence, { from: 0, durationInFrames: 100, layout: 'invalid-value' }, void 0)), /The layout prop of <Sequence \/> expects either "absolute-fill" or "none", but you passed: invalid-value/); | ||
}); | ||
//# sourceMappingURL=sequence-validation.test.js.map |
@@ -5,2 +5,3 @@ /// <reference types="react" /> | ||
playing: boolean; | ||
rootId: string; | ||
}; | ||
@@ -7,0 +8,0 @@ export declare type SetTimelineContextValue = { |
@@ -8,2 +8,3 @@ "use strict"; | ||
playing: false, | ||
rootId: '', | ||
}); | ||
@@ -10,0 +11,0 @@ exports.SetTimelineContext = react_1.createContext({ |
@@ -15,3 +15,5 @@ "use strict"; | ||
const context = react_1.useContext(sequencing_1.SequenceContext); | ||
const contextOffset = context ? context.from : 0; | ||
const contextOffset = context | ||
? context.cumulatedFrom + context.relativeFrom | ||
: 0; | ||
return frame - contextOffset; | ||
@@ -18,0 +20,0 @@ }; |
/// <reference types="react" /> | ||
export declare type RemotionVideoProps = Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, 'autoplay' | 'controls'>; | ||
import { VolumeProp } from '../volume-prop'; | ||
export declare type RemotionMainVideoProps = { | ||
startAt?: number; | ||
endAt?: number; | ||
}; | ||
export declare type RemotionVideoProps = Omit<React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, 'autoplay' | 'controls'> & { | ||
volume?: VolumeProp; | ||
}; | ||
//# sourceMappingURL=props.d.ts.map |
import React from 'react'; | ||
import { RemotionVideoProps } from './props'; | ||
export declare const Video: React.FC<RemotionVideoProps>; | ||
import { RemotionMainVideoProps, RemotionVideoProps } from './props'; | ||
export declare const Video: React.FC<RemotionVideoProps & RemotionMainVideoProps>; | ||
//# sourceMappingURL=Video.d.ts.map |
@@ -5,5 +5,16 @@ "use strict"; | ||
const jsx_runtime_1 = require("react/jsx-runtime"); | ||
const sequencing_1 = require("../sequencing"); | ||
const validate_media_props_1 = require("../validate-media-props"); | ||
const validate_start_from_props_1 = require("../validate-start-from-props"); | ||
const VideoForDevelopment_1 = require("./VideoForDevelopment"); | ||
const VideoForRendering_1 = require("./VideoForRendering"); | ||
const Video = (props) => { | ||
const { startAt, endAt, ...otherProps } = props; | ||
if (typeof startAt !== 'undefined' || typeof endAt !== 'undefined') { | ||
validate_start_from_props_1.validateStartFromProps(startAt, endAt); | ||
const startAtFrameNo = startAt !== null && startAt !== void 0 ? startAt : 0; | ||
const endAtFrameNo = endAt !== null && endAt !== void 0 ? endAt : Infinity; | ||
return (jsx_runtime_1.jsx(sequencing_1.Sequence, Object.assign({ showInTimeline: false, from: 0 - startAtFrameNo, durationInFrames: endAtFrameNo }, { children: jsx_runtime_1.jsx(exports.Video, Object.assign({}, otherProps), void 0) }), void 0)); | ||
} | ||
validate_media_props_1.validateMediaProps(props, 'Video'); | ||
if (process.env.NODE_ENV === 'development') { | ||
@@ -10,0 +21,0 @@ return jsx_runtime_1.jsx(VideoForDevelopment_1.VideoForDevelopment, Object.assign({}, props), void 0); |
@@ -6,20 +6,53 @@ "use strict"; | ||
const react_1 = require("react"); | ||
const feature_flags_1 = require("../feature-flags"); | ||
const is_approximately_the_same_1 = require("../is-approximately-the-same"); | ||
const timeline_position_state_1 = require("../timeline-position-state"); | ||
const use_frame_1 = require("../use-frame"); | ||
const use_unsafe_video_config_1 = require("../use-unsafe-video-config"); | ||
const volume_prop_1 = require("../volume-prop"); | ||
const get_current_time_1 = require("./get-current-time"); | ||
const VideoForDevelopment = (props) => { | ||
const videoRef = react_1.useRef(null); | ||
const currentFrame = use_frame_1.useCurrentFrame(); | ||
const absoluteFrame = use_frame_1.useAbsoluteCurrentFrame(); | ||
const videoConfig = use_unsafe_video_config_1.useUnsafeVideoConfig(); | ||
const [playing] = timeline_position_state_1.usePlayingState(); | ||
const [actualVolume, setActualVolume] = react_1.useState(1); | ||
const { volume, ...nativeProps } = props; | ||
// TODO: Register as an asset | ||
react_1.useEffect(() => { | ||
var _a, _b; | ||
if (playing) { | ||
(_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.play(); | ||
var _a, _b, _c; | ||
if (playing && !((_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.ended)) { | ||
(_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.play(); | ||
} | ||
else { | ||
(_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.pause(); | ||
(_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.pause(); | ||
} | ||
}, [playing]); | ||
react_1.useEffect(() => { | ||
const ref = videoRef.current; | ||
if (!ref) { | ||
return; | ||
} | ||
if (ref.volume !== actualVolume) { | ||
setActualVolume(ref.volume); | ||
return; | ||
} | ||
const onChange = () => { | ||
setActualVolume(ref.volume); | ||
}; | ||
ref.addEventListener('volumechange', onChange); | ||
return () => ref.removeEventListener('volumechange', onChange); | ||
}, [actualVolume]); | ||
react_1.useEffect(() => { | ||
const userPreferredVolume = volume_prop_1.evaluateVolume({ | ||
frame: currentFrame, | ||
volume, | ||
}); | ||
if (!is_approximately_the_same_1.isApproximatelyTheSame(userPreferredVolume, actualVolume) && | ||
videoRef.current) { | ||
videoRef.current.volume = userPreferredVolume; | ||
} | ||
}, [actualVolume, currentFrame, props.volume, volume]); | ||
react_1.useEffect(() => { | ||
if (!videoRef.current) { | ||
@@ -29,16 +62,25 @@ throw new Error('No video ref found'); | ||
if (!videoConfig) { | ||
throw new Error('No video config found'); | ||
throw new Error('No video config found. <Video> must be placed inside a composition.'); | ||
} | ||
if (!playing) { | ||
videoRef.current.currentTime = currentFrame / (1000 / videoConfig.fps); | ||
return; | ||
const currentTime = (() => { | ||
if (feature_flags_1.FEATURE_FLAG_V2_BREAKING_CHANGES) { | ||
return get_current_time_1.getCurrentTime({ | ||
fps: videoConfig.fps, | ||
frame: currentFrame, | ||
src: props.src, | ||
}); | ||
} | ||
return currentFrame / (1000 / videoConfig.fps); | ||
})(); | ||
if (!playing || absoluteFrame === 0) { | ||
videoRef.current.currentTime = currentTime; | ||
} | ||
if (videoRef.current.paused) { | ||
videoRef.current.currentTime = currentFrame / (1000 / videoConfig.fps); | ||
if (videoRef.current.paused && !videoRef.current.ended && playing) { | ||
videoRef.current.currentTime = currentTime; | ||
videoRef.current.play(); | ||
} | ||
}, [currentFrame, playing, videoConfig]); | ||
return jsx_runtime_1.jsx("video", Object.assign({ ref: videoRef, muted: true }, props), void 0); | ||
}, [currentFrame, playing, videoConfig, absoluteFrame, props.src]); | ||
return jsx_runtime_1.jsx("video", Object.assign({ ref: videoRef }, nativeProps), void 0); | ||
}; | ||
exports.VideoForDevelopment = VideoForDevelopment; | ||
//# sourceMappingURL=VideoForDevelopment.js.map |
@@ -6,19 +6,92 @@ "use strict"; | ||
const react_1 = require("react"); | ||
const use_audio_frame_1 = require("../audio/use-audio-frame"); | ||
const CompositionManager_1 = require("../CompositionManager"); | ||
const feature_flags_1 = require("../feature-flags"); | ||
const is_approximately_the_same_1 = require("../is-approximately-the-same"); | ||
const is_remote_asset_1 = require("../is-remote-asset"); | ||
const random_1 = require("../random"); | ||
const ready_manager_1 = require("../ready-manager"); | ||
const sequencing_1 = require("../sequencing"); | ||
const use_frame_1 = require("../use-frame"); | ||
const use_unsafe_video_config_1 = require("../use-unsafe-video-config"); | ||
const VideoForRendering = ({ onError, ...props }) => { | ||
const volume_prop_1 = require("../volume-prop"); | ||
const get_current_time_1 = require("./get-current-time"); | ||
const VideoForRendering = ({ onError, volume: volumeProp, ...props }) => { | ||
const absoluteFrame = use_frame_1.useAbsoluteCurrentFrame(); | ||
const frame = use_frame_1.useCurrentFrame(); | ||
const audioFrame = use_audio_frame_1.useAudioFrame(); | ||
const videoConfig = use_unsafe_video_config_1.useUnsafeVideoConfig(); | ||
const videoRef = react_1.useRef(null); | ||
const sequenceContext = react_1.useContext(sequencing_1.SequenceContext); | ||
const { registerAsset, unregisterAsset } = react_1.useContext(CompositionManager_1.CompositionManager); | ||
// Generate a string that's as unique as possible for this asset | ||
// but at the same time the same on all threads | ||
const id = react_1.useMemo(() => { | ||
var _a; | ||
return `audio-${random_1.random((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}-muted:${props.muted}`; | ||
}, [ | ||
props.src, | ||
props.muted, | ||
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom, | ||
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom, | ||
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames, | ||
]); | ||
if (!videoConfig) { | ||
throw new Error('No video config found'); | ||
} | ||
const volume = volume_prop_1.evaluateVolume({ | ||
volume: volumeProp, | ||
frame: audioFrame, | ||
}); | ||
react_1.useEffect(() => { | ||
if (!props.src) { | ||
throw new Error('No src passed'); | ||
} | ||
if (props.muted) { | ||
return; | ||
} | ||
registerAsset({ | ||
type: 'video', | ||
src: props.src, | ||
id, | ||
frame: absoluteFrame, | ||
volume, | ||
isRemote: is_remote_asset_1.isRemoteAsset(props.src), | ||
mediaFrame: frame, | ||
}); | ||
return () => unregisterAsset(id); | ||
}, [ | ||
props.muted, | ||
props.src, | ||
registerAsset, | ||
id, | ||
unregisterAsset, | ||
volume, | ||
frame, | ||
absoluteFrame, | ||
]); | ||
react_1.useEffect(() => { | ||
if (!videoRef.current) { | ||
return; | ||
} | ||
const frameInSeconds = frame / videoConfig.fps; | ||
const currentTime = (() => { | ||
if (feature_flags_1.FEATURE_FLAG_V2_BREAKING_CHANGES) { | ||
return get_current_time_1.getCurrentTime({ | ||
fps: videoConfig.fps, | ||
frame: audioFrame, | ||
src: props.src, | ||
}); | ||
} | ||
return audioFrame / (1000 / videoConfig.fps); | ||
})(); | ||
const handle = ready_manager_1.delayRender(); | ||
if (videoRef.current.currentTime === frameInSeconds) { | ||
if (process.env.NODE_ENV === 'test') { | ||
ready_manager_1.continueRender(handle); | ||
return; | ||
} | ||
if (is_approximately_the_same_1.isApproximatelyTheSame(videoRef.current.currentTime, currentTime)) { | ||
if (videoRef.current.readyState >= 2) { | ||
ready_manager_1.continueRender(handle); | ||
return; | ||
} | ||
videoRef.current.addEventListener('loadeddata', () => { | ||
@@ -29,4 +102,11 @@ ready_manager_1.continueRender(handle); | ||
} | ||
videoRef.current.currentTime = frameInSeconds; | ||
videoRef.current.currentTime = currentTime; | ||
videoRef.current.addEventListener('seeked', () => { | ||
// Improve me: This is ensures frame perfectness but slows down render. | ||
// Please see this issue for context: https://github.com/JonnyBurger/remotion/issues/200 | ||
setTimeout(() => { | ||
ready_manager_1.continueRender(handle); | ||
}, 100); | ||
}, { once: true }); | ||
videoRef.current.addEventListener('ended', () => { | ||
ready_manager_1.continueRender(handle); | ||
@@ -38,3 +118,3 @@ }, { once: true }); | ||
}, { once: true }); | ||
}, [frame, videoConfig.fps]); | ||
}, [audioFrame, props.src, videoConfig.fps]); | ||
return jsx_runtime_1.jsx("video", Object.assign({ ref: videoRef }, props), void 0); | ||
@@ -41,0 +121,0 @@ }; |
{ | ||
"name": "remotion", | ||
"version": "1.6.0-alpha.0985ca71", | ||
"version": "1.6.0-alpha.1aea6849", | ||
"description": "Render videos in React", | ||
@@ -23,6 +23,8 @@ "main": "dist/index.js", | ||
"prettier": "^2.0.5", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"typescript": "^4.1.2" | ||
}, | ||
"peerDependencies": { | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1" | ||
}, | ||
"devDependencies": { | ||
@@ -33,4 +35,3 @@ "@jonny/eslint-config": "^2.1.210", | ||
"@types/node": "^14.14.14", | ||
"@types/react": "^17.0.0", | ||
"@types/react-dom": "^17.0.0", | ||
"@types/webpack-env": "^1.16.0", | ||
"eslint": "^7.4.0", | ||
@@ -37,0 +38,0 @@ "jest": "^26.6.3", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
381472
10
394
4490
4
- Removedreact@^17.0.1
- Removedreact-dom@^17.0.1