remotion 4.0.0-alpha5 → 4.0.0-alpha6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/audio/AudioForDevelopment.js +10 -3
- package/dist/cjs/spring/index.d.ts +5 -1
- package/dist/cjs/spring/index.js +35 -14
- package/dist/cjs/static-file.d.ts +28 -0
- package/dist/cjs/static-file.js +43 -3
- package/dist/cjs/use-media-playback.js +12 -3
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/video/OffthreadVideo.js +2 -2
- package/dist/cjs/video/VideoForDevelopment.js +6 -2
- package/dist/cjs/video/VideoForRendering.js +6 -1
- package/dist/cjs/video/props.d.ts +1 -0
- package/dist/esm/index.mjs +118 -33
- package/dist/esm/version.mjs +1 -1
- package/package.json +1 -1
|
@@ -36,7 +36,14 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
|
|
|
36
36
|
const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
|
|
37
37
|
// Generate a string that's as unique as possible for this asset
|
|
38
38
|
// but at the same time deterministic. We use it to combat strict mode issues.
|
|
39
|
-
const id = (0, react_1.useMemo)(() => `audio-${(0, random_js_1.random)(src !== null && src !== void 0 ? src : '')}-${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}`, [
|
|
39
|
+
const id = (0, react_1.useMemo)(() => `audio-${(0, random_js_1.random)(src !== null && src !== void 0 ? src : '')}-${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}-loop:${props.loop}`, [
|
|
40
|
+
src,
|
|
41
|
+
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
|
|
42
|
+
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
|
|
43
|
+
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
|
|
44
|
+
props.muted,
|
|
45
|
+
props.loop,
|
|
46
|
+
]);
|
|
40
47
|
const audioRef = (0, shared_audio_tags_js_1.useSharedAudio)(propsToPass, id).el;
|
|
41
48
|
const actualVolume = (0, use_media_tag_volume_js_1.useMediaTagVolume)(audioRef);
|
|
42
49
|
(0, use_sync_volume_with_media_tag_js_1.useSyncVolumeWithMediaTag)({
|
|
@@ -74,12 +81,12 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
|
|
|
74
81
|
return;
|
|
75
82
|
}
|
|
76
83
|
if (current.duration) {
|
|
77
|
-
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, src, current.duration);
|
|
84
|
+
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, current.src, current.duration);
|
|
78
85
|
return;
|
|
79
86
|
}
|
|
80
87
|
const onLoadedMetadata = () => {
|
|
81
88
|
var _a;
|
|
82
|
-
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, src, current.duration);
|
|
89
|
+
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, current.src, current.duration);
|
|
83
90
|
};
|
|
84
91
|
current.addEventListener('loadedmetadata', onLoadedMetadata);
|
|
85
92
|
return () => {
|
|
@@ -4,6 +4,7 @@ import type { SpringConfig } from './spring-utils.js';
|
|
|
4
4
|
* @see [Documentation](https://www.remotion.dev/docs/spring)
|
|
5
5
|
* @param {number} frame The current time value. Most of the time you want to pass in the return value of useCurrentFrame.
|
|
6
6
|
* @param {number} fps The framerate at which the animation runs. Pass in the value obtained by `useVideoConfig()`.
|
|
7
|
+
* @param {?boolean} reverse Whether the animation plays in reverse or not. Default `false`.
|
|
7
8
|
* @param {?Object} config optional object that allows you to customize the physical properties of the animation.
|
|
8
9
|
* @param {number} [config.mass=1] The weight of the spring. If you reduce the mass, the animation becomes faster!
|
|
9
10
|
* @param {number} [config.damping=10] How hard the animation decelerates.
|
|
@@ -13,8 +14,9 @@ import type { SpringConfig } from './spring-utils.js';
|
|
|
13
14
|
* @param {?number} [config.to] The end value of the animation. Default `1`
|
|
14
15
|
* @param {?number} [config.durationInFrames] Stretch the duration of an animation to a set value.. Default `undefined`
|
|
15
16
|
* @param {?number} [config.durationThreshold] How close to the end the animation is considered to be done. Default `0.005`
|
|
17
|
+
* @param {?number} [config.delay] Delay the animation for this amount of frames. Default `0`
|
|
16
18
|
*/
|
|
17
|
-
export declare function spring({ frame, fps, config, from, to, durationInFrames, durationRestThreshold, }: {
|
|
19
|
+
export declare function spring({ frame: passedFrame, fps, config, from, to, durationInFrames: passedDurationInFrames, durationRestThreshold, delay, reverse, }: {
|
|
18
20
|
frame: number;
|
|
19
21
|
fps: number;
|
|
20
22
|
config?: Partial<SpringConfig>;
|
|
@@ -22,6 +24,8 @@ export declare function spring({ frame, fps, config, from, to, durationInFrames,
|
|
|
22
24
|
to?: number;
|
|
23
25
|
durationInFrames?: number;
|
|
24
26
|
durationRestThreshold?: number;
|
|
27
|
+
delay?: number;
|
|
28
|
+
reverse?: boolean;
|
|
25
29
|
}): number;
|
|
26
30
|
export { measureSpring } from './measure-spring.js';
|
|
27
31
|
export { SpringConfig } from './spring-utils.js';
|
package/dist/cjs/spring/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const spring_utils_js_1 = require("./spring-utils.js");
|
|
|
11
11
|
* @see [Documentation](https://www.remotion.dev/docs/spring)
|
|
12
12
|
* @param {number} frame The current time value. Most of the time you want to pass in the return value of useCurrentFrame.
|
|
13
13
|
* @param {number} fps The framerate at which the animation runs. Pass in the value obtained by `useVideoConfig()`.
|
|
14
|
+
* @param {?boolean} reverse Whether the animation plays in reverse or not. Default `false`.
|
|
14
15
|
* @param {?Object} config optional object that allows you to customize the physical properties of the animation.
|
|
15
16
|
* @param {number} [config.mass=1] The weight of the spring. If you reduce the mass, the animation becomes faster!
|
|
16
17
|
* @param {number} [config.damping=10] How hard the animation decelerates.
|
|
@@ -20,24 +21,44 @@ const spring_utils_js_1 = require("./spring-utils.js");
|
|
|
20
21
|
* @param {?number} [config.to] The end value of the animation. Default `1`
|
|
21
22
|
* @param {?number} [config.durationInFrames] Stretch the duration of an animation to a set value.. Default `undefined`
|
|
22
23
|
* @param {?number} [config.durationThreshold] How close to the end the animation is considered to be done. Default `0.005`
|
|
24
|
+
* @param {?number} [config.delay] Delay the animation for this amount of frames. Default `0`
|
|
23
25
|
*/
|
|
24
|
-
function spring({ frame, fps, config = {}, from = 0, to = 1, durationInFrames, durationRestThreshold, }) {
|
|
25
|
-
(0, validation_spring_duration_js_1.validateSpringDuration)(
|
|
26
|
-
(0, validate_frame_js_1.validateFrame)({
|
|
26
|
+
function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durationInFrames: passedDurationInFrames, durationRestThreshold, delay = 0, reverse = false, }) {
|
|
27
|
+
(0, validation_spring_duration_js_1.validateSpringDuration)(passedDurationInFrames);
|
|
28
|
+
(0, validate_frame_js_1.validateFrame)({
|
|
29
|
+
frame: passedFrame,
|
|
30
|
+
durationInFrames: Infinity,
|
|
31
|
+
allowFloats: true,
|
|
32
|
+
});
|
|
27
33
|
(0, validate_fps_js_1.validateFps)(fps, 'to spring()', false);
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
const needsToCalculateNaturalDuration = reverse || typeof passedDurationInFrames !== 'undefined';
|
|
35
|
+
const naturalDuration = needsToCalculateNaturalDuration
|
|
36
|
+
? (0, measure_spring_js_1.measureSpring)({
|
|
37
|
+
fps,
|
|
38
|
+
config,
|
|
39
|
+
from,
|
|
40
|
+
to,
|
|
41
|
+
threshold: durationRestThreshold,
|
|
42
|
+
})
|
|
43
|
+
: undefined;
|
|
44
|
+
const naturalDurationGetter = needsToCalculateNaturalDuration
|
|
45
|
+
? {
|
|
46
|
+
get: () => naturalDuration,
|
|
47
|
+
}
|
|
48
|
+
: {
|
|
49
|
+
get: () => {
|
|
50
|
+
throw new Error('did not calculate natural duration, this is an error with Remotion. Please report');
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const frame = reverse
|
|
54
|
+
? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
|
|
55
|
+
: passedFrame;
|
|
38
56
|
const spr = (0, spring_utils_js_1.springCalculation)({
|
|
39
57
|
fps,
|
|
40
|
-
frame:
|
|
58
|
+
frame: (passedDurationInFrames === undefined
|
|
59
|
+
? frame
|
|
60
|
+
: frame / (passedDurationInFrames / naturalDurationGetter.get())) -
|
|
61
|
+
delay,
|
|
41
62
|
config,
|
|
42
63
|
from,
|
|
43
64
|
to,
|
|
@@ -1,5 +1,33 @@
|
|
|
1
|
+
declare const problematicCharacters: {
|
|
2
|
+
'%3A': string;
|
|
3
|
+
'%2F': string;
|
|
4
|
+
'%3F': string;
|
|
5
|
+
'%23': string;
|
|
6
|
+
'%5B': string;
|
|
7
|
+
'%5D': string;
|
|
8
|
+
'%40': string;
|
|
9
|
+
'%21': string;
|
|
10
|
+
'%24': string;
|
|
11
|
+
'%26': string;
|
|
12
|
+
'%27': string;
|
|
13
|
+
'%28': string;
|
|
14
|
+
'%29': string;
|
|
15
|
+
'%2A': string;
|
|
16
|
+
'%2B': string;
|
|
17
|
+
'%2C': string;
|
|
18
|
+
'%3B': string;
|
|
19
|
+
};
|
|
20
|
+
declare type HexCode = keyof typeof problematicCharacters;
|
|
21
|
+
export declare type HexInfo = {
|
|
22
|
+
containsHex: false;
|
|
23
|
+
} | {
|
|
24
|
+
containsHex: true;
|
|
25
|
+
hexCode: HexCode;
|
|
26
|
+
};
|
|
27
|
+
export declare const includesHexOfUnsafeChar: (path: string) => HexInfo;
|
|
1
28
|
/**
|
|
2
29
|
* @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
|
|
3
30
|
* @see [Documentation](https://www.remotion.dev/docs/staticfile)
|
|
4
31
|
*/
|
|
5
32
|
export declare const staticFile: (path: string) => string;
|
|
33
|
+
export {};
|
package/dist/cjs/static-file.js
CHANGED
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.staticFile = void 0;
|
|
3
|
+
exports.staticFile = exports.includesHexOfUnsafeChar = void 0;
|
|
4
|
+
const problematicCharacters = {
|
|
5
|
+
'%3A': ':',
|
|
6
|
+
'%2F': '/',
|
|
7
|
+
'%3F': '?',
|
|
8
|
+
'%23': '#',
|
|
9
|
+
'%5B': '[',
|
|
10
|
+
'%5D': ']',
|
|
11
|
+
'%40': '@',
|
|
12
|
+
'%21': '!',
|
|
13
|
+
'%24': '$',
|
|
14
|
+
'%26': '&',
|
|
15
|
+
'%27': "'",
|
|
16
|
+
'%28': '(',
|
|
17
|
+
'%29': ')',
|
|
18
|
+
'%2A': '*',
|
|
19
|
+
'%2B': '+',
|
|
20
|
+
'%2C': ',',
|
|
21
|
+
'%3B': ';',
|
|
22
|
+
};
|
|
23
|
+
const didWarn = {};
|
|
24
|
+
const warnOnce = (message) => {
|
|
25
|
+
if (didWarn[message]) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.warn(message);
|
|
29
|
+
didWarn[message] = true;
|
|
30
|
+
};
|
|
31
|
+
const includesHexOfUnsafeChar = (path) => {
|
|
32
|
+
for (const key of Object.keys(problematicCharacters)) {
|
|
33
|
+
if (path.includes(key)) {
|
|
34
|
+
return { containsHex: true, hexCode: key };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { containsHex: false };
|
|
38
|
+
};
|
|
39
|
+
exports.includesHexOfUnsafeChar = includesHexOfUnsafeChar;
|
|
4
40
|
const trimLeadingSlash = (path) => {
|
|
5
41
|
if (path.startsWith('/')) {
|
|
6
|
-
return trimLeadingSlash(path.
|
|
42
|
+
return trimLeadingSlash(path.substring(1));
|
|
7
43
|
}
|
|
8
44
|
return path;
|
|
9
45
|
};
|
|
@@ -38,7 +74,11 @@ const staticFile = (path) => {
|
|
|
38
74
|
if (path.startsWith('public/')) {
|
|
39
75
|
throw new TypeError(`Do not include the public/ prefix when using staticFile() - got "${path}". See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
40
76
|
}
|
|
41
|
-
const
|
|
77
|
+
const includesHex = (0, exports.includesHexOfUnsafeChar)(path);
|
|
78
|
+
if (includesHex.containsHex) {
|
|
79
|
+
warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). The encoding gets automatically handled by staticFile() `);
|
|
80
|
+
}
|
|
81
|
+
const preparsed = inner(encodeURIComponent(path));
|
|
42
82
|
if (!preparsed.startsWith('/')) {
|
|
43
83
|
return `/${preparsed}`;
|
|
44
84
|
}
|
|
@@ -51,12 +51,21 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
|
|
|
51
51
|
(0, warn_about_non_seekable_media_js_1.warnAboutNonSeekableMedia)(mediaRef.current, onlyWarnForMediaSeekingError ? 'console-warning' : 'console-error');
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
// Only perform a seek if the time is not already the same.
|
|
55
|
+
// Chrome rounds to 6 digits, so 0.033333333 -> 0.033333,
|
|
56
|
+
// therefore a threshold is allowed.
|
|
57
|
+
// Refer to the https://github.com/remotion-dev/video-buffering-example
|
|
58
|
+
// which is fixed by only seeking conditionally.
|
|
59
|
+
const makesSenseToSeek = Math.abs(mediaRef.current.currentTime - shouldBeTime) > 0.00001;
|
|
54
60
|
if (!playing || absoluteFrame === 0) {
|
|
55
|
-
|
|
61
|
+
if (makesSenseToSeek) {
|
|
62
|
+
mediaRef.current.currentTime = shouldBeTime;
|
|
63
|
+
}
|
|
56
64
|
}
|
|
57
65
|
if (mediaRef.current.paused && !mediaRef.current.ended && playing) {
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
if (makesSenseToSeek) {
|
|
67
|
+
mediaRef.current.currentTime = shouldBeTime;
|
|
68
|
+
}
|
|
60
69
|
(0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType);
|
|
61
70
|
}
|
|
62
71
|
}, [
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "4.0.0-
|
|
1
|
+
export declare const VERSION = "4.0.0-alpha6";
|
package/dist/cjs/version.js
CHANGED
|
@@ -14,7 +14,7 @@ const VideoForDevelopment_js_1 = require("./VideoForDevelopment.js");
|
|
|
14
14
|
* @see [Documentation](https://www.remotion.dev/docs/offthreadvideo)
|
|
15
15
|
*/
|
|
16
16
|
const OffthreadVideo = (props) => {
|
|
17
|
-
const { startFrom, endAt, ...otherProps } = props;
|
|
17
|
+
const { startFrom, endAt, imageFormat, ...otherProps } = props;
|
|
18
18
|
const environment = (0, get_environment_js_1.useRemotionEnvironment)();
|
|
19
19
|
const onDuration = (0, react_1.useCallback)(() => undefined, []);
|
|
20
20
|
if (typeof props.src !== 'string') {
|
|
@@ -31,7 +31,7 @@ const OffthreadVideo = (props) => {
|
|
|
31
31
|
}
|
|
32
32
|
(0, validate_media_props_js_1.validateMediaProps)(props, 'Video');
|
|
33
33
|
if (environment === 'rendering') {
|
|
34
|
-
return (0, jsx_runtime_1.jsx)(OffthreadVideoForRendering_js_1.OffthreadVideoForRendering, { ...otherProps });
|
|
34
|
+
return ((0, jsx_runtime_1.jsx)(OffthreadVideoForRendering_js_1.OffthreadVideoForRendering, { imageFormat: imageFormat, ...otherProps }));
|
|
35
35
|
}
|
|
36
36
|
return ((0, jsx_runtime_1.jsx)(VideoForDevelopment_js_1.VideoForDevelopment, { onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...otherProps }));
|
|
37
37
|
};
|
|
@@ -75,7 +75,11 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
|
|
|
75
75
|
var _a;
|
|
76
76
|
if (current === null || current === void 0 ? void 0 : current.error) {
|
|
77
77
|
console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
|
|
78
|
-
|
|
78
|
+
// If user is handling the error, we don't cause an unhandled exception
|
|
79
|
+
if (props.onError) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
throw new Error(`The browser threw an error while playing the video ${src}: Code ${current.error.code} - ${(_a = current === null || current === void 0 ? void 0 : current.error) === null || _a === void 0 ? void 0 : _a.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
|
|
79
83
|
}
|
|
80
84
|
else {
|
|
81
85
|
throw new Error('The browser threw an error');
|
|
@@ -85,7 +89,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
|
|
|
85
89
|
return () => {
|
|
86
90
|
current.removeEventListener('error', errorHandler);
|
|
87
91
|
};
|
|
88
|
-
}, [src]);
|
|
92
|
+
}, [props.onError, src]);
|
|
89
93
|
const currentOnDurationCallback = (0, react_1.useRef)();
|
|
90
94
|
currentOnDurationCallback.current = onDuration;
|
|
91
95
|
(0, react_1.useEffect)(() => {
|
|
@@ -146,7 +146,11 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
|
|
|
146
146
|
var _a;
|
|
147
147
|
if (current === null || current === void 0 ? void 0 : current.error) {
|
|
148
148
|
console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
|
|
149
|
-
|
|
149
|
+
// If user is handling the error, we don't cause an unhandled exception
|
|
150
|
+
if (onError) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
throw new Error(`The browser threw an error while playing the video ${props.src}: Code ${current.error.code} - ${(_a = current === null || current === void 0 ? void 0 : current.error) === null || _a === void 0 ? void 0 : _a.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
|
|
150
154
|
}
|
|
151
155
|
else {
|
|
152
156
|
throw new Error('The browser threw an error');
|
|
@@ -167,6 +171,7 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
|
|
|
167
171
|
videoConfig.fps,
|
|
168
172
|
frame,
|
|
169
173
|
mediaStartsAt,
|
|
174
|
+
onError,
|
|
170
175
|
]);
|
|
171
176
|
const { src } = props;
|
|
172
177
|
// If video source switches, make new handle
|
package/dist/esm/index.mjs
CHANGED
|
@@ -58,7 +58,7 @@ function truthy(value) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Automatically generated on publish
|
|
61
|
-
const VERSION = '4.0.0-
|
|
61
|
+
const VERSION = '4.0.0-alpha6';
|
|
62
62
|
|
|
63
63
|
const checkMultipleRemotionVersions = () => {
|
|
64
64
|
if (typeof globalThis === 'undefined') {
|
|
@@ -1176,13 +1176,13 @@ const evaluateVolume = ({ frame, volume, mediaVolume = 1, allowAmplificationDuri
|
|
|
1176
1176
|
return Math.max(0, Math.min(maxVolume, evaluated));
|
|
1177
1177
|
};
|
|
1178
1178
|
|
|
1179
|
-
const didWarn = {};
|
|
1180
|
-
const warnOnce = (message) => {
|
|
1181
|
-
if (didWarn[message]) {
|
|
1179
|
+
const didWarn$1 = {};
|
|
1180
|
+
const warnOnce$1 = (message) => {
|
|
1181
|
+
if (didWarn$1[message]) {
|
|
1182
1182
|
return;
|
|
1183
1183
|
}
|
|
1184
1184
|
console.warn(message);
|
|
1185
|
-
didWarn[message] = true;
|
|
1185
|
+
didWarn$1[message] = true;
|
|
1186
1186
|
};
|
|
1187
1187
|
const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, }) => {
|
|
1188
1188
|
const videoConfig = useVideoConfig();
|
|
@@ -1220,7 +1220,7 @@ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, pla
|
|
|
1220
1220
|
}, [duration, startsAt, volume, mediaVolume]);
|
|
1221
1221
|
useEffect(() => {
|
|
1222
1222
|
if (typeof volume === 'number' && volume !== initialVolume) {
|
|
1223
|
-
warnOnce(`Remotion: The ${mediaType} with src ${src} has changed it's volume. Prefer the callback syntax for setting volume to get better timeline display: https://www.remotion.dev/docs/using-audio/#controlling-volume`);
|
|
1223
|
+
warnOnce$1(`Remotion: The ${mediaType} with src ${src} has changed it's volume. Prefer the callback syntax for setting volume to get better timeline display: https://www.remotion.dev/docs/using-audio/#controlling-volume`);
|
|
1224
1224
|
}
|
|
1225
1225
|
}, [initialVolume, mediaType, src, volume]);
|
|
1226
1226
|
useEffect(() => {
|
|
@@ -1505,12 +1505,21 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
|
|
|
1505
1505
|
warnAboutNonSeekableMedia(mediaRef.current, onlyWarnForMediaSeekingError ? 'console-warning' : 'console-error');
|
|
1506
1506
|
}
|
|
1507
1507
|
}
|
|
1508
|
+
// Only perform a seek if the time is not already the same.
|
|
1509
|
+
// Chrome rounds to 6 digits, so 0.033333333 -> 0.033333,
|
|
1510
|
+
// therefore a threshold is allowed.
|
|
1511
|
+
// Refer to the https://github.com/remotion-dev/video-buffering-example
|
|
1512
|
+
// which is fixed by only seeking conditionally.
|
|
1513
|
+
const makesSenseToSeek = Math.abs(mediaRef.current.currentTime - shouldBeTime) > 0.00001;
|
|
1508
1514
|
if (!playing || absoluteFrame === 0) {
|
|
1509
|
-
|
|
1515
|
+
if (makesSenseToSeek) {
|
|
1516
|
+
mediaRef.current.currentTime = shouldBeTime;
|
|
1517
|
+
}
|
|
1510
1518
|
}
|
|
1511
1519
|
if (mediaRef.current.paused && !mediaRef.current.ended && playing) {
|
|
1512
|
-
|
|
1513
|
-
|
|
1520
|
+
if (makesSenseToSeek) {
|
|
1521
|
+
mediaRef.current.currentTime = shouldBeTime;
|
|
1522
|
+
}
|
|
1514
1523
|
playAndHandleNotAllowedError(mediaRef, mediaType);
|
|
1515
1524
|
}
|
|
1516
1525
|
}, [
|
|
@@ -1626,7 +1635,14 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
|
|
|
1626
1635
|
const sequenceContext = useContext(SequenceContext);
|
|
1627
1636
|
// Generate a string that's as unique as possible for this asset
|
|
1628
1637
|
// but at the same time deterministic. We use it to combat strict mode issues.
|
|
1629
|
-
const id = useMemo(() => `audio-${random(src !== null && src !== void 0 ? src : '')}-${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}`, [
|
|
1638
|
+
const id = useMemo(() => `audio-${random(src !== null && src !== void 0 ? src : '')}-${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}-loop:${props.loop}`, [
|
|
1639
|
+
src,
|
|
1640
|
+
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
|
|
1641
|
+
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
|
|
1642
|
+
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
|
|
1643
|
+
props.muted,
|
|
1644
|
+
props.loop,
|
|
1645
|
+
]);
|
|
1630
1646
|
const audioRef = useSharedAudio(propsToPass, id).el;
|
|
1631
1647
|
const actualVolume = useMediaTagVolume(audioRef);
|
|
1632
1648
|
useSyncVolumeWithMediaTag({
|
|
@@ -1664,12 +1680,12 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
|
|
|
1664
1680
|
return;
|
|
1665
1681
|
}
|
|
1666
1682
|
if (current.duration) {
|
|
1667
|
-
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, src, current.duration);
|
|
1683
|
+
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, current.src, current.duration);
|
|
1668
1684
|
return;
|
|
1669
1685
|
}
|
|
1670
1686
|
const onLoadedMetadata = () => {
|
|
1671
1687
|
var _a;
|
|
1672
|
-
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, src, current.duration);
|
|
1688
|
+
(_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, current.src, current.duration);
|
|
1673
1689
|
};
|
|
1674
1690
|
current.addEventListener('loadedmetadata', onLoadedMetadata);
|
|
1675
1691
|
return () => {
|
|
@@ -3552,6 +3568,7 @@ function measureSpring({ fps, config = {}, threshold = 0.005, from = 0, to = 1,
|
|
|
3552
3568
|
* @see [Documentation](https://www.remotion.dev/docs/spring)
|
|
3553
3569
|
* @param {number} frame The current time value. Most of the time you want to pass in the return value of useCurrentFrame.
|
|
3554
3570
|
* @param {number} fps The framerate at which the animation runs. Pass in the value obtained by `useVideoConfig()`.
|
|
3571
|
+
* @param {?boolean} reverse Whether the animation plays in reverse or not. Default `false`.
|
|
3555
3572
|
* @param {?Object} config optional object that allows you to customize the physical properties of the animation.
|
|
3556
3573
|
* @param {number} [config.mass=1] The weight of the spring. If you reduce the mass, the animation becomes faster!
|
|
3557
3574
|
* @param {number} [config.damping=10] How hard the animation decelerates.
|
|
@@ -3561,24 +3578,44 @@ function measureSpring({ fps, config = {}, threshold = 0.005, from = 0, to = 1,
|
|
|
3561
3578
|
* @param {?number} [config.to] The end value of the animation. Default `1`
|
|
3562
3579
|
* @param {?number} [config.durationInFrames] Stretch the duration of an animation to a set value.. Default `undefined`
|
|
3563
3580
|
* @param {?number} [config.durationThreshold] How close to the end the animation is considered to be done. Default `0.005`
|
|
3581
|
+
* @param {?number} [config.delay] Delay the animation for this amount of frames. Default `0`
|
|
3564
3582
|
*/
|
|
3565
|
-
function spring({ frame, fps, config = {}, from = 0, to = 1, durationInFrames, durationRestThreshold, }) {
|
|
3566
|
-
validateSpringDuration(
|
|
3567
|
-
validateFrame({
|
|
3583
|
+
function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durationInFrames: passedDurationInFrames, durationRestThreshold, delay = 0, reverse = false, }) {
|
|
3584
|
+
validateSpringDuration(passedDurationInFrames);
|
|
3585
|
+
validateFrame({
|
|
3586
|
+
frame: passedFrame,
|
|
3587
|
+
durationInFrames: Infinity,
|
|
3588
|
+
allowFloats: true,
|
|
3589
|
+
});
|
|
3568
3590
|
validateFps(fps, 'to spring()', false);
|
|
3569
|
-
const
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3591
|
+
const needsToCalculateNaturalDuration = reverse || typeof passedDurationInFrames !== 'undefined';
|
|
3592
|
+
const naturalDuration = needsToCalculateNaturalDuration
|
|
3593
|
+
? measureSpring({
|
|
3594
|
+
fps,
|
|
3595
|
+
config,
|
|
3596
|
+
from,
|
|
3597
|
+
to,
|
|
3598
|
+
threshold: durationRestThreshold,
|
|
3599
|
+
})
|
|
3600
|
+
: undefined;
|
|
3601
|
+
const naturalDurationGetter = needsToCalculateNaturalDuration
|
|
3602
|
+
? {
|
|
3603
|
+
get: () => naturalDuration,
|
|
3604
|
+
}
|
|
3605
|
+
: {
|
|
3606
|
+
get: () => {
|
|
3607
|
+
throw new Error('did not calculate natural duration, this is an error with Remotion. Please report');
|
|
3608
|
+
},
|
|
3609
|
+
};
|
|
3610
|
+
const frame = reverse
|
|
3611
|
+
? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
|
|
3612
|
+
: passedFrame;
|
|
3579
3613
|
const spr = springCalculation({
|
|
3580
3614
|
fps,
|
|
3581
|
-
frame:
|
|
3615
|
+
frame: (passedDurationInFrames === undefined
|
|
3616
|
+
? frame
|
|
3617
|
+
: frame / (passedDurationInFrames / naturalDurationGetter.get())) -
|
|
3618
|
+
delay,
|
|
3582
3619
|
config,
|
|
3583
3620
|
from,
|
|
3584
3621
|
to,
|
|
@@ -3592,9 +3629,44 @@ function spring({ frame, fps, config = {}, from = 0, to = 1, durationInFrames, d
|
|
|
3592
3629
|
return Math.max(spr.current, to);
|
|
3593
3630
|
}
|
|
3594
3631
|
|
|
3632
|
+
const problematicCharacters = {
|
|
3633
|
+
'%3A': ':',
|
|
3634
|
+
'%2F': '/',
|
|
3635
|
+
'%3F': '?',
|
|
3636
|
+
'%23': '#',
|
|
3637
|
+
'%5B': '[',
|
|
3638
|
+
'%5D': ']',
|
|
3639
|
+
'%40': '@',
|
|
3640
|
+
'%21': '!',
|
|
3641
|
+
'%24': '$',
|
|
3642
|
+
'%26': '&',
|
|
3643
|
+
'%27': "'",
|
|
3644
|
+
'%28': '(',
|
|
3645
|
+
'%29': ')',
|
|
3646
|
+
'%2A': '*',
|
|
3647
|
+
'%2B': '+',
|
|
3648
|
+
'%2C': ',',
|
|
3649
|
+
'%3B': ';',
|
|
3650
|
+
};
|
|
3651
|
+
const didWarn = {};
|
|
3652
|
+
const warnOnce = (message) => {
|
|
3653
|
+
if (didWarn[message]) {
|
|
3654
|
+
return;
|
|
3655
|
+
}
|
|
3656
|
+
console.warn(message);
|
|
3657
|
+
didWarn[message] = true;
|
|
3658
|
+
};
|
|
3659
|
+
const includesHexOfUnsafeChar = (path) => {
|
|
3660
|
+
for (const key of Object.keys(problematicCharacters)) {
|
|
3661
|
+
if (path.includes(key)) {
|
|
3662
|
+
return { containsHex: true, hexCode: key };
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
return { containsHex: false };
|
|
3666
|
+
};
|
|
3595
3667
|
const trimLeadingSlash = (path) => {
|
|
3596
3668
|
if (path.startsWith('/')) {
|
|
3597
|
-
return trimLeadingSlash(path.
|
|
3669
|
+
return trimLeadingSlash(path.substring(1));
|
|
3598
3670
|
}
|
|
3599
3671
|
return path;
|
|
3600
3672
|
};
|
|
@@ -3629,7 +3701,11 @@ const staticFile = (path) => {
|
|
|
3629
3701
|
if (path.startsWith('public/')) {
|
|
3630
3702
|
throw new TypeError(`Do not include the public/ prefix when using staticFile() - got "${path}". See: https://remotion.dev/docs/staticfile-relative-paths`);
|
|
3631
3703
|
}
|
|
3632
|
-
const
|
|
3704
|
+
const includesHex = includesHexOfUnsafeChar(path);
|
|
3705
|
+
if (includesHex.containsHex) {
|
|
3706
|
+
warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). The encoding gets automatically handled by staticFile() `);
|
|
3707
|
+
}
|
|
3708
|
+
const preparsed = inner(encodeURIComponent(path));
|
|
3633
3709
|
if (!preparsed.startsWith('/')) {
|
|
3634
3710
|
return `/${preparsed}`;
|
|
3635
3711
|
}
|
|
@@ -3852,7 +3928,11 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
|
|
|
3852
3928
|
var _a;
|
|
3853
3929
|
if (current === null || current === void 0 ? void 0 : current.error) {
|
|
3854
3930
|
console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
|
|
3855
|
-
|
|
3931
|
+
// If user is handling the error, we don't cause an unhandled exception
|
|
3932
|
+
if (props.onError) {
|
|
3933
|
+
return;
|
|
3934
|
+
}
|
|
3935
|
+
throw new Error(`The browser threw an error while playing the video ${src}: Code ${current.error.code} - ${(_a = current === null || current === void 0 ? void 0 : current.error) === null || _a === void 0 ? void 0 : _a.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
|
|
3856
3936
|
}
|
|
3857
3937
|
else {
|
|
3858
3938
|
throw new Error('The browser threw an error');
|
|
@@ -3862,7 +3942,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
|
|
|
3862
3942
|
return () => {
|
|
3863
3943
|
current.removeEventListener('error', errorHandler);
|
|
3864
3944
|
};
|
|
3865
|
-
}, [src]);
|
|
3945
|
+
}, [props.onError, src]);
|
|
3866
3946
|
const currentOnDurationCallback = useRef();
|
|
3867
3947
|
currentOnDurationCallback.current = onDuration;
|
|
3868
3948
|
useEffect(() => {
|
|
@@ -3894,7 +3974,7 @@ const VideoForDevelopment = forwardRef(VideoForDevelopmentRefForwardingFunction)
|
|
|
3894
3974
|
* @see [Documentation](https://www.remotion.dev/docs/offthreadvideo)
|
|
3895
3975
|
*/
|
|
3896
3976
|
const OffthreadVideo = (props) => {
|
|
3897
|
-
const { startFrom, endAt, ...otherProps } = props;
|
|
3977
|
+
const { startFrom, endAt, imageFormat, ...otherProps } = props;
|
|
3898
3978
|
const environment = useRemotionEnvironment();
|
|
3899
3979
|
const onDuration = useCallback(() => undefined, []);
|
|
3900
3980
|
if (typeof props.src !== 'string') {
|
|
@@ -3911,7 +3991,7 @@ const OffthreadVideo = (props) => {
|
|
|
3911
3991
|
}
|
|
3912
3992
|
validateMediaProps(props, 'Video');
|
|
3913
3993
|
if (environment === 'rendering') {
|
|
3914
|
-
return jsx(OffthreadVideoForRendering, { ...otherProps });
|
|
3994
|
+
return (jsx(OffthreadVideoForRendering, { imageFormat: imageFormat, ...otherProps }));
|
|
3915
3995
|
}
|
|
3916
3996
|
return (jsx(VideoForDevelopment, { onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...otherProps }));
|
|
3917
3997
|
};
|
|
@@ -4045,7 +4125,11 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
|
|
|
4045
4125
|
var _a;
|
|
4046
4126
|
if (current === null || current === void 0 ? void 0 : current.error) {
|
|
4047
4127
|
console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
|
|
4048
|
-
|
|
4128
|
+
// If user is handling the error, we don't cause an unhandled exception
|
|
4129
|
+
if (onError) {
|
|
4130
|
+
return;
|
|
4131
|
+
}
|
|
4132
|
+
throw new Error(`The browser threw an error while playing the video ${props.src}: Code ${current.error.code} - ${(_a = current === null || current === void 0 ? void 0 : current.error) === null || _a === void 0 ? void 0 : _a.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
|
|
4049
4133
|
}
|
|
4050
4134
|
else {
|
|
4051
4135
|
throw new Error('The browser threw an error');
|
|
@@ -4066,6 +4150,7 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
|
|
|
4066
4150
|
videoConfig.fps,
|
|
4067
4151
|
frame,
|
|
4068
4152
|
mediaStartsAt,
|
|
4153
|
+
onError,
|
|
4069
4154
|
]);
|
|
4070
4155
|
const { src } = props;
|
|
4071
4156
|
// If video source switches, make new handle
|
package/dist/esm/version.mjs
CHANGED