remotion 4.0.21 → 4.0.23

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.
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ import type { TAsset } from './CompositionManager.js';
3
+ export type AssetManagerContext = {
4
+ registerAsset: (asset: TAsset) => void;
5
+ unregisterAsset: (id: string) => void;
6
+ assets: TAsset[];
7
+ };
8
+ export declare const AssetManager: import("react").Context<AssetManagerContext>;
9
+ export declare const AssetManagerProvider: React.FC<{
10
+ children: React.ReactNode;
11
+ }>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AssetManagerProvider = exports.AssetManager = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ exports.AssetManager = (0, react_1.createContext)({
7
+ registerAsset: () => undefined,
8
+ unregisterAsset: () => undefined,
9
+ assets: [],
10
+ });
11
+ const AssetManagerProvider = ({ children }) => {
12
+ const [assets, setAssets] = (0, react_1.useState)([]);
13
+ const registerAsset = (0, react_1.useCallback)((asset) => {
14
+ setAssets((assts) => {
15
+ return [...assts, asset];
16
+ });
17
+ }, []);
18
+ const unregisterAsset = (0, react_1.useCallback)((id) => {
19
+ setAssets((assts) => {
20
+ return assts.filter((a) => a.id !== id);
21
+ });
22
+ }, []);
23
+ (0, react_1.useLayoutEffect)(() => {
24
+ if (typeof window !== 'undefined') {
25
+ window.remotion_collectAssets = () => {
26
+ setAssets([]); // clear assets at next render
27
+ return assets;
28
+ };
29
+ }
30
+ }, [assets]);
31
+ const contextValue = (0, react_1.useMemo)(() => {
32
+ return {
33
+ registerAsset,
34
+ unregisterAsset,
35
+ assets,
36
+ };
37
+ }, [assets, registerAsset, unregisterAsset]);
38
+ return ((0, jsx_runtime_1.jsx)(exports.AssetManager.Provider, { value: contextValue, children: children }));
39
+ };
40
+ exports.AssetManagerProvider = AssetManagerProvider;
@@ -46,6 +46,7 @@ declare global {
46
46
  siteVersion: '10';
47
47
  remotion_version: string;
48
48
  remotion_imported: string | boolean;
49
+ remotion_unsavedProps: boolean | undefined;
49
50
  }
50
51
  }
51
52
  export type BundleState = {
@@ -323,8 +323,7 @@ function normalizeColor(color) {
323
323
  if ((match = matchers.hsl.exec(color))) {
324
324
  return ((hslToRgb(parse360(match[1]), // h
325
325
  parsePercentage(match[2]), // s
326
- parsePercentage(match[3]) // l
327
- ) |
326
+ parsePercentage(match[3])) |
328
327
  0x000000ff) >>> // a
329
328
  0);
330
329
  }
@@ -333,8 +332,7 @@ function normalizeColor(color) {
333
332
  if ((match = matchers.hsla.exec(color))) {
334
333
  return ((hslToRgb(parse360(match[1]), // h
335
334
  parsePercentage(match[2]), // s
336
- parsePercentage(match[3]) // l
337
- ) |
335
+ parsePercentage(match[3])) |
338
336
  parse1(match[4])) >>> // a
339
337
  0);
340
338
  }
@@ -0,0 +1,7 @@
1
+ type ContinueRenderFnBinded = () => void;
2
+ /**
3
+ * @description Same as delayRender(), but as a hook.
4
+ * @see [Documentation](https://remotion.dev/docs/use-delay-render)
5
+ */
6
+ export declare const useDelayRender: (label?: string) => ContinueRenderFnBinded;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDelayRender = void 0;
4
+ const react_1 = require("react");
5
+ const delay_render_js_1 = require("./delay-render.js");
6
+ /**
7
+ * @description Same as delayRender(), but as a hook.
8
+ * @see [Documentation](https://remotion.dev/docs/use-delay-render)
9
+ */
10
+ const useDelayRender = (label) => {
11
+ const [handle] = (0, react_1.useState)(() => (0, delay_render_js_1.delayRender)(label));
12
+ return (0, react_1.useCallback)(() => {
13
+ (0, delay_render_js_1.continueRender)(handle);
14
+ }, [handle]);
15
+ };
16
+ exports.useDelayRender = useDelayRender;
@@ -8,8 +8,20 @@ const timeline_position_state_js_1 = require("./timeline-position-state.js");
8
8
  const use_current_frame_js_1 = require("./use-current-frame.js");
9
9
  const use_video_config_js_1 = require("./use-video-config.js");
10
10
  const get_current_time_js_1 = require("./video/get-current-time.js");
11
+ const video_fragment_js_1 = require("./video/video-fragment.js");
11
12
  const warn_about_non_seekable_media_js_1 = require("./warn-about-non-seekable-media.js");
12
13
  exports.DEFAULT_ACCEPTABLE_TIMESHIFT = 0.45;
14
+ const seek = (mediaRef, time) => {
15
+ if (!mediaRef.current) {
16
+ return;
17
+ }
18
+ // iOS seeking does not support multiple decimals
19
+ if ((0, video_fragment_js_1.isIosSafari)()) {
20
+ mediaRef.current.currentTime = Number(time.toFixed(1));
21
+ return;
22
+ }
23
+ mediaRef.current.currentTime = time;
24
+ };
13
25
  const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, }) => {
14
26
  const { playbackRate: globalPlaybackRate } = (0, react_1.useContext)(timeline_position_state_js_1.TimelineContext);
15
27
  const frame = (0, use_current_frame_js_1.useCurrentFrame)();
@@ -53,7 +65,7 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
53
65
  if (timeShift > acceptableTimeshift) {
54
66
  // If scrubbing around, adjust timing
55
67
  // or if time shift is bigger than 0.45sec
56
- mediaRef.current.currentTime = shouldBeTime;
68
+ seek(mediaRef, shouldBeTime);
57
69
  if (!onlyWarnForMediaSeekingError) {
58
70
  (0, warn_about_non_seekable_media_js_1.warnAboutNonSeekableMedia)(mediaRef.current, onlyWarnForMediaSeekingError ? 'console-warning' : 'console-error');
59
71
  }
@@ -67,12 +79,12 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
67
79
  const makesSenseToSeek = Math.abs(mediaRef.current.currentTime - shouldBeTime) > 0.00001;
68
80
  if (!playing || absoluteFrame === 0) {
69
81
  if (makesSenseToSeek) {
70
- mediaRef.current.currentTime = shouldBeTime;
82
+ seek(mediaRef, shouldBeTime);
71
83
  }
72
84
  }
73
85
  if (mediaRef.current.paused && !mediaRef.current.ended && playing) {
74
86
  if (makesSenseToSeek) {
75
- mediaRef.current.currentTime = shouldBeTime;
87
+ seek(mediaRef, shouldBeTime);
76
88
  }
77
89
  (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType);
78
90
  }
@@ -1 +1 @@
1
- export declare const VERSION = "4.0.21";
1
+ export declare const VERSION = "4.0.23";
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Automatically generated on publish
5
- exports.VERSION = '4.0.21';
5
+ exports.VERSION = '4.0.23';
@@ -111,7 +111,11 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
111
111
  current.removeEventListener('loadedmetadata', onLoadedMetadata);
112
112
  };
113
113
  }, [src]);
114
- return ((0, jsx_runtime_1.jsx)("video", { ref: videoRef, muted: muted || mediaMuted, playsInline: true, src: actualSrc, ...nativeProps }));
114
+ return ((0, jsx_runtime_1.jsx)("video", { ref: videoRef,
115
+ // Without this, on iOS Safari, the video cannot be seeked.
116
+ // if a seek is triggered before `loadedmetadata` is fired,
117
+ // the video will not seek, even if `loadedmetadata` is fired afterwards.
118
+ preload: (0, video_fragment_js_1.isIosSafari)() ? 'metadata' : 'auto', muted: muted || mediaMuted, playsInline: true, src: actualSrc, ...nativeProps }));
115
119
  };
116
120
  // Copy types from forwardRef but not necessary to remove ref
117
121
  exports.VideoForDevelopment = (0, react_1.forwardRef)(VideoForDevelopmentRefForwardingFunction);
@@ -4,6 +4,7 @@ export declare const useAppendVideoFragment: ({ actualSrc: initialActualSrc, act
4
4
  duration: number;
5
5
  fps: number;
6
6
  }) => string;
7
+ export declare const isIosSafari: () => boolean;
7
8
  export declare const appendVideoFragment: ({ actualSrc, actualFrom, duration, fps, }: {
8
9
  actualSrc: string;
9
10
  actualFrom: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.appendVideoFragment = exports.useAppendVideoFragment = void 0;
3
+ exports.appendVideoFragment = exports.isIosSafari = exports.useAppendVideoFragment = void 0;
4
4
  const react_1 = require("react");
5
5
  const toSeconds = (time, fps) => {
6
6
  return Math.round((time / fps) * 100) / 100;
@@ -27,6 +27,11 @@ const useAppendVideoFragment = ({ actualSrc: initialActualSrc, actualFrom: initi
27
27
  return appended;
28
28
  };
29
29
  exports.useAppendVideoFragment = useAppendVideoFragment;
30
+ const isIosSafari = () => {
31
+ return (/iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
32
+ Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/)));
33
+ };
34
+ exports.isIosSafari = isIosSafari;
30
35
  // https://github.com/remotion-dev/remotion/issues/1655
31
36
  const isIOSSafariCase = (actualSrc) => {
32
37
  return typeof window === 'undefined'
@@ -59,7 +59,7 @@ function truthy(value) {
59
59
  }
60
60
 
61
61
  // Automatically generated on publish
62
- const VERSION = '4.0.21';
62
+ const VERSION = '4.0.23';
63
63
 
64
64
  const checkMultipleRemotionVersions = () => {
65
65
  if (typeof globalThis === 'undefined') {
@@ -1722,6 +1722,65 @@ const getMediaTime = ({ fps, frame, src, playbackRate, startFrom, mediaType, })
1722
1722
  return (expectedFrame * msPerFrame + msShift) / 1000;
1723
1723
  };
1724
1724
 
1725
+ const toSeconds = (time, fps) => {
1726
+ return Math.round((time / fps) * 100) / 100;
1727
+ };
1728
+ const isSubsetOfDuration = (prevStartFrom, newStartFrom, prevDuration, newDuration) => {
1729
+ return (prevStartFrom <= newStartFrom &&
1730
+ prevStartFrom + prevDuration >= newStartFrom + newDuration);
1731
+ };
1732
+ const useAppendVideoFragment = ({ actualSrc: initialActualSrc, actualFrom: initialActualFrom, duration: initialDuration, fps, }) => {
1733
+ const actualFromRef = useRef(initialActualFrom);
1734
+ const actualDuration = useRef(initialDuration);
1735
+ const actualSrc = useRef(initialActualSrc);
1736
+ if (!isSubsetOfDuration || initialActualSrc !== actualSrc.current) {
1737
+ actualFromRef.current = initialActualFrom;
1738
+ actualDuration.current = initialDuration;
1739
+ actualSrc.current = initialActualSrc;
1740
+ }
1741
+ const appended = appendVideoFragment({
1742
+ actualSrc: actualSrc.current,
1743
+ actualFrom: actualFromRef.current,
1744
+ duration: actualDuration.current,
1745
+ fps,
1746
+ });
1747
+ return appended;
1748
+ };
1749
+ const isIosSafari = () => {
1750
+ return (/iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
1751
+ Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/)));
1752
+ };
1753
+ // https://github.com/remotion-dev/remotion/issues/1655
1754
+ const isIOSSafariCase = (actualSrc) => {
1755
+ return typeof window === 'undefined'
1756
+ ? false
1757
+ : /iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
1758
+ Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/)) &&
1759
+ actualSrc.startsWith('blob:');
1760
+ };
1761
+ const appendVideoFragment = ({ actualSrc, actualFrom, duration, fps, }) => {
1762
+ var _a;
1763
+ if (isIOSSafariCase(actualSrc)) {
1764
+ return actualSrc;
1765
+ }
1766
+ if (actualSrc.startsWith('data:')) {
1767
+ return actualSrc;
1768
+ }
1769
+ const existingHash = Boolean(new URL(actualSrc, (_a = (typeof window === 'undefined' ? null : window.location.href)) !== null && _a !== void 0 ? _a : 'http://localhost:3000').hash);
1770
+ if (existingHash) {
1771
+ return actualSrc;
1772
+ }
1773
+ if (!Number.isFinite(actualFrom)) {
1774
+ return actualSrc;
1775
+ }
1776
+ actualSrc += `#t=${toSeconds(-actualFrom, fps)}`;
1777
+ if (!Number.isFinite(duration)) {
1778
+ return actualSrc;
1779
+ }
1780
+ actualSrc += `,${toSeconds(duration, fps)}`;
1781
+ return actualSrc;
1782
+ };
1783
+
1725
1784
  const alreadyWarned = {};
1726
1785
  const warnAboutNonSeekableMedia = (ref, type) => {
1727
1786
  // Media is not loaded yet, but this does not yet mean something is wrong with the media
@@ -1754,6 +1813,17 @@ const warnAboutNonSeekableMedia = (ref, type) => {
1754
1813
  };
1755
1814
 
1756
1815
  const DEFAULT_ACCEPTABLE_TIMESHIFT = 0.45;
1816
+ const seek = (mediaRef, time) => {
1817
+ if (!mediaRef.current) {
1818
+ return;
1819
+ }
1820
+ // iOS seeking does not support multiple decimals
1821
+ if (isIosSafari()) {
1822
+ mediaRef.current.currentTime = Number(time.toFixed(1));
1823
+ return;
1824
+ }
1825
+ mediaRef.current.currentTime = time;
1826
+ };
1757
1827
  const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, }) => {
1758
1828
  const { playbackRate: globalPlaybackRate } = useContext(TimelineContext);
1759
1829
  const frame = useCurrentFrame();
@@ -1797,7 +1867,7 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
1797
1867
  if (timeShift > acceptableTimeshift) {
1798
1868
  // If scrubbing around, adjust timing
1799
1869
  // or if time shift is bigger than 0.45sec
1800
- mediaRef.current.currentTime = shouldBeTime;
1870
+ seek(mediaRef, shouldBeTime);
1801
1871
  if (!onlyWarnForMediaSeekingError) {
1802
1872
  warnAboutNonSeekableMedia(mediaRef.current, onlyWarnForMediaSeekingError ? 'console-warning' : 'console-error');
1803
1873
  }
@@ -1811,12 +1881,12 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
1811
1881
  const makesSenseToSeek = Math.abs(mediaRef.current.currentTime - shouldBeTime) > 0.00001;
1812
1882
  if (!playing || absoluteFrame === 0) {
1813
1883
  if (makesSenseToSeek) {
1814
- mediaRef.current.currentTime = shouldBeTime;
1884
+ seek(mediaRef, shouldBeTime);
1815
1885
  }
1816
1886
  }
1817
1887
  if (mediaRef.current.paused && !mediaRef.current.ended && playing) {
1818
1888
  if (makesSenseToSeek) {
1819
- mediaRef.current.currentTime = shouldBeTime;
1889
+ seek(mediaRef, shouldBeTime);
1820
1890
  }
1821
1891
  playAndHandleNotAllowedError(mediaRef, mediaType);
1822
1892
  }
@@ -3546,8 +3616,7 @@ function normalizeColor(color) {
3546
3616
  if ((match = matchers.hsl.exec(color))) {
3547
3617
  return ((hslToRgb(parse360(match[1]), // h
3548
3618
  parsePercentage(match[2]), // s
3549
- parsePercentage(match[3]) // l
3550
- ) |
3619
+ parsePercentage(match[3])) |
3551
3620
  0x000000ff) >>> // a
3552
3621
  0);
3553
3622
  }
@@ -3556,8 +3625,7 @@ function normalizeColor(color) {
3556
3625
  if ((match = matchers.hsla.exec(color))) {
3557
3626
  return ((hslToRgb(parse360(match[1]), // h
3558
3627
  parsePercentage(match[2]), // s
3559
- parsePercentage(match[3]) // l
3560
- ) |
3628
+ parsePercentage(match[3])) |
3561
3629
  parse1(match[4])) >>> // a
3562
3630
  0);
3563
3631
  }
@@ -4296,61 +4364,6 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
4296
4364
  return (jsx(Img, { src: actualSrc, className: className, ...props, onError: onErr }));
4297
4365
  };
4298
4366
 
4299
- const toSeconds = (time, fps) => {
4300
- return Math.round((time / fps) * 100) / 100;
4301
- };
4302
- const isSubsetOfDuration = (prevStartFrom, newStartFrom, prevDuration, newDuration) => {
4303
- return (prevStartFrom <= newStartFrom &&
4304
- prevStartFrom + prevDuration >= newStartFrom + newDuration);
4305
- };
4306
- const useAppendVideoFragment = ({ actualSrc: initialActualSrc, actualFrom: initialActualFrom, duration: initialDuration, fps, }) => {
4307
- const actualFromRef = useRef(initialActualFrom);
4308
- const actualDuration = useRef(initialDuration);
4309
- const actualSrc = useRef(initialActualSrc);
4310
- if (!isSubsetOfDuration || initialActualSrc !== actualSrc.current) {
4311
- actualFromRef.current = initialActualFrom;
4312
- actualDuration.current = initialDuration;
4313
- actualSrc.current = initialActualSrc;
4314
- }
4315
- const appended = appendVideoFragment({
4316
- actualSrc: actualSrc.current,
4317
- actualFrom: actualFromRef.current,
4318
- duration: actualDuration.current,
4319
- fps,
4320
- });
4321
- return appended;
4322
- };
4323
- // https://github.com/remotion-dev/remotion/issues/1655
4324
- const isIOSSafariCase = (actualSrc) => {
4325
- return typeof window === 'undefined'
4326
- ? false
4327
- : /iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
4328
- Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/)) &&
4329
- actualSrc.startsWith('blob:');
4330
- };
4331
- const appendVideoFragment = ({ actualSrc, actualFrom, duration, fps, }) => {
4332
- var _a;
4333
- if (isIOSSafariCase(actualSrc)) {
4334
- return actualSrc;
4335
- }
4336
- if (actualSrc.startsWith('data:')) {
4337
- return actualSrc;
4338
- }
4339
- const existingHash = Boolean(new URL(actualSrc, (_a = (typeof window === 'undefined' ? null : window.location.href)) !== null && _a !== void 0 ? _a : 'http://localhost:3000').hash);
4340
- if (existingHash) {
4341
- return actualSrc;
4342
- }
4343
- if (!Number.isFinite(actualFrom)) {
4344
- return actualSrc;
4345
- }
4346
- actualSrc += `#t=${toSeconds(-actualFrom, fps)}`;
4347
- if (!Number.isFinite(duration)) {
4348
- return actualSrc;
4349
- }
4350
- actualSrc += `,${toSeconds(duration, fps)}`;
4351
- return actualSrc;
4352
- };
4353
-
4354
4367
  const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
4355
4368
  var _a, _b;
4356
4369
  const videoRef = useRef(null);
@@ -4449,7 +4462,11 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
4449
4462
  current.removeEventListener('loadedmetadata', onLoadedMetadata);
4450
4463
  };
4451
4464
  }, [src]);
4452
- return (jsx("video", { ref: videoRef, muted: muted || mediaMuted, playsInline: true, src: actualSrc, ...nativeProps }));
4465
+ return (jsx("video", { ref: videoRef,
4466
+ // Without this, on iOS Safari, the video cannot be seeked.
4467
+ // if a seek is triggered before `loadedmetadata` is fired,
4468
+ // the video will not seek, even if `loadedmetadata` is fired afterwards.
4469
+ preload: isIosSafari() ? 'metadata' : 'auto', muted: muted || mediaMuted, playsInline: true, src: actualSrc, ...nativeProps }));
4453
4470
  };
4454
4471
  // Copy types from forwardRef but not necessary to remove ref
4455
4472
  const VideoForDevelopment = forwardRef(VideoForDevelopmentRefForwardingFunction);
@@ -1,4 +1,4 @@
1
1
  // Automatically generated on publish
2
- const VERSION = '4.0.21';
2
+ const VERSION = '4.0.23';
3
3
 
4
4
  export { VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remotion",
3
- "version": "4.0.21",
3
+ "version": "4.0.23",
4
4
  "description": "Render videos in React",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "eslint": "8.42.0",
29
29
  "eslint-plugin-require-extensions": "^0.1.2",
30
30
  "jsdom": "21.1.0",
31
- "prettier": "^2.7.1",
31
+ "prettier": "3.0.2",
32
32
  "prettier-plugin-organize-imports": "^3.2.2",
33
33
  "react": "^18.0.0",
34
34
  "react-dom": "^18.0.0",