remotion 4.0.0-webhook.27 → 4.1.0-alpha2

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.
Files changed (283) hide show
  1. package/LICENSE.md +8 -8
  2. package/README.md +7 -7
  3. package/dist/{AbsoluteFill.d.ts → cjs/AbsoluteFill.d.ts} +2 -2
  4. package/dist/{AbsoluteFill.js → cjs/AbsoluteFill.js} +2 -2
  5. package/dist/cjs/AssetManager.d.ts +11 -0
  6. package/dist/cjs/AssetManager.js +40 -0
  7. package/dist/{CanUseRemotionHooks.d.ts → cjs/CanUseRemotionHooks.d.ts} +0 -0
  8. package/dist/{CanUseRemotionHooks.js → cjs/CanUseRemotionHooks.js} +0 -0
  9. package/dist/cjs/Clipper.d.ts +7 -0
  10. package/dist/cjs/Clipper.js +24 -0
  11. package/dist/cjs/Composition.d.ts +41 -0
  12. package/dist/cjs/Composition.js +132 -0
  13. package/dist/cjs/CompositionManager.d.ts +75 -0
  14. package/dist/{CompositionManager.js → cjs/CompositionManager.js} +29 -66
  15. package/dist/cjs/CompositionManagerContext.d.ts +18 -0
  16. package/dist/cjs/CompositionManagerContext.js +16 -0
  17. package/dist/cjs/EditorProps.d.ts +15 -0
  18. package/dist/cjs/EditorProps.js +53 -0
  19. package/dist/{Folder.d.ts → cjs/Folder.d.ts} +6 -2
  20. package/dist/{Folder.js → cjs/Folder.js} +10 -6
  21. package/dist/{IFrame.d.ts → cjs/IFrame.d.ts} +4 -0
  22. package/dist/{IFrame.js → cjs/IFrame.js} +8 -4
  23. package/dist/cjs/Img.d.ts +9 -0
  24. package/dist/cjs/Img.js +100 -0
  25. package/dist/cjs/NativeLayers.d.ts +13 -0
  26. package/dist/cjs/NativeLayers.js +29 -0
  27. package/dist/cjs/Null.d.ts +2 -0
  28. package/dist/cjs/Null.js +25 -0
  29. package/dist/{RemotionRoot.d.ts → cjs/RemotionRoot.d.ts} +1 -0
  30. package/dist/cjs/RemotionRoot.js +72 -0
  31. package/dist/cjs/ResolveCompositionConfig.d.ts +24 -0
  32. package/dist/cjs/ResolveCompositionConfig.js +192 -0
  33. package/dist/cjs/Sequence.d.ts +22 -0
  34. package/dist/{Sequence.js → cjs/Sequence.js} +27 -29
  35. package/dist/cjs/SequenceContext.d.ts +9 -0
  36. package/dist/cjs/SequenceContext.js +5 -0
  37. package/dist/cjs/SequenceManager.d.ts +11 -0
  38. package/dist/cjs/SequenceManager.js +57 -0
  39. package/dist/cjs/Still.d.ts +8 -0
  40. package/dist/cjs/Still.js +22 -0
  41. package/dist/{absolute-src.d.ts → cjs/absolute-src.d.ts} +0 -0
  42. package/dist/{absolute-src.js → cjs/absolute-src.js} +0 -0
  43. package/dist/{asset-types.d.ts → cjs/asset-types.d.ts} +0 -0
  44. package/dist/{asset-types.js → cjs/asset-types.js} +0 -0
  45. package/dist/{audio → cjs/audio}/Audio.d.ts +10 -4
  46. package/dist/cjs/audio/Audio.js +58 -0
  47. package/dist/cjs/audio/AudioForDevelopment.d.ts +11 -0
  48. package/dist/cjs/audio/AudioForDevelopment.js +101 -0
  49. package/dist/cjs/audio/AudioForRendering.d.ts +10 -0
  50. package/dist/cjs/audio/AudioForRendering.js +111 -0
  51. package/dist/cjs/audio/index.d.ts +2 -0
  52. package/dist/{audio → cjs/audio}/index.js +2 -2
  53. package/dist/cjs/audio/props.d.ts +12 -0
  54. package/dist/{audio → cjs/audio}/props.js +0 -0
  55. package/dist/{audio → cjs/audio}/shared-audio-tags.d.ts +10 -4
  56. package/dist/{audio → cjs/audio}/shared-audio-tags.js +35 -13
  57. package/dist/{audio → cjs/audio}/use-audio-frame.d.ts +0 -0
  58. package/dist/{audio → cjs/audio}/use-audio-frame.js +4 -4
  59. package/dist/{bezier.d.ts → cjs/bezier.d.ts} +0 -0
  60. package/dist/{bezier.js → cjs/bezier.js} +0 -0
  61. package/dist/cjs/cancel-render.d.ts +5 -0
  62. package/dist/cjs/cancel-render.js +47 -0
  63. package/dist/{config → cjs/config}/input-props.d.ts +0 -0
  64. package/dist/{config → cjs/config}/input-props.js +3 -3
  65. package/dist/{default-css.d.ts → cjs/default-css.d.ts} +0 -0
  66. package/dist/{default-css.js → cjs/default-css.js} +0 -0
  67. package/dist/{delay-render.d.ts → cjs/delay-render.d.ts} +4 -4
  68. package/dist/{delay-render.js → cjs/delay-render.js} +12 -12
  69. package/dist/{easing.d.ts → cjs/easing.d.ts} +4 -0
  70. package/dist/{easing.js → cjs/easing.js} +6 -2
  71. package/dist/cjs/freeze.d.ts +11 -0
  72. package/dist/{freeze.js → cjs/freeze.js} +8 -4
  73. package/dist/{get-asset-file-name.d.ts → cjs/get-asset-file-name.d.ts} +0 -0
  74. package/dist/{get-asset-file-name.js → cjs/get-asset-file-name.js} +0 -0
  75. package/dist/cjs/get-environment.d.ts +3 -0
  76. package/dist/{get-environment.js → cjs/get-environment.js} +14 -2
  77. package/dist/cjs/get-preview-dom-element.d.ts +2 -0
  78. package/dist/cjs/get-preview-dom-element.js +8 -0
  79. package/dist/cjs/get-static-files.d.ts +21 -0
  80. package/dist/cjs/get-static-files.js +35 -0
  81. package/dist/{get-timeline-clip-name.d.ts → cjs/get-timeline-clip-name.d.ts} +0 -0
  82. package/dist/{get-timeline-clip-name.js → cjs/get-timeline-clip-name.js} +0 -0
  83. package/dist/cjs/index.d.ts +102 -0
  84. package/dist/cjs/index.js +105 -0
  85. package/dist/cjs/internals.d.ts +131 -0
  86. package/dist/cjs/internals.js +120 -0
  87. package/dist/{interpolate-colors.d.ts → cjs/interpolate-colors.d.ts} +5 -0
  88. package/dist/{interpolate-colors.js → cjs/interpolate-colors.js} +10 -10
  89. package/dist/{interpolate.d.ts → cjs/interpolate.d.ts} +11 -7
  90. package/dist/{interpolate.js → cjs/interpolate.js} +0 -0
  91. package/dist/{is-approximately-the-same.d.ts → cjs/is-approximately-the-same.d.ts} +0 -0
  92. package/dist/{is-approximately-the-same.js → cjs/is-approximately-the-same.js} +0 -0
  93. package/dist/cjs/is-player.d.ts +3 -0
  94. package/dist/cjs/is-player.js +14 -0
  95. package/dist/{loading-indicator.d.ts → cjs/loading-indicator.d.ts} +0 -0
  96. package/dist/{loading-indicator.js → cjs/loading-indicator.js} +4 -4
  97. package/dist/cjs/loop/index.d.ts +13 -0
  98. package/dist/cjs/loop/index.js +46 -0
  99. package/dist/{multiple-versions-warning.d.ts → cjs/multiple-versions-warning.d.ts} +0 -0
  100. package/dist/{multiple-versions-warning.js → cjs/multiple-versions-warning.js} +11 -6
  101. package/dist/{nonce.d.ts → cjs/nonce.d.ts} +1 -1
  102. package/dist/{nonce.js → cjs/nonce.js} +6 -0
  103. package/dist/{play-and-handle-not-allowed-error.d.ts → cjs/play-and-handle-not-allowed-error.d.ts} +0 -0
  104. package/dist/{play-and-handle-not-allowed-error.js → cjs/play-and-handle-not-allowed-error.js} +4 -0
  105. package/dist/{portal-node.d.ts → cjs/portal-node.d.ts} +0 -0
  106. package/dist/{portal-node.js → cjs/portal-node.js} +0 -0
  107. package/dist/cjs/prefetch-state.d.ts +8 -0
  108. package/dist/cjs/prefetch-state.js +27 -0
  109. package/dist/cjs/prefetch.d.ts +13 -0
  110. package/dist/{prefetch.js → cjs/prefetch.js} +43 -17
  111. package/dist/cjs/props-if-has-props.d.ts +10 -0
  112. package/dist/{video-config.js → cjs/props-if-has-props.js} +0 -0
  113. package/dist/cjs/random.d.ts +6 -0
  114. package/dist/{random.js → cjs/random.js} +3 -3
  115. package/dist/{register-root.d.ts → cjs/register-root.d.ts} +4 -0
  116. package/dist/{register-root.js → cjs/register-root.js} +4 -0
  117. package/dist/cjs/resolve-video-config.d.ts +8 -0
  118. package/dist/cjs/resolve-video-config.js +89 -0
  119. package/dist/cjs/series/flatten-children.d.ts +2 -0
  120. package/dist/{series → cjs/series}/flatten-children.js +0 -0
  121. package/dist/cjs/series/index.d.ts +17 -0
  122. package/dist/{series → cjs/series}/index.js +22 -8
  123. package/dist/cjs/setup-env-variables.d.ts +1 -0
  124. package/dist/{setup-env-variables.js → cjs/setup-env-variables.js} +7 -9
  125. package/dist/{spring → cjs/spring}/index.d.ts +10 -6
  126. package/dist/cjs/spring/index.js +75 -0
  127. package/dist/cjs/spring/measure-spring.d.ts +12 -0
  128. package/dist/{spring → cjs/spring}/measure-spring.js +8 -4
  129. package/dist/{spring → cjs/spring}/spring-utils.d.ts +2 -2
  130. package/dist/{spring → cjs/spring}/spring-utils.js +0 -0
  131. package/dist/cjs/static-file.d.ts +33 -0
  132. package/dist/cjs/static-file.js +87 -0
  133. package/dist/{timeline-position-state.d.ts → cjs/timeline-position-state.d.ts} +4 -4
  134. package/dist/{timeline-position-state.js → cjs/timeline-position-state.js} +9 -1
  135. package/dist/cjs/truthy.d.ts +3 -0
  136. package/dist/{truthy.js → cjs/truthy.js} +0 -0
  137. package/dist/cjs/use-current-frame.d.ts +5 -0
  138. package/dist/{use-current-frame.js → cjs/use-current-frame.js} +8 -9
  139. package/dist/cjs/use-lazy-component.d.ts +7 -0
  140. package/dist/{use-lazy-component.js → cjs/use-lazy-component.js} +0 -0
  141. package/dist/{use-media-in-timeline.d.ts → cjs/use-media-in-timeline.d.ts} +3 -2
  142. package/dist/{use-media-in-timeline.js → cjs/use-media-in-timeline.js} +29 -25
  143. package/dist/{use-media-playback.d.ts → cjs/use-media-playback.d.ts} +3 -1
  144. package/dist/cjs/use-media-playback.js +86 -0
  145. package/dist/{use-media-tag-volume.d.ts → cjs/use-media-tag-volume.d.ts} +0 -0
  146. package/dist/{use-media-tag-volume.js → cjs/use-media-tag-volume.js} +0 -0
  147. package/dist/{use-sync-volume-with-media-tag.d.ts → cjs/use-sync-volume-with-media-tag.d.ts} +2 -2
  148. package/dist/{use-sync-volume-with-media-tag.js → cjs/use-sync-volume-with-media-tag.js} +5 -4
  149. package/dist/{use-unsafe-video-config.d.ts → cjs/use-unsafe-video-config.d.ts} +1 -1
  150. package/dist/{use-unsafe-video-config.js → cjs/use-unsafe-video-config.js} +4 -4
  151. package/dist/cjs/use-video-config.d.ts +8 -0
  152. package/dist/cjs/use-video-config.js +34 -0
  153. package/dist/cjs/use-video.d.ts +7 -0
  154. package/dist/cjs/use-video.js +38 -0
  155. package/dist/cjs/validate-frame.d.ts +5 -0
  156. package/dist/cjs/validate-frame.js +24 -0
  157. package/dist/cjs/validate-media-props.d.ts +4 -0
  158. package/dist/{validate-media-props.js → cjs/validate-media-props.js} +0 -0
  159. package/dist/{validate-start-from-props.d.ts → cjs/validate-start-from-props.d.ts} +0 -0
  160. package/dist/{validate-start-from-props.js → cjs/validate-start-from-props.js} +0 -0
  161. package/dist/{validation → cjs/validation}/validate-composition-id.d.ts +0 -0
  162. package/dist/{validation → cjs/validation}/validate-composition-id.js +0 -0
  163. package/dist/cjs/validation/validate-default-props.d.ts +1 -0
  164. package/dist/cjs/validation/validate-default-props.js +15 -0
  165. package/dist/{validation → cjs/validation}/validate-dimensions.d.ts +0 -0
  166. package/dist/{validation → cjs/validation}/validate-dimensions.js +0 -0
  167. package/dist/cjs/validation/validate-duration-in-frames.d.ts +5 -0
  168. package/dist/{validation → cjs/validation}/validate-duration-in-frames.js +5 -2
  169. package/dist/{validation → cjs/validation}/validate-folder-name.d.ts +0 -0
  170. package/dist/{validation → cjs/validation}/validate-folder-name.js +0 -0
  171. package/dist/{validation → cjs/validation}/validate-fps.d.ts +0 -0
  172. package/dist/{validation → cjs/validation}/validate-fps.js +0 -0
  173. package/dist/{validation → cjs/validation}/validation-spring-duration.d.ts +0 -0
  174. package/dist/{validation → cjs/validation}/validation-spring-duration.js +0 -0
  175. package/dist/cjs/version.d.ts +1 -0
  176. package/dist/{version.js → cjs/version.js} +1 -1
  177. package/dist/cjs/video/OffthreadVideo.d.ts +7 -0
  178. package/dist/cjs/video/OffthreadVideo.js +38 -0
  179. package/dist/{video → cjs/video}/OffthreadVideoForRendering.d.ts +1 -1
  180. package/dist/cjs/video/OffthreadVideoForRendering.js +103 -0
  181. package/dist/cjs/video/Video.d.ts +12 -0
  182. package/dist/cjs/video/Video.js +55 -0
  183. package/dist/{video → cjs/video}/VideoForDevelopment.d.ts +5 -2
  184. package/dist/cjs/video/VideoForDevelopment.js +117 -0
  185. package/dist/cjs/video/VideoForRendering.d.ts +10 -0
  186. package/dist/cjs/video/VideoForRendering.js +208 -0
  187. package/dist/cjs/video/duration-state.d.ts +17 -0
  188. package/dist/cjs/video/duration-state.js +35 -0
  189. package/dist/{video → cjs/video}/get-current-time.d.ts +0 -0
  190. package/dist/{video → cjs/video}/get-current-time.js +12 -11
  191. package/dist/cjs/video/index.d.ts +3 -0
  192. package/dist/{video → cjs/video}/index.js +4 -4
  193. package/dist/cjs/video/props.d.ts +32 -0
  194. package/dist/cjs/video/props.js +2 -0
  195. package/dist/cjs/video/video-fragment.d.ts +12 -0
  196. package/dist/cjs/video/video-fragment.js +60 -0
  197. package/dist/{video-config.d.ts → cjs/video-config.d.ts} +2 -2
  198. package/dist/{video/props.js → cjs/video-config.js} +0 -0
  199. package/dist/{volume-position-state.d.ts → cjs/volume-position-state.d.ts} +4 -4
  200. package/dist/{volume-position-state.js → cjs/volume-position-state.js} +0 -0
  201. package/dist/{volume-prop.d.ts → cjs/volume-prop.d.ts} +3 -2
  202. package/dist/{volume-prop.js → cjs/volume-prop.js} +4 -3
  203. package/dist/{warn-about-non-seekable-media.d.ts → cjs/warn-about-non-seekable-media.d.ts} +0 -0
  204. package/dist/{warn-about-non-seekable-media.js → cjs/warn-about-non-seekable-media.js} +2 -2
  205. package/dist/cjs/wrap-remotion-context.d.ts +31 -0
  206. package/dist/cjs/wrap-remotion-context.js +85 -0
  207. package/dist/esm/index.mjs +4623 -0
  208. package/dist/esm/version.mjs +4 -0
  209. package/package.json +80 -57
  210. package/version.js +2 -1
  211. package/.prettierrc.js +0 -14
  212. package/.turbo/turbo-build.log +0 -5
  213. package/dist/Composition.d.ts +0 -22
  214. package/dist/Composition.js +0 -98
  215. package/dist/CompositionManager.d.ts +0 -79
  216. package/dist/Img.d.ts +0 -2
  217. package/dist/Img.js +0 -51
  218. package/dist/RemotionRoot.js +0 -71
  219. package/dist/Sequence.d.ts +0 -29
  220. package/dist/Still.d.ts +0 -3
  221. package/dist/Still.js +0 -9
  222. package/dist/audio/Audio.js +0 -32
  223. package/dist/audio/AudioForDevelopment.d.ts +0 -8
  224. package/dist/audio/AudioForDevelopment.js +0 -71
  225. package/dist/audio/AudioForRendering.d.ts +0 -6
  226. package/dist/audio/AudioForRendering.js +0 -75
  227. package/dist/audio/index.d.ts +0 -2
  228. package/dist/audio/props.d.ts +0 -10
  229. package/dist/config.d.ts +0 -218
  230. package/dist/config.js +0 -21
  231. package/dist/freeze.d.ts +0 -7
  232. package/dist/get-environment.d.ts +0 -2
  233. package/dist/get-preview-dom-element.d.ts +0 -1
  234. package/dist/get-preview-dom-element.js +0 -7
  235. package/dist/index.d.ts +0 -72
  236. package/dist/index.js +0 -58
  237. package/dist/internals.d.ts +0 -88
  238. package/dist/internals.js +0 -93
  239. package/dist/loop/index.d.ts +0 -9
  240. package/dist/loop/index.js +0 -28
  241. package/dist/prefetch-state.d.ts +0 -13
  242. package/dist/prefetch-state.js +0 -26
  243. package/dist/prefetch.d.ts +0 -7
  244. package/dist/random.d.ts +0 -6
  245. package/dist/series/flatten-children.d.ts +0 -2
  246. package/dist/series/index.d.ts +0 -13
  247. package/dist/setup-env-variables.d.ts +0 -2
  248. package/dist/spring/index.js +0 -51
  249. package/dist/spring/measure-spring.d.ts +0 -8
  250. package/dist/static-file.d.ts +0 -1
  251. package/dist/static-file.js +0 -29
  252. package/dist/truthy.d.ts +0 -3
  253. package/dist/use-current-frame.d.ts +0 -6
  254. package/dist/use-lazy-component.d.ts +0 -7
  255. package/dist/use-media-playback.js +0 -75
  256. package/dist/use-video-config.d.ts +0 -7
  257. package/dist/use-video-config.js +0 -26
  258. package/dist/use-video.d.ts +0 -13
  259. package/dist/use-video.js +0 -28
  260. package/dist/validate-media-props.d.ts +0 -4
  261. package/dist/validation/validate-duration-in-frames.d.ts +0 -1
  262. package/dist/validation/validate-offthreadvideo-image-format.d.ts +0 -1
  263. package/dist/validation/validate-offthreadvideo-image-format.js +0 -15
  264. package/dist/version.d.ts +0 -1
  265. package/dist/video/LoopedVideo.d.ts +0 -3
  266. package/dist/video/LoopedVideo.js +0 -16
  267. package/dist/video/OffthreadVideo.d.ts +0 -3
  268. package/dist/video/OffthreadVideo.js +0 -27
  269. package/dist/video/OffthreadVideoForRendering.js +0 -101
  270. package/dist/video/Video.d.ts +0 -6
  271. package/dist/video/Video.js +0 -29
  272. package/dist/video/VideoForDevelopment.js +0 -69
  273. package/dist/video/VideoForRendering.d.ts +0 -6
  274. package/dist/video/VideoForRendering.js +0 -168
  275. package/dist/video/duration-state.d.ts +0 -8
  276. package/dist/video/duration-state.js +0 -15
  277. package/dist/video/index.d.ts +0 -3
  278. package/dist/video/props.d.ts +0 -21
  279. package/dist/wrap-remotion-context.d.ts +0 -14
  280. package/dist/wrap-remotion-context.js +0 -65
  281. package/ensure-correct-version.js +0 -24
  282. package/tsconfig.json +0 -12
  283. package/version.d.ts +0 -1
@@ -0,0 +1,4623 @@
1
+ import React, { createContext, useState, useMemo, useLayoutEffect, useContext, useEffect, forwardRef, Children, isValidElement, useRef, useCallback, createRef, useImperativeHandle, useReducer, Suspense } from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { createPortal } from 'react-dom';
4
+
5
+ const NativeLayersContext = createContext({
6
+ setClipRegion: () => {
7
+ throw new Error('NativeLayers not set');
8
+ },
9
+ clipRegion: null,
10
+ });
11
+ const NativeLayersProvider = ({ children, }) => {
12
+ const [clipRegion, setClipRegion] = useState(null);
13
+ const context = useMemo(() => {
14
+ return {
15
+ setClipRegion,
16
+ clipRegion,
17
+ };
18
+ }, [clipRegion, setClipRegion]);
19
+ useLayoutEffect(() => {
20
+ if (typeof window !== 'undefined') {
21
+ window.remotion_getClipRegion = () => {
22
+ return clipRegion;
23
+ };
24
+ }
25
+ }, [clipRegion, setClipRegion]);
26
+ return (jsx(NativeLayersContext.Provider, { value: context, children: children }));
27
+ };
28
+
29
+ const Clipper = ({ height, width, x, y }) => {
30
+ const { setClipRegion } = useContext(NativeLayersContext);
31
+ useEffect(() => {
32
+ setClipRegion((c) => {
33
+ if (c === 'hide') {
34
+ throw new Error('Cannot render <Clipper>, because another <Null> is already rendered');
35
+ }
36
+ if (c === null) {
37
+ return { height, width, x, y };
38
+ }
39
+ throw new Error('Cannot render <Clipper>, because another component clipping the region was already rendered (most likely <Clipper>)');
40
+ });
41
+ return () => {
42
+ setClipRegion(null);
43
+ };
44
+ }, [height, setClipRegion, width, x, y]);
45
+ return null;
46
+ };
47
+
48
+ const IsPlayerContext = createContext(false);
49
+ const IsPlayerContextProvider = ({ children, }) => {
50
+ return jsx(IsPlayerContext.Provider, { value: true, children: children });
51
+ };
52
+ const useIsPlayer = () => {
53
+ return useContext(IsPlayerContext);
54
+ };
55
+
56
+ function truthy(value) {
57
+ return Boolean(value);
58
+ }
59
+
60
+ // Automatically generated on publish
61
+ const VERSION = '4.1.0-alpha2';
62
+
63
+ const checkMultipleRemotionVersions = () => {
64
+ if (typeof globalThis === 'undefined') {
65
+ return;
66
+ }
67
+ const alreadyImported = globalThis.remotion_imported ||
68
+ (typeof window !== 'undefined' && window.remotion_imported);
69
+ if (alreadyImported) {
70
+ if (alreadyImported === VERSION) {
71
+ // Next.JS will reload the package and cause a server-side warning.
72
+ // It's okay if this happens during SSR in developement
73
+ return;
74
+ }
75
+ throw new TypeError(`🚨 Multiple versions of Remotion detected: ${[
76
+ VERSION,
77
+ typeof alreadyImported === 'string'
78
+ ? alreadyImported
79
+ : 'an older version',
80
+ ]
81
+ .filter(truthy)
82
+ .join(' and ')}. This will cause things to break in an unexpected way.\nCheck that all your Remotion packages are on the same version. If your dependencies depend on Remotion, make them peer dependencies. You can also run \`npx remotion versions\` from your terminal to see which versions are mismatching.`);
83
+ }
84
+ globalThis.remotion_imported = VERSION;
85
+ if (typeof window !== 'undefined') {
86
+ window.remotion_imported = VERSION;
87
+ }
88
+ };
89
+
90
+ const Null = () => {
91
+ const { setClipRegion } = useContext(NativeLayersContext);
92
+ useEffect(() => {
93
+ setClipRegion((c) => {
94
+ if (c === null) {
95
+ return 'hide';
96
+ }
97
+ // Rendering multiple <Null> is fine, because they are all hidden
98
+ if (c === 'hide') {
99
+ return 'hide';
100
+ }
101
+ throw new Error('Cannot render <Null>, because another component clipping the region was already rendered (most likely <Clipper>)');
102
+ });
103
+ return () => {
104
+ setClipRegion(null);
105
+ };
106
+ }, [setClipRegion]);
107
+ return null;
108
+ };
109
+
110
+ const AbsoluteFillRefForwarding = (props, ref) => {
111
+ const { style, ...other } = props;
112
+ const actualStyle = useMemo(() => {
113
+ return {
114
+ position: 'absolute',
115
+ top: 0,
116
+ left: 0,
117
+ right: 0,
118
+ bottom: 0,
119
+ width: '100%',
120
+ height: '100%',
121
+ display: 'flex',
122
+ flexDirection: 'column',
123
+ ...style,
124
+ };
125
+ }, [style]);
126
+ return jsx("div", { ref: ref, style: actualStyle, ...other });
127
+ };
128
+ /**
129
+ * @description An absolutely positioned <div> element with 100% width, height, and a column flex style
130
+ * @see [Documentation](https://www.remotion.dev/docs/absolute-fill)
131
+ */
132
+ const AbsoluteFill = forwardRef(AbsoluteFillRefForwarding);
133
+
134
+ const getAbsoluteSrc = (relativeSrc) => {
135
+ return new URL(relativeSrc, window.location.origin).href;
136
+ };
137
+
138
+ const isErrorLike = (err) => {
139
+ if (err === null) {
140
+ return false;
141
+ }
142
+ if (typeof err !== 'object') {
143
+ return false;
144
+ }
145
+ if (!('stack' in err)) {
146
+ return false;
147
+ }
148
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
149
+ // @ts-ignore we just asserted
150
+ if (typeof err.stack !== 'string') {
151
+ return false;
152
+ }
153
+ if (!('message' in err)) {
154
+ return false;
155
+ }
156
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
157
+ // @ts-ignore we just asserted
158
+ if (typeof err.message !== 'string') {
159
+ return false;
160
+ }
161
+ return true;
162
+ };
163
+ /**
164
+ * @description When you invoke this function, Remotion will stop rendering all the frames without any retries
165
+ * @see [Documentation](https://www.remotion.dev/docs/cancel-render)
166
+ */
167
+ function cancelRender(err) {
168
+ let error;
169
+ if (isErrorLike(err)) {
170
+ error = err;
171
+ }
172
+ else if (typeof err === 'string') {
173
+ error = Error(err);
174
+ }
175
+ else {
176
+ error = Error('Rendering was cancelled');
177
+ }
178
+ window.remotion_cancelledError = error.stack;
179
+ throw error;
180
+ }
181
+
182
+ const getRemotionEnvironment = () => {
183
+ if (process.env.NODE_ENV === 'production') {
184
+ if (typeof window !== 'undefined' && window.remotion_isPlayer) {
185
+ return 'player-production';
186
+ }
187
+ return 'rendering';
188
+ }
189
+ // The Vitest framework sets NODE_ENV as test.
190
+ // Right now we don't need to treat it in a special
191
+ // way which is good - defaulting to `rendering`.
192
+ if (process.env.NODE_ENV === 'test') {
193
+ return 'rendering';
194
+ }
195
+ if (typeof window !== 'undefined' && window.remotion_isPlayer) {
196
+ return 'player-development';
197
+ }
198
+ return 'preview';
199
+ };
200
+ const useRemotionEnvironment = () => {
201
+ const isPlayer = useIsPlayer();
202
+ if (isPlayer) {
203
+ if (process.env.NODE_ENV === 'production') {
204
+ return 'player-production';
205
+ }
206
+ return 'player-development';
207
+ }
208
+ return getRemotionEnvironment();
209
+ };
210
+
211
+ const HIDDEN_NAMES = ['__WEBPACK_DEFAULT_EXPORT__'];
212
+ const getTimelineClipName = (children) => {
213
+ var _a;
214
+ const tree = (_a = Children.map(children, (ch) => {
215
+ if (!isValidElement(ch)) {
216
+ return null;
217
+ }
218
+ // Must be name, not ID
219
+ const name = typeof ch.type !== 'string' && ch.type.name;
220
+ if (name && !HIDDEN_NAMES.includes(name)) {
221
+ return name;
222
+ }
223
+ if (ch.props.children) {
224
+ const chName = getTimelineClipName(ch.props.children);
225
+ return chName;
226
+ }
227
+ return null;
228
+ })) === null || _a === void 0 ? void 0 : _a.filter(Boolean);
229
+ return (tree === null || tree === void 0 ? void 0 : tree.length) ? tree[0] : '';
230
+ };
231
+
232
+ const NonceContext = createContext({
233
+ getNonce: () => 0,
234
+ fastRefreshes: 0,
235
+ });
236
+ const useNonce = () => {
237
+ const context = useContext(NonceContext);
238
+ const [nonce, setNonce] = useState(() => context.getNonce());
239
+ const lastContext = useRef(context);
240
+ // Only if context changes, but not initially
241
+ useEffect(() => {
242
+ if (lastContext.current === context) {
243
+ return;
244
+ }
245
+ lastContext.current = context;
246
+ setNonce(context.getNonce);
247
+ }, [context]);
248
+ return nonce;
249
+ };
250
+
251
+ const SequenceContext = createContext(null);
252
+
253
+ const SequenceManager = React.createContext({
254
+ registerSequence: () => {
255
+ throw new Error('SequenceManagerContext not initialized');
256
+ },
257
+ unregisterSequence: () => {
258
+ throw new Error('SequenceManagerContext not initialized');
259
+ },
260
+ sequences: [],
261
+ });
262
+ const SequenceManagerProvider = ({ children }) => {
263
+ const [sequences, setSequences] = useState([]);
264
+ const registerSequence = useCallback((seq) => {
265
+ setSequences((seqs) => {
266
+ return [...seqs, seq];
267
+ });
268
+ }, []);
269
+ const unregisterSequence = useCallback((seq) => {
270
+ setSequences((seqs) => seqs.filter((s) => s.id !== seq));
271
+ }, []);
272
+ const context = useMemo(() => {
273
+ return {
274
+ registerSequence,
275
+ sequences,
276
+ unregisterSequence,
277
+ };
278
+ }, [registerSequence, sequences, unregisterSequence]);
279
+ return (jsx(SequenceManager.Provider, { value: context, children: children }));
280
+ };
281
+
282
+ const CompositionManager = createContext({
283
+ compositions: [],
284
+ registerComposition: () => undefined,
285
+ unregisterComposition: () => undefined,
286
+ registerFolder: () => undefined,
287
+ unregisterFolder: () => undefined,
288
+ currentComposition: null,
289
+ setCurrentComposition: () => undefined,
290
+ setCurrentCompositionMetadata: () => undefined,
291
+ folders: [],
292
+ currentCompositionMetadata: null,
293
+ });
294
+
295
+ let didWarnSSRImport = false;
296
+ const warnOnceSSRImport = () => {
297
+ if (didWarnSSRImport) {
298
+ return;
299
+ }
300
+ didWarnSSRImport = true;
301
+ console.warn('Called `getInputProps()` on the server. This function is not available server-side and has returned an empty object.');
302
+ console.warn("To hide this warning, don't call this function on the server:");
303
+ console.warn(" typeof window === 'undefined' ? {} : getInputProps()");
304
+ };
305
+ const getInputProps = () => {
306
+ if (typeof window === 'undefined') {
307
+ warnOnceSSRImport();
308
+ return {};
309
+ }
310
+ if (getRemotionEnvironment() === 'player-development' ||
311
+ getRemotionEnvironment() === 'player-production') {
312
+ throw new Error('You cannot call `getInputProps()` from a <Player>. Instead, the props are available as React props from component that you passed as `component` prop.');
313
+ }
314
+ const param = window.remotion_inputProps;
315
+ if (!param) {
316
+ return {};
317
+ }
318
+ const parsed = JSON.parse(param);
319
+ return parsed;
320
+ };
321
+
322
+ const EditorPropsContext = createContext({
323
+ props: {},
324
+ updateProps: () => {
325
+ throw new Error('Not implemented');
326
+ },
327
+ });
328
+ const EditorPropsProvider = ({ children }) => {
329
+ const [props, setProps] = React.useState({});
330
+ const updateProps = useCallback(({ defaultProps, id, newProps, }) => {
331
+ setProps((prev) => {
332
+ var _a;
333
+ return {
334
+ ...prev,
335
+ [id]: typeof newProps === 'function'
336
+ ? newProps((_a = prev[id]) !== null && _a !== void 0 ? _a : defaultProps)
337
+ : newProps,
338
+ };
339
+ });
340
+ }, []);
341
+ const ctx = useMemo(() => {
342
+ return { props, updateProps };
343
+ }, [props, updateProps]);
344
+ return (jsx(EditorPropsContext.Provider, { value: ctx, children: children }));
345
+ };
346
+
347
+ const validateDimension = (amount, nameOfProp, location) => {
348
+ if (typeof amount !== 'number') {
349
+ throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
350
+ }
351
+ if (isNaN(amount)) {
352
+ throw new TypeError(`The "${nameOfProp}" prop ${location} must not be NaN, but is NaN.`);
353
+ }
354
+ if (!Number.isFinite(amount)) {
355
+ throw new TypeError(`The "${nameOfProp}" prop ${location} must be finite, but is ${amount}.`);
356
+ }
357
+ if (amount % 1 !== 0) {
358
+ throw new TypeError(`The "${nameOfProp}" prop ${location} must be an integer, but is ${amount}.`);
359
+ }
360
+ if (amount <= 0) {
361
+ throw new TypeError(`The "${nameOfProp}" prop ${location} must be positive, but got ${amount}.`);
362
+ }
363
+ };
364
+
365
+ const validateDurationInFrames = ({ allowFloats, component, durationInFrames, }) => {
366
+ if (typeof durationInFrames !== 'number') {
367
+ throw new Error(`The "durationInFrames" prop ${component} must be a number, but you passed a value of type ${typeof durationInFrames}`);
368
+ }
369
+ if (durationInFrames <= 0) {
370
+ throw new TypeError(`The "durationInFrames" prop ${component} must be positive, but got ${durationInFrames}.`);
371
+ }
372
+ if (!allowFloats && durationInFrames % 1 !== 0) {
373
+ throw new TypeError(`The "durationInFrames" prop ${component} must be an integer, but got ${durationInFrames}.`);
374
+ }
375
+ if (!Number.isFinite(durationInFrames)) {
376
+ throw new TypeError(`The "durationInFrames" prop ${component} must be finite, but got ${durationInFrames}.`);
377
+ }
378
+ };
379
+
380
+ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, }) => {
381
+ var _a, _b, _c, _d, _e, _f;
382
+ const calculatedProm = composition.calculateMetadata
383
+ ? composition.calculateMetadata({
384
+ defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
385
+ props: {
386
+ ...((_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {}),
387
+ ...(editorPropsOrUndefined !== null && editorPropsOrUndefined !== void 0 ? editorPropsOrUndefined : {}),
388
+ ...(typeof window === 'undefined' ||
389
+ getRemotionEnvironment() === 'player-development' ||
390
+ getRemotionEnvironment() === 'player-production'
391
+ ? {}
392
+ : (_c = getInputProps()) !== null && _c !== void 0 ? _c : {}),
393
+ },
394
+ abortSignal: signal,
395
+ })
396
+ : null;
397
+ if (calculatedProm !== null &&
398
+ typeof calculatedProm === 'object' &&
399
+ 'then' in calculatedProm) {
400
+ return calculatedProm.then((c) => {
401
+ var _a, _b;
402
+ const { height, width, durationInFrames, fps } = validateCalculated({
403
+ calculated: c,
404
+ composition,
405
+ });
406
+ return {
407
+ width,
408
+ height,
409
+ fps,
410
+ durationInFrames,
411
+ id: composition.id,
412
+ defaultProps: (_b = (_a = c.props) !== null && _a !== void 0 ? _a : composition.defaultProps) !== null && _b !== void 0 ? _b : {},
413
+ };
414
+ });
415
+ }
416
+ const data = validateCalculated({
417
+ calculated: calculatedProm,
418
+ composition,
419
+ });
420
+ if (calculatedProm === null) {
421
+ return {
422
+ ...data,
423
+ id: composition.id,
424
+ defaultProps: (_d = composition === null || composition === void 0 ? void 0 : composition.defaultProps) !== null && _d !== void 0 ? _d : {},
425
+ };
426
+ }
427
+ return {
428
+ ...data,
429
+ id: composition.id,
430
+ defaultProps: (_f = (_e = calculatedProm === null || calculatedProm === void 0 ? void 0 : calculatedProm.props) !== null && _e !== void 0 ? _e : composition.defaultProps) !== null && _f !== void 0 ? _f : {},
431
+ };
432
+ };
433
+ const validateCalculated = ({ composition, calculated, }) => {
434
+ var _a, _b, _c, _d, _e, _f, _g, _h;
435
+ const potentialErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
436
+ const width = (_b = (_a = calculated === null || calculated === void 0 ? void 0 : calculated.width) !== null && _a !== void 0 ? _a : composition.width) !== null && _b !== void 0 ? _b : null;
437
+ if (!width) {
438
+ throw new TypeError('Composition width was neither specified via the `width` prop nor the `calculateMetadata()` function.');
439
+ }
440
+ validateDimension(width, 'width', potentialErrorLocation);
441
+ const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : null;
442
+ if (!height) {
443
+ throw new TypeError('Composition height was neither specified via the `height` prop nor the `calculateMetadata()` function.');
444
+ }
445
+ validateDimension(width, 'height', potentialErrorLocation);
446
+ const fps = (_f = (_e = calculated === null || calculated === void 0 ? void 0 : calculated.fps) !== null && _e !== void 0 ? _e : composition.fps) !== null && _f !== void 0 ? _f : null;
447
+ if (!fps) {
448
+ throw new TypeError('Composition fps was neither specified via the `fps` prop nor the `calculateMetadata()` function.');
449
+ }
450
+ const durationInFrames = (_h = (_g = calculated === null || calculated === void 0 ? void 0 : calculated.durationInFrames) !== null && _g !== void 0 ? _g : composition.durationInFrames) !== null && _h !== void 0 ? _h : null;
451
+ if (!durationInFrames) {
452
+ throw new TypeError('Composition durationInFrames was neither specified via the `durationInFrames` prop nor the `calculateMetadata()` function.');
453
+ }
454
+ validateDurationInFrames({
455
+ durationInFrames,
456
+ component: potentialErrorLocation,
457
+ allowFloats: false,
458
+ });
459
+ return { width, height, fps, durationInFrames };
460
+ };
461
+
462
+ const ResolveCompositionContext = createContext(null);
463
+ const resolveCompositionsRef = createRef();
464
+ const ResolveCompositionConfig = ({ children }) => {
465
+ const [currentRenderModalComposition, setCurrentRenderModalComposition] = useState(null);
466
+ const { compositions, currentComposition, currentCompositionMetadata } = useContext(CompositionManager);
467
+ const selectedComposition = compositions.find((c) => c.id === currentComposition);
468
+ const renderModalComposition = compositions.find((c) => c.id === currentRenderModalComposition);
469
+ const { props: allEditorProps } = useContext(EditorPropsContext);
470
+ const [resolvedConfigs, setResolvedConfigs] = useState({});
471
+ const selectedEditorProps = useMemo(() => {
472
+ var _a;
473
+ return selectedComposition
474
+ ? (_a = allEditorProps[selectedComposition.id]) !== null && _a !== void 0 ? _a : {}
475
+ : {};
476
+ }, [allEditorProps, selectedComposition]);
477
+ const renderModalProps = useMemo(() => {
478
+ var _a;
479
+ return renderModalComposition
480
+ ? (_a = allEditorProps[renderModalComposition.id]) !== null && _a !== void 0 ? _a : {}
481
+ : {};
482
+ }, [allEditorProps, renderModalComposition]);
483
+ const doResolution = useCallback((composition, editorProps) => {
484
+ const controller = new AbortController();
485
+ if (currentCompositionMetadata) {
486
+ return controller;
487
+ }
488
+ const { signal } = controller;
489
+ const promOrNot = resolveVideoConfig({ composition, editorProps, signal });
490
+ if (typeof promOrNot === 'object' && 'then' in promOrNot) {
491
+ setResolvedConfigs((r) => ({
492
+ ...r,
493
+ [composition.id]: {
494
+ type: 'loading',
495
+ },
496
+ }));
497
+ promOrNot
498
+ .then((c) => {
499
+ if (controller.signal.aborted) {
500
+ return;
501
+ }
502
+ setResolvedConfigs((r) => ({
503
+ ...r,
504
+ [composition.id]: {
505
+ type: 'success',
506
+ result: c,
507
+ },
508
+ }));
509
+ })
510
+ .catch((err) => {
511
+ if (controller.signal.aborted) {
512
+ return;
513
+ }
514
+ setResolvedConfigs((r) => ({
515
+ ...r,
516
+ [composition.id]: {
517
+ type: 'error',
518
+ error: err,
519
+ },
520
+ }));
521
+ });
522
+ }
523
+ else {
524
+ setResolvedConfigs((r) => ({
525
+ ...r,
526
+ [composition.id]: {
527
+ type: 'success',
528
+ result: promOrNot,
529
+ },
530
+ }));
531
+ }
532
+ return controller;
533
+ }, [currentCompositionMetadata]);
534
+ useImperativeHandle(resolveCompositionsRef, () => {
535
+ return {
536
+ setCurrentRenderModalComposition: (id) => {
537
+ setCurrentRenderModalComposition(id);
538
+ },
539
+ reloadCurrentlySelectedComposition: () => {
540
+ var _a;
541
+ if (!currentComposition) {
542
+ return;
543
+ }
544
+ const composition = compositions.find((c) => c.id === currentComposition);
545
+ if (!composition) {
546
+ throw new Error(`Could not find composition with id ${currentComposition}`);
547
+ }
548
+ const editorProps = (_a = allEditorProps[currentComposition]) !== null && _a !== void 0 ? _a : {};
549
+ doResolution(composition, editorProps);
550
+ },
551
+ };
552
+ }, [allEditorProps, compositions, currentComposition, doResolution]);
553
+ const isTheSame = (selectedComposition === null || selectedComposition === void 0 ? void 0 : selectedComposition.id) === (renderModalComposition === null || renderModalComposition === void 0 ? void 0 : renderModalComposition.id);
554
+ useEffect(() => {
555
+ if (selectedComposition && needsResolution(selectedComposition)) {
556
+ const controller = doResolution(selectedComposition, selectedEditorProps);
557
+ return () => {
558
+ controller.abort();
559
+ };
560
+ }
561
+ }, [doResolution, selectedComposition, selectedEditorProps]);
562
+ useEffect(() => {
563
+ if (renderModalComposition && !isTheSame) {
564
+ const controller = doResolution(renderModalComposition, renderModalProps);
565
+ return () => {
566
+ controller.abort();
567
+ };
568
+ }
569
+ }, [doResolution, isTheSame, renderModalComposition, renderModalProps]);
570
+ const resolvedConfigsIncludingStaticOnes = useMemo(() => {
571
+ const staticComps = compositions.filter((c) => {
572
+ return c.calculateMetadata === null;
573
+ });
574
+ return {
575
+ ...resolvedConfigs,
576
+ ...staticComps.reduce((acc, curr) => {
577
+ var _a;
578
+ return {
579
+ ...acc,
580
+ [curr.id]: {
581
+ type: 'success',
582
+ result: { ...curr, defaultProps: (_a = curr.defaultProps) !== null && _a !== void 0 ? _a : {} },
583
+ },
584
+ };
585
+ }, {}),
586
+ };
587
+ }, [compositions, resolvedConfigs]);
588
+ return (jsx(ResolveCompositionContext.Provider, { value: resolvedConfigsIncludingStaticOnes, children: children }));
589
+ };
590
+ const needsResolution = (composition) => {
591
+ return Boolean(composition.calculateMetadata);
592
+ };
593
+ const useResolvedVideoConfig = (preferredCompositionId) => {
594
+ const context = useContext(ResolveCompositionContext);
595
+ const { props: allEditorProps } = useContext(EditorPropsContext);
596
+ const { compositions, currentComposition, currentCompositionMetadata } = useContext(CompositionManager);
597
+ const compositionId = preferredCompositionId !== null && preferredCompositionId !== void 0 ? preferredCompositionId : currentComposition;
598
+ const composition = compositions.find((c) => c.id === compositionId);
599
+ const selectedEditorProps = useMemo(() => {
600
+ var _a;
601
+ return composition ? (_a = allEditorProps[composition.id]) !== null && _a !== void 0 ? _a : {} : {};
602
+ }, [allEditorProps, composition]);
603
+ return useMemo(() => {
604
+ var _a, _b, _c;
605
+ if (!composition) {
606
+ return null;
607
+ }
608
+ if (currentCompositionMetadata) {
609
+ return {
610
+ type: 'success',
611
+ result: {
612
+ ...currentCompositionMetadata,
613
+ id: composition.id,
614
+ defaultProps: (_a = currentCompositionMetadata.defaultProps) !== null && _a !== void 0 ? _a : {},
615
+ },
616
+ };
617
+ }
618
+ if (!needsResolution(composition)) {
619
+ return {
620
+ type: 'success',
621
+ result: {
622
+ ...composition,
623
+ defaultProps: {
624
+ ...((_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {}),
625
+ ...(selectedEditorProps !== null && selectedEditorProps !== void 0 ? selectedEditorProps : {}),
626
+ ...(typeof window === 'undefined' ||
627
+ getRemotionEnvironment() === 'player-development' ||
628
+ getRemotionEnvironment() === 'player-production'
629
+ ? {}
630
+ : (_c = getInputProps()) !== null && _c !== void 0 ? _c : {}),
631
+ },
632
+ },
633
+ };
634
+ }
635
+ if (!context[composition.id]) {
636
+ return null;
637
+ }
638
+ return context[composition.id];
639
+ }, [composition, context, currentCompositionMetadata, selectedEditorProps]);
640
+ };
641
+
642
+ const useVideo = () => {
643
+ const context = useContext(CompositionManager);
644
+ const selected = context.compositions.find((c) => {
645
+ return c.id === context.currentComposition;
646
+ });
647
+ const resolved = useResolvedVideoConfig(context.currentComposition);
648
+ return useMemo(() => {
649
+ var _a;
650
+ if (!resolved) {
651
+ return null;
652
+ }
653
+ if (resolved.type === 'error') {
654
+ return null;
655
+ }
656
+ if (resolved.type === 'loading') {
657
+ return null;
658
+ }
659
+ if (!selected) {
660
+ return null;
661
+ }
662
+ return {
663
+ ...resolved.result,
664
+ defaultProps: selected.defaultProps,
665
+ id: selected.id,
666
+ // We override the selected metadata with the metadata that was passed to renderMedia(),
667
+ // and don't allow it to be changed during render anymore
668
+ ...((_a = context.currentCompositionMetadata) !== null && _a !== void 0 ? _a : {}),
669
+ component: selected.component,
670
+ };
671
+ }, [context.currentCompositionMetadata, resolved, selected]);
672
+ };
673
+
674
+ const TimelineContext = createContext({
675
+ frame: 0,
676
+ playing: false,
677
+ playbackRate: 1,
678
+ rootId: '',
679
+ imperativePlaying: {
680
+ current: false,
681
+ },
682
+ setPlaybackRate: () => {
683
+ throw new Error('default');
684
+ },
685
+ audioAndVideoTags: { current: [] },
686
+ });
687
+ const SetTimelineContext = createContext({
688
+ setFrame: () => {
689
+ throw new Error('default');
690
+ },
691
+ setPlaying: () => {
692
+ throw new Error('default');
693
+ },
694
+ });
695
+ const useTimelinePosition = () => {
696
+ const videoConfig = useVideo();
697
+ const state = useContext(TimelineContext);
698
+ // A dynamically calculated duration using calculateMetadata()
699
+ // may lead to the frame being bigger than the duration.
700
+ // If we have the config, we clamp the frame to the duration.
701
+ if (!videoConfig) {
702
+ return state.frame;
703
+ }
704
+ return Math.min(videoConfig.durationInFrames - 1, state.frame);
705
+ };
706
+ const useTimelineSetFrame = () => {
707
+ const { setFrame } = useContext(SetTimelineContext);
708
+ return setFrame;
709
+ };
710
+ const usePlayingState = () => {
711
+ const { playing, imperativePlaying } = useContext(TimelineContext);
712
+ const { setPlaying } = useContext(SetTimelineContext);
713
+ return useMemo(() => [playing, setPlaying, imperativePlaying], [imperativePlaying, playing, setPlaying]);
714
+ };
715
+
716
+ var TimelinePosition = /*#__PURE__*/Object.freeze({
717
+ __proto__: null,
718
+ TimelineContext: TimelineContext,
719
+ SetTimelineContext: SetTimelineContext,
720
+ useTimelinePosition: useTimelinePosition,
721
+ useTimelineSetFrame: useTimelineSetFrame,
722
+ usePlayingState: usePlayingState
723
+ });
724
+
725
+ const CanUseRemotionHooks = createContext(false);
726
+ const CanUseRemotionHooksProvider = ({ children }) => {
727
+ return (jsx(CanUseRemotionHooks.Provider, { value: true, children: children }));
728
+ };
729
+
730
+ const useUnsafeVideoConfig = () => {
731
+ var _a;
732
+ const context = useContext(SequenceContext);
733
+ const ctxDuration = (_a = context === null || context === void 0 ? void 0 : context.durationInFrames) !== null && _a !== void 0 ? _a : null;
734
+ const video = useVideo();
735
+ return useMemo(() => {
736
+ if (!video) {
737
+ return null;
738
+ }
739
+ const { id, durationInFrames, fps, height, width, defaultProps } = video;
740
+ return {
741
+ id,
742
+ width,
743
+ height,
744
+ fps,
745
+ durationInFrames: ctxDuration !== null && ctxDuration !== void 0 ? ctxDuration : durationInFrames,
746
+ defaultProps,
747
+ };
748
+ }, [ctxDuration, video]);
749
+ };
750
+
751
+ /**
752
+ * /**
753
+ * @description Get some info about the context of the video that you are making.
754
+ * @see [Documentation](https://www.remotion.dev/docs/use-video-config)
755
+ * @returns Returns an object containing `fps`, `width`, `height` and `durationInFrames`, all of type `number`.
756
+ */
757
+ const useVideoConfig = () => {
758
+ const videoConfig = useUnsafeVideoConfig();
759
+ const context = useContext(CanUseRemotionHooks);
760
+ const isPlayer = useIsPlayer();
761
+ if (!videoConfig) {
762
+ if ((typeof window !== 'undefined' && window.remotion_isPlayer) ||
763
+ isPlayer) {
764
+ throw new Error([
765
+ 'No video config found. Likely reasons:',
766
+ '- You are probably calling useVideoConfig() from outside the component passed to <Player />. See https://www.remotion.dev/docs/player/examples for how to set up the Player correctly.',
767
+ '- You have multiple versions of Remotion installed which causes the React context to get lost.',
768
+ ].join('-'));
769
+ }
770
+ throw new Error('No video config found. You are probably calling useVideoConfig() from a component which has not been registered as a <Composition />. See https://www.remotion.dev/docs/the-fundamentals#defining-compositions for more information.');
771
+ }
772
+ if (!context) {
773
+ throw new Error('Called useVideoConfig() outside a Remotion composition.');
774
+ }
775
+ return videoConfig;
776
+ };
777
+
778
+ const SequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity, children, name, showInTimeline = true, loopDisplay, ...other }, ref) => {
779
+ const { layout = 'absolute-fill' } = other;
780
+ const [id] = useState(() => String(Math.random()));
781
+ const parentSequence = useContext(SequenceContext);
782
+ const { rootId } = useContext(TimelineContext);
783
+ const cumulatedFrom = parentSequence
784
+ ? parentSequence.cumulatedFrom + parentSequence.relativeFrom
785
+ : 0;
786
+ const nonce = useNonce();
787
+ const environment = useRemotionEnvironment();
788
+ if (layout !== 'absolute-fill' && layout !== 'none') {
789
+ throw new TypeError(`The layout prop of <Sequence /> expects either "absolute-fill" or "none", but you passed: ${layout}`);
790
+ }
791
+ // @ts-expect-error
792
+ if (layout === 'none' && typeof other.style !== 'undefined') {
793
+ throw new TypeError('If layout="none", you may not pass a style.');
794
+ }
795
+ if (typeof durationInFrames !== 'number') {
796
+ throw new TypeError(`You passed to durationInFrames an argument of type ${typeof durationInFrames}, but it must be a number.`);
797
+ }
798
+ if (durationInFrames <= 0) {
799
+ throw new TypeError(`durationInFrames must be positive, but got ${durationInFrames}`);
800
+ }
801
+ if (typeof from !== 'number') {
802
+ throw new TypeError(`You passed to the "from" props of your <Sequence> an argument of type ${typeof from}, but it must be a number.`);
803
+ }
804
+ if (!Number.isFinite(from)) {
805
+ throw new TypeError(`The "from" prop of a sequence must be finite, but got ${from}.`);
806
+ }
807
+ const absoluteFrame = useTimelinePosition();
808
+ const videoConfig = useVideoConfig();
809
+ const parentSequenceDuration = parentSequence
810
+ ? Math.min(parentSequence.durationInFrames - from, durationInFrames)
811
+ : durationInFrames;
812
+ const actualDurationInFrames = Math.max(0, Math.min(videoConfig.durationInFrames - from, parentSequenceDuration));
813
+ const { registerSequence, unregisterSequence } = useContext(SequenceManager);
814
+ const contextValue = useMemo(() => {
815
+ var _a;
816
+ return {
817
+ cumulatedFrom,
818
+ relativeFrom: from,
819
+ durationInFrames: actualDurationInFrames,
820
+ parentFrom: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom) !== null && _a !== void 0 ? _a : 0,
821
+ id,
822
+ };
823
+ }, [
824
+ cumulatedFrom,
825
+ from,
826
+ actualDurationInFrames,
827
+ parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom,
828
+ id,
829
+ ]);
830
+ const timelineClipName = useMemo(() => {
831
+ return name !== null && name !== void 0 ? name : getTimelineClipName(children);
832
+ }, [children, name]);
833
+ useEffect(() => {
834
+ var _a;
835
+ if (environment !== 'preview') {
836
+ return;
837
+ }
838
+ registerSequence({
839
+ from,
840
+ duration: actualDurationInFrames,
841
+ id,
842
+ displayName: timelineClipName,
843
+ parent: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id) !== null && _a !== void 0 ? _a : null,
844
+ type: 'sequence',
845
+ rootId,
846
+ showInTimeline,
847
+ nonce,
848
+ loopDisplay,
849
+ });
850
+ return () => {
851
+ unregisterSequence(id);
852
+ };
853
+ }, [
854
+ durationInFrames,
855
+ id,
856
+ name,
857
+ registerSequence,
858
+ timelineClipName,
859
+ unregisterSequence,
860
+ parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id,
861
+ actualDurationInFrames,
862
+ rootId,
863
+ from,
864
+ showInTimeline,
865
+ nonce,
866
+ loopDisplay,
867
+ environment,
868
+ ]);
869
+ const endThreshold = cumulatedFrom + from + durationInFrames - 1;
870
+ const content = absoluteFrame < cumulatedFrom + from
871
+ ? null
872
+ : absoluteFrame > endThreshold
873
+ ? null
874
+ : children;
875
+ const styleIfThere = other.layout === 'none' ? undefined : other.style;
876
+ const defaultStyle = useMemo(() => {
877
+ return {
878
+ flexDirection: undefined,
879
+ ...(styleIfThere !== null && styleIfThere !== void 0 ? styleIfThere : {}),
880
+ };
881
+ }, [styleIfThere]);
882
+ if (ref !== null && layout === 'none') {
883
+ throw new TypeError('It is not supported to pass both a `ref` and `layout="none"` to <Sequence />.');
884
+ }
885
+ return (jsx(SequenceContext.Provider, { value: contextValue, children: content === null ? null : other.layout === 'none' ? (content) : (jsx(AbsoluteFill, { ref: ref, style: defaultStyle, className: other.className, children: content })) }));
886
+ };
887
+ /**
888
+ * @description A component that time-shifts its children and wraps them in an absolutely positioned <div>.
889
+ * @see [Documentation](https://www.remotion.dev/docs/sequence]
890
+ */
891
+ const Sequence = forwardRef(SequenceRefForwardingFunction);
892
+
893
+ /**
894
+ * @description Get the current frame of the video. Frames are 0-indexed, meaning the first frame is 0, the last frame is the duration of the composition in frames minus one.
895
+ * @see [Documentation](https://remotion.dev/docs/use-current-frame)
896
+ */
897
+ const useCurrentFrame = () => {
898
+ const canUseRemotionHooks = useContext(CanUseRemotionHooks);
899
+ if (!canUseRemotionHooks) {
900
+ if (typeof window !== 'undefined' && window.remotion_isPlayer) {
901
+ throw new Error(`useCurrentFrame can only be called inside a component that was passed to <Player>. See: https://www.remotion.dev/docs/player/examples`);
902
+ }
903
+ throw new Error(`useCurrentFrame() can only be called inside a component that was registered as a composition. See https://www.remotion.dev/docs/the-fundamentals#defining-compositions`);
904
+ }
905
+ const frame = useTimelinePosition();
906
+ const context = useContext(SequenceContext);
907
+ const contextOffset = context
908
+ ? context.cumulatedFrom + context.relativeFrom
909
+ : 0;
910
+ return frame - contextOffset;
911
+ };
912
+
913
+ /**
914
+ * @description This component allows you to quickly lay out an animation so it repeats itself.
915
+ * @see [Documentation](https://www.remotion.dev/docs/loop)
916
+ */
917
+ const Loop = ({ durationInFrames, times = Infinity, children, name, ...props }) => {
918
+ const currentFrame = useCurrentFrame();
919
+ const { durationInFrames: compDuration } = useVideoConfig();
920
+ validateDurationInFrames({
921
+ durationInFrames,
922
+ component: 'of the <Loop /> component',
923
+ allowFloats: true,
924
+ });
925
+ if (typeof times !== 'number') {
926
+ throw new TypeError(`You passed to "times" an argument of type ${typeof times}, but it must be a number.`);
927
+ }
928
+ if (times !== Infinity && times % 1 !== 0) {
929
+ throw new TypeError(`The "times" prop of a loop must be an integer, but got ${times}.`);
930
+ }
931
+ if (times < 0) {
932
+ throw new TypeError(`The "times" prop of a loop must be at least 0, but got ${times}`);
933
+ }
934
+ const maxTimes = Math.ceil(compDuration / durationInFrames);
935
+ const actualTimes = Math.min(maxTimes, times);
936
+ const style = props.layout === 'none' ? undefined : props.style;
937
+ const maxFrame = durationInFrames * (actualTimes - 1);
938
+ const start = Math.floor(currentFrame / durationInFrames) * durationInFrames;
939
+ const from = Math.min(start, maxFrame);
940
+ const loopDisplay = useMemo(() => {
941
+ return {
942
+ numberOfTimes: actualTimes,
943
+ startOffset: -from,
944
+ durationInFrames,
945
+ };
946
+ }, [actualTimes, durationInFrames, from]);
947
+ return (jsx(Sequence, { durationInFrames: durationInFrames, from: from, name: name, loopDisplay: loopDisplay, layout: props.layout, style: style, children: children }));
948
+ };
949
+
950
+ const validateMediaProps = (props, component) => {
951
+ if (typeof props.volume !== 'number' &&
952
+ typeof props.volume !== 'function' &&
953
+ typeof props.volume !== 'undefined') {
954
+ throw new TypeError(`You have passed a volume of type ${typeof props.volume} to your <${component} /> component. Volume must be a number or a function with the signature '(frame: number) => number' undefined.`);
955
+ }
956
+ if (typeof props.volume === 'number' && props.volume < 0) {
957
+ throw new TypeError(`You have passed a volume below 0 to your <${component} /> component. Volume must be between 0 and 1`);
958
+ }
959
+ if (typeof props.playbackRate !== 'number' &&
960
+ typeof props.playbackRate !== 'undefined') {
961
+ throw new TypeError(`You have passed a playbackRate of type ${typeof props.playbackRate} to your <${component} /> component. Playback rate must a real number or undefined.`);
962
+ }
963
+ if (typeof props.playbackRate === 'number' &&
964
+ (isNaN(props.playbackRate) ||
965
+ !Number.isFinite(props.playbackRate) ||
966
+ props.playbackRate <= 0)) {
967
+ throw new TypeError(`You have passed a playbackRate of ${props.playbackRate} to your <${component} /> component. Playback rate must be a real number above 0.`);
968
+ }
969
+ };
970
+
971
+ const validateStartFromProps = (startFrom, endAt) => {
972
+ if (typeof startFrom !== 'undefined') {
973
+ if (typeof startFrom !== 'number') {
974
+ throw new TypeError(`type of startFrom prop must be a number, instead got type ${typeof startFrom}.`);
975
+ }
976
+ if (isNaN(startFrom) || startFrom === Infinity) {
977
+ throw new TypeError('startFrom prop can not be NaN or Infinity.');
978
+ }
979
+ if (startFrom < 0) {
980
+ throw new TypeError(`startFrom must be greater than equal to 0 instead got ${startFrom}.`);
981
+ }
982
+ }
983
+ if (typeof endAt !== 'undefined') {
984
+ if (typeof endAt !== 'number') {
985
+ throw new TypeError(`type of endAt prop must be a number, instead got type ${typeof endAt}.`);
986
+ }
987
+ if (isNaN(endAt)) {
988
+ throw new TypeError('endAt prop can not be NaN.');
989
+ }
990
+ if (endAt <= 0) {
991
+ throw new TypeError(`endAt must be a positive number, instead got ${endAt}.`);
992
+ }
993
+ }
994
+ if (endAt < startFrom) {
995
+ throw new TypeError('endAt prop must be greater than startFrom prop.');
996
+ }
997
+ };
998
+
999
+ const durationReducer = (state, action) => {
1000
+ switch (action.type) {
1001
+ case 'got-duration':
1002
+ return {
1003
+ ...state,
1004
+ [getAbsoluteSrc(action.src)]: action.durationInSeconds,
1005
+ };
1006
+ default:
1007
+ return state;
1008
+ }
1009
+ };
1010
+ const DurationsContext = createContext({
1011
+ durations: {},
1012
+ setDurations: () => {
1013
+ throw new Error('context missing');
1014
+ },
1015
+ });
1016
+ const DurationsContextProvider = ({ children }) => {
1017
+ const [durations, setDurations] = useReducer(durationReducer, {});
1018
+ const value = useMemo(() => {
1019
+ return {
1020
+ durations,
1021
+ setDurations,
1022
+ };
1023
+ }, [durations]);
1024
+ return (jsx(DurationsContext.Provider, { value: value, children: children }));
1025
+ };
1026
+
1027
+ const PreloadContext = createContext({});
1028
+ let preloads = {};
1029
+ let updaters = [];
1030
+ const setPreloads = (updater) => {
1031
+ preloads = updater(preloads);
1032
+ updaters.forEach((u) => u());
1033
+ };
1034
+ const PrefetchProvider = ({ children }) => {
1035
+ const [_preloads, _setPreloads] = useState(() => preloads);
1036
+ useEffect(() => {
1037
+ const updaterFunction = () => {
1038
+ _setPreloads(preloads);
1039
+ };
1040
+ updaters.push(updaterFunction);
1041
+ return () => {
1042
+ updaters = updaters.filter((u) => u !== updaterFunction);
1043
+ };
1044
+ }, []);
1045
+ return (jsx(PreloadContext.Provider, { value: _preloads, children: children }));
1046
+ };
1047
+
1048
+ const usePreload = (src) => {
1049
+ var _a;
1050
+ const preloads = useContext(PreloadContext);
1051
+ return (_a = preloads[src]) !== null && _a !== void 0 ? _a : src;
1052
+ };
1053
+ const blobToBase64 = function (blob) {
1054
+ const reader = new FileReader();
1055
+ return new Promise((resolve, reject) => {
1056
+ reader.onload = function () {
1057
+ const dataUrl = reader.result;
1058
+ resolve(dataUrl);
1059
+ };
1060
+ reader.onerror = (err) => {
1061
+ return reject(err);
1062
+ };
1063
+ reader.readAsDataURL(blob);
1064
+ });
1065
+ };
1066
+ /**
1067
+ * @description When you call the preFetch() function, an asset will be fetched and kept in memory so it is ready when you want to play it in a <Player>.
1068
+ * @see [Documentation](https://www.remotion.dev/docs/prefetch)
1069
+ */
1070
+ const prefetch = (src, options) => {
1071
+ var _a;
1072
+ const method = (_a = options === null || options === void 0 ? void 0 : options.method) !== null && _a !== void 0 ? _a : 'blob-url';
1073
+ if (getRemotionEnvironment() === 'rendering') {
1074
+ return {
1075
+ free: () => undefined,
1076
+ waitUntilDone: () => Promise.resolve(src),
1077
+ };
1078
+ }
1079
+ let canceled = false;
1080
+ let objectUrl = null;
1081
+ let resolve = () => undefined;
1082
+ let reject = () => undefined;
1083
+ const waitUntilDone = new Promise((res, rej) => {
1084
+ resolve = res;
1085
+ reject = rej;
1086
+ });
1087
+ const controller = new AbortController();
1088
+ let canBeAborted = true;
1089
+ fetch(src, {
1090
+ signal: controller.signal,
1091
+ })
1092
+ .then((res) => {
1093
+ canBeAborted = false;
1094
+ if (canceled) {
1095
+ return null;
1096
+ }
1097
+ if (!res.ok) {
1098
+ throw new Error(`HTTP error, status = ${res.status}`);
1099
+ }
1100
+ return res.blob();
1101
+ })
1102
+ .then((buf) => {
1103
+ if (!buf) {
1104
+ return;
1105
+ }
1106
+ if (method === 'base64') {
1107
+ return blobToBase64(buf);
1108
+ }
1109
+ return URL.createObjectURL(buf);
1110
+ })
1111
+ .then((url) => {
1112
+ if (canceled) {
1113
+ return;
1114
+ }
1115
+ objectUrl = url;
1116
+ setPreloads((p) => ({
1117
+ ...p,
1118
+ [src]: objectUrl,
1119
+ }));
1120
+ resolve(objectUrl);
1121
+ })
1122
+ .catch((err) => {
1123
+ reject(err);
1124
+ });
1125
+ return {
1126
+ free: () => {
1127
+ if (objectUrl) {
1128
+ if (method === 'blob-url') {
1129
+ URL.revokeObjectURL(objectUrl);
1130
+ }
1131
+ setPreloads((p) => {
1132
+ const copy = { ...p };
1133
+ delete copy[src];
1134
+ return copy;
1135
+ });
1136
+ }
1137
+ else {
1138
+ canceled = true;
1139
+ if (canBeAborted) {
1140
+ try {
1141
+ controller.abort();
1142
+ }
1143
+ catch (e) { }
1144
+ }
1145
+ }
1146
+ },
1147
+ waitUntilDone: () => {
1148
+ return waitUntilDone;
1149
+ },
1150
+ };
1151
+ };
1152
+
1153
+ /* eslint-disable no-bitwise */
1154
+ function mulberry32(a) {
1155
+ let t = a + 0x6d2b79f5;
1156
+ t = Math.imul(t ^ (t >>> 15), t | 1);
1157
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
1158
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
1159
+ }
1160
+ function hashCode(str) {
1161
+ let i = 0;
1162
+ let chr = 0;
1163
+ let hash = 0;
1164
+ for (i = 0; i < str.length; i++) {
1165
+ chr = str.charCodeAt(i);
1166
+ hash = (hash << 5) - hash + chr;
1167
+ hash |= 0; // Convert to 32bit integer
1168
+ }
1169
+ return hash;
1170
+ }
1171
+ /**
1172
+ * @description A deterministic pseudo-random number generator. Pass in the same seed and get the same pseudorandom number.
1173
+ * @see [Documentation](https://remotion.dev/docs/random)
1174
+ */
1175
+ const random = (seed, dummy) => {
1176
+ if (dummy !== undefined) {
1177
+ throw new TypeError('random() takes only one argument');
1178
+ }
1179
+ if (seed === null) {
1180
+ return Math.random();
1181
+ }
1182
+ if (typeof seed === 'string') {
1183
+ return mulberry32(hashCode(seed));
1184
+ }
1185
+ if (typeof seed === 'number') {
1186
+ return mulberry32(seed * 10000000000);
1187
+ }
1188
+ throw new Error('random() argument must be a number or a string');
1189
+ };
1190
+
1191
+ const useMediaStartsAt = () => {
1192
+ var _a;
1193
+ const parentSequence = useContext(SequenceContext);
1194
+ const startsAt = Math.min(0, (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom) !== null && _a !== void 0 ? _a : 0);
1195
+ return startsAt;
1196
+ };
1197
+ /**
1198
+ * When passing a function as the prop for `volume`,
1199
+ * we calculate the way more intuitive value for currentFrame
1200
+ */
1201
+ const useFrameForVolumeProp = () => {
1202
+ const frame = useCurrentFrame();
1203
+ const startsAt = useMediaStartsAt();
1204
+ return frame + startsAt;
1205
+ };
1206
+
1207
+ const getAssetDisplayName = (filename) => {
1208
+ if (/data:|blob:/.test(filename.substring(0, 5))) {
1209
+ return 'Data URL';
1210
+ }
1211
+ const splitted = filename
1212
+ .split('/')
1213
+ .map((s) => s.split('\\'))
1214
+ .flat(1);
1215
+ return splitted[splitted.length - 1];
1216
+ };
1217
+
1218
+ const playAndHandleNotAllowedError = (mediaRef, mediaType) => {
1219
+ const { current } = mediaRef;
1220
+ if (!current) {
1221
+ return;
1222
+ }
1223
+ const prom = current.play();
1224
+ if (prom.catch) {
1225
+ prom.catch((err) => {
1226
+ if (!current) {
1227
+ return;
1228
+ }
1229
+ // Pause was called after play in Chrome
1230
+ if (err.message.includes('request was interrupted by a call to pause')) {
1231
+ return;
1232
+ }
1233
+ // Pause was called after play in Safari
1234
+ if (err.message.includes('The operation was aborted.')) {
1235
+ return;
1236
+ }
1237
+ // Pause was called after play in Firefox
1238
+ if (err.message.includes('The fetching process for the media resource was aborted by the user agent')) {
1239
+ return;
1240
+ }
1241
+ // Got replaced by a different audio source in Chromium
1242
+ if (err.message.includes('request was interrupted by a new load request')) {
1243
+ return;
1244
+ }
1245
+ // Audio tag got unmounted
1246
+ if (err.message.includes('because the media was removed from the document')) {
1247
+ return;
1248
+ }
1249
+ console.log(`Could not play ${mediaType} due to following error: `, err);
1250
+ if (!current.muted) {
1251
+ console.log(`The video will be muted and we'll retry playing it.`, err);
1252
+ current.muted = true;
1253
+ current.play();
1254
+ }
1255
+ });
1256
+ }
1257
+ };
1258
+
1259
+ const evaluateVolume = ({ frame, volume, mediaVolume = 1, allowAmplificationDuringRender, }) => {
1260
+ const maxVolume = allowAmplificationDuringRender ? Infinity : 1;
1261
+ if (typeof volume === 'number') {
1262
+ return Math.min(maxVolume, volume * mediaVolume);
1263
+ }
1264
+ if (typeof volume === 'undefined') {
1265
+ return Number(mediaVolume);
1266
+ }
1267
+ const evaluated = volume(frame) * mediaVolume;
1268
+ if (typeof evaluated !== 'number') {
1269
+ throw new TypeError(`You passed in a a function to the volume prop but it did not return a number but a value of type ${typeof evaluated} for frame ${frame}`);
1270
+ }
1271
+ if (Number.isNaN(evaluated)) {
1272
+ throw new TypeError(`You passed in a function to the volume prop but it returned NaN for frame ${frame}.`);
1273
+ }
1274
+ if (!Number.isFinite(evaluated)) {
1275
+ throw new TypeError(`You passed in a function to the volume prop but it returned a non-finite number for frame ${frame}.`);
1276
+ }
1277
+ return Math.max(0, Math.min(maxVolume, evaluated));
1278
+ };
1279
+
1280
+ const didWarn$1 = {};
1281
+ const warnOnce$1 = (message) => {
1282
+ if (didWarn$1[message]) {
1283
+ return;
1284
+ }
1285
+ console.warn(message);
1286
+ didWarn$1[message] = true;
1287
+ };
1288
+ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, }) => {
1289
+ const videoConfig = useVideoConfig();
1290
+ const { rootId, audioAndVideoTags } = useContext(TimelineContext);
1291
+ const parentSequence = useContext(SequenceContext);
1292
+ const actualFrom = parentSequence
1293
+ ? parentSequence.relativeFrom + parentSequence.cumulatedFrom
1294
+ : 0;
1295
+ const [playing] = usePlayingState();
1296
+ const startsAt = useMediaStartsAt();
1297
+ const { registerSequence, unregisterSequence } = useContext(SequenceManager);
1298
+ const [id] = useState(() => String(Math.random()));
1299
+ const [initialVolume] = useState(() => volume);
1300
+ const nonce = useNonce();
1301
+ const duration = parentSequence
1302
+ ? Math.min(parentSequence.durationInFrames, videoConfig.durationInFrames)
1303
+ : videoConfig.durationInFrames;
1304
+ const doesVolumeChange = typeof volume === 'function';
1305
+ const environment = useRemotionEnvironment();
1306
+ const volumes = useMemo(() => {
1307
+ if (typeof volume === 'number') {
1308
+ return volume;
1309
+ }
1310
+ return new Array(Math.floor(Math.max(0, duration + startsAt)))
1311
+ .fill(true)
1312
+ .map((_, i) => {
1313
+ return evaluateVolume({
1314
+ frame: i + startsAt,
1315
+ volume,
1316
+ mediaVolume,
1317
+ allowAmplificationDuringRender: false,
1318
+ });
1319
+ })
1320
+ .join(',');
1321
+ }, [duration, startsAt, volume, mediaVolume]);
1322
+ useEffect(() => {
1323
+ if (typeof volume === 'number' && volume !== initialVolume) {
1324
+ 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`);
1325
+ }
1326
+ }, [initialVolume, mediaType, src, volume]);
1327
+ useEffect(() => {
1328
+ var _a;
1329
+ if (!mediaRef.current) {
1330
+ return;
1331
+ }
1332
+ if (!src) {
1333
+ throw new Error('No src passed');
1334
+ }
1335
+ if (environment !== 'preview' && process.env.NODE_ENV !== 'test') {
1336
+ return;
1337
+ }
1338
+ registerSequence({
1339
+ type: mediaType,
1340
+ src,
1341
+ id,
1342
+ duration,
1343
+ from: 0,
1344
+ parent: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id) !== null && _a !== void 0 ? _a : null,
1345
+ displayName: getAssetDisplayName(src),
1346
+ rootId,
1347
+ volume: volumes,
1348
+ showInTimeline: true,
1349
+ nonce,
1350
+ startMediaFrom: 0 - startsAt,
1351
+ doesVolumeChange,
1352
+ loopDisplay: undefined,
1353
+ playbackRate,
1354
+ });
1355
+ return () => {
1356
+ unregisterSequence(id);
1357
+ };
1358
+ }, [
1359
+ actualFrom,
1360
+ duration,
1361
+ id,
1362
+ parentSequence,
1363
+ src,
1364
+ registerSequence,
1365
+ rootId,
1366
+ unregisterSequence,
1367
+ videoConfig,
1368
+ volumes,
1369
+ doesVolumeChange,
1370
+ nonce,
1371
+ mediaRef,
1372
+ mediaType,
1373
+ startsAt,
1374
+ playbackRate,
1375
+ environment,
1376
+ ]);
1377
+ useEffect(() => {
1378
+ const tag = {
1379
+ id,
1380
+ play: () => {
1381
+ if (!playing) {
1382
+ // Don't play if for example in a <Freeze> state.
1383
+ return;
1384
+ }
1385
+ return playAndHandleNotAllowedError(mediaRef, mediaType);
1386
+ },
1387
+ };
1388
+ audioAndVideoTags.current.push(tag);
1389
+ return () => {
1390
+ audioAndVideoTags.current = audioAndVideoTags.current.filter((a) => a.id !== id);
1391
+ };
1392
+ }, [audioAndVideoTags, id, mediaRef, mediaType, playing]);
1393
+ };
1394
+
1395
+ // Taken from https://github.com/facebook/react-native/blob/0b9ea60b4fee8cacc36e7160e31b91fc114dbc0d/Libraries/Animated/src/nodes/AnimatedInterpolation.js
1396
+ function interpolateFunction(input, inputRange, outputRange, options) {
1397
+ const { extrapolateLeft, extrapolateRight, easing } = options;
1398
+ let result = input;
1399
+ const [inputMin, inputMax] = inputRange;
1400
+ const [outputMin, outputMax] = outputRange;
1401
+ if (result < inputMin) {
1402
+ if (extrapolateLeft === 'identity') {
1403
+ return result;
1404
+ }
1405
+ if (extrapolateLeft === 'clamp') {
1406
+ result = inputMin;
1407
+ }
1408
+ }
1409
+ if (result > inputMax) {
1410
+ if (extrapolateRight === 'identity') {
1411
+ return result;
1412
+ }
1413
+ if (extrapolateRight === 'clamp') {
1414
+ result = inputMax;
1415
+ }
1416
+ }
1417
+ if (outputMin === outputMax) {
1418
+ return outputMin;
1419
+ }
1420
+ // Input Range
1421
+ result = (result - inputMin) / (inputMax - inputMin);
1422
+ // Easing
1423
+ result = easing(result);
1424
+ // Output Range
1425
+ result = result * (outputMax - outputMin) + outputMin;
1426
+ return result;
1427
+ }
1428
+ function findRange(input, inputRange) {
1429
+ let i;
1430
+ for (i = 1; i < inputRange.length - 1; ++i) {
1431
+ if (inputRange[i] >= input) {
1432
+ break;
1433
+ }
1434
+ }
1435
+ return i - 1;
1436
+ }
1437
+ function checkValidInputRange(arr) {
1438
+ for (let i = 1; i < arr.length; ++i) {
1439
+ if (!(arr[i] > arr[i - 1])) {
1440
+ throw new Error(`inputRange must be strictly monotonically non-decreasing but got [${arr.join(',')}]`);
1441
+ }
1442
+ }
1443
+ }
1444
+ function checkInfiniteRange(name, arr) {
1445
+ if (arr.length < 2) {
1446
+ throw new Error(name + ' must have at least 2 elements');
1447
+ }
1448
+ for (const index in arr) {
1449
+ if (typeof arr[index] !== 'number') {
1450
+ throw new Error(`${name} must contain only numbers`);
1451
+ }
1452
+ if (arr[index] === -Infinity || arr[index] === Infinity) {
1453
+ throw new Error(`${name} must contain only finite numbers, but got [${arr.join(',')}]`);
1454
+ }
1455
+ }
1456
+ }
1457
+ /**
1458
+ * Map a value from an input range to an output range.
1459
+ * @link https://www.remotion.dev/docs/interpolate
1460
+ * @param {!number} input value to interpolate
1461
+ * @param {!number[]} inputRange range of values that you expect the input to assume.
1462
+ * @param {!number[]} outputRange range of output values that you want the input to map to.
1463
+ * @param {?object} options
1464
+ * @param {?Function} options.easing easing function which allows you to customize the input, for example to apply a certain easing function. By default, the input is left unmodified, resulting in a pure linear interpolation {@link https://www.remotion.dev/docs/easing}
1465
+ * @param {string=} [options.extrapolateLeft="extend"] What should happen if the input value is outside left the input range, default: "extend" {@link https://www.remotion.dev/docs/interpolate#extrapolateleft}
1466
+ * @param {string=} [options.extrapolateRight="extend"] Same as extrapolateLeft, except for values outside right the input range {@link https://www.remotion.dev/docs/interpolate#extrapolateright}
1467
+ */
1468
+ function interpolate(input, inputRange, outputRange, options) {
1469
+ var _a;
1470
+ if (typeof input === 'undefined') {
1471
+ throw new Error('input can not be undefined');
1472
+ }
1473
+ if (typeof inputRange === 'undefined') {
1474
+ throw new Error('inputRange can not be undefined');
1475
+ }
1476
+ if (typeof outputRange === 'undefined') {
1477
+ throw new Error('outputRange can not be undefined');
1478
+ }
1479
+ if (inputRange.length !== outputRange.length) {
1480
+ throw new Error('inputRange (' +
1481
+ inputRange.length +
1482
+ ') and outputRange (' +
1483
+ outputRange.length +
1484
+ ') must have the same length');
1485
+ }
1486
+ checkInfiniteRange('inputRange', inputRange);
1487
+ checkInfiniteRange('outputRange', outputRange);
1488
+ checkValidInputRange(inputRange);
1489
+ const easing = (_a = options === null || options === void 0 ? void 0 : options.easing) !== null && _a !== void 0 ? _a : ((num) => num);
1490
+ let extrapolateLeft = 'extend';
1491
+ if ((options === null || options === void 0 ? void 0 : options.extrapolateLeft) !== undefined) {
1492
+ extrapolateLeft = options.extrapolateLeft;
1493
+ }
1494
+ let extrapolateRight = 'extend';
1495
+ if ((options === null || options === void 0 ? void 0 : options.extrapolateRight) !== undefined) {
1496
+ extrapolateRight = options.extrapolateRight;
1497
+ }
1498
+ if (typeof input !== 'number') {
1499
+ throw new TypeError('Cannot interpolate an input which is not a number');
1500
+ }
1501
+ const range = findRange(input, inputRange);
1502
+ return interpolateFunction(input, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
1503
+ easing,
1504
+ extrapolateLeft,
1505
+ extrapolateRight,
1506
+ });
1507
+ }
1508
+
1509
+ // Calculate the `.currentTime` of a video or audio element
1510
+ const getExpectedMediaFrameUncorrected = ({ frame, playbackRate, startFrom, }) => {
1511
+ return interpolate(frame, [-1, startFrom, startFrom + 1], [-1, startFrom, startFrom + playbackRate]);
1512
+ };
1513
+ const getMediaTime = ({ fps, frame, src, playbackRate, startFrom, mediaType, }) => {
1514
+ const expectedFrame = getExpectedMediaFrameUncorrected({
1515
+ frame,
1516
+ playbackRate,
1517
+ startFrom,
1518
+ });
1519
+ const isChrome = typeof window !== 'undefined' &&
1520
+ window.navigator.userAgent.match(/Chrome\/([0-9]+)/);
1521
+ if (isChrome &&
1522
+ Number(isChrome[1]) < 112 &&
1523
+ mediaType === 'video' &&
1524
+ src.endsWith('.mp4')) {
1525
+ // In Chrome, for MP4s, if 30fps, the first frame is still displayed at 0.033333
1526
+ // even though after that it increases by 0.033333333 each.
1527
+ // So frame = 0 in Remotion is like frame = 1 for the browser
1528
+ return (expectedFrame + 1) / fps;
1529
+ }
1530
+ // For WebM videos, we need to add a little bit of shift to get the right frame.
1531
+ const msPerFrame = 1000 / fps;
1532
+ const msShift = msPerFrame / 2;
1533
+ return (expectedFrame * msPerFrame + msShift) / 1000;
1534
+ };
1535
+
1536
+ const alreadyWarned = {};
1537
+ const warnAboutNonSeekableMedia = (ref, type) => {
1538
+ // Media is not loaded yet, but this does not yet mean something is wrong with the media
1539
+ if (ref === null) {
1540
+ return;
1541
+ }
1542
+ if (ref.seekable.length === 0) {
1543
+ return;
1544
+ }
1545
+ if (ref.seekable.length > 1) {
1546
+ return;
1547
+ }
1548
+ if (alreadyWarned[ref.src]) {
1549
+ return;
1550
+ }
1551
+ const range = { start: ref.seekable.start(0), end: ref.seekable.end(0) };
1552
+ if (range.start === 0 && range.end === 0) {
1553
+ const msg = `The media ${ref.src} cannot be seeked. This could be one of two reasons: 1) The media resource was replaced while the video is playing but it was not loaded yet. 2) The media does not support seeking. Please see https://remotion.dev/docs/non-seekable-media for assistance.`;
1554
+ if (type === 'console-error') {
1555
+ console.error(msg);
1556
+ }
1557
+ else if (type === 'console-warning') {
1558
+ console.warn(`The media ${ref.src} does not support seeking. The video will render fine, but may not play correctly in the Remotion Studio and in the <Player>. See https://remotion.dev/docs/non-seekable-media for an explanation.`);
1559
+ }
1560
+ else {
1561
+ throw new Error(msg);
1562
+ }
1563
+ alreadyWarned[ref.src] = true;
1564
+ }
1565
+ };
1566
+
1567
+ const DEFAULT_ACCEPTABLE_TIMESHIFT = 0.45;
1568
+ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, }) => {
1569
+ const { playbackRate: globalPlaybackRate } = useContext(TimelineContext);
1570
+ const frame = useCurrentFrame();
1571
+ const absoluteFrame = useTimelinePosition();
1572
+ const [playing] = usePlayingState();
1573
+ const { fps } = useVideoConfig();
1574
+ const mediaStartsAt = useMediaStartsAt();
1575
+ const playbackRate = localPlaybackRate * globalPlaybackRate;
1576
+ useEffect(() => {
1577
+ var _a;
1578
+ if (!playing) {
1579
+ (_a = mediaRef.current) === null || _a === void 0 ? void 0 : _a.pause();
1580
+ }
1581
+ }, [mediaRef, mediaType, playing]);
1582
+ useEffect(() => {
1583
+ const tagName = mediaType === 'audio' ? '<Audio>' : '<Video>';
1584
+ if (!mediaRef.current) {
1585
+ throw new Error(`No ${mediaType} ref found`);
1586
+ }
1587
+ if (!src) {
1588
+ throw new Error(`No 'src' attribute was passed to the ${tagName} element.`);
1589
+ }
1590
+ mediaRef.current.playbackRate = Math.max(0, playbackRate);
1591
+ const shouldBeTime = getMediaTime({
1592
+ fps,
1593
+ frame,
1594
+ src,
1595
+ playbackRate: localPlaybackRate,
1596
+ startFrom: -mediaStartsAt,
1597
+ mediaType,
1598
+ });
1599
+ const isTime = mediaRef.current.currentTime;
1600
+ const timeShift = Math.abs(shouldBeTime - isTime);
1601
+ if (timeShift > acceptableTimeshift && !mediaRef.current.ended) {
1602
+ // If scrubbing around, adjust timing
1603
+ // or if time shift is bigger than 0.2sec
1604
+ mediaRef.current.currentTime = shouldBeTime;
1605
+ if (!onlyWarnForMediaSeekingError) {
1606
+ warnAboutNonSeekableMedia(mediaRef.current, onlyWarnForMediaSeekingError ? 'console-warning' : 'console-error');
1607
+ }
1608
+ }
1609
+ // Only perform a seek if the time is not already the same.
1610
+ // Chrome rounds to 6 digits, so 0.033333333 -> 0.033333,
1611
+ // therefore a threshold is allowed.
1612
+ // Refer to the https://github.com/remotion-dev/video-buffering-example
1613
+ // which is fixed by only seeking conditionally.
1614
+ const makesSenseToSeek = Math.abs(mediaRef.current.currentTime - shouldBeTime) > 0.00001;
1615
+ if (!playing || absoluteFrame === 0) {
1616
+ if (makesSenseToSeek) {
1617
+ mediaRef.current.currentTime = shouldBeTime;
1618
+ }
1619
+ }
1620
+ if (mediaRef.current.paused && !mediaRef.current.ended && playing) {
1621
+ if (makesSenseToSeek) {
1622
+ mediaRef.current.currentTime = shouldBeTime;
1623
+ }
1624
+ playAndHandleNotAllowedError(mediaRef, mediaType);
1625
+ }
1626
+ }, [
1627
+ absoluteFrame,
1628
+ fps,
1629
+ playbackRate,
1630
+ frame,
1631
+ mediaRef,
1632
+ mediaType,
1633
+ playing,
1634
+ src,
1635
+ mediaStartsAt,
1636
+ localPlaybackRate,
1637
+ onlyWarnForMediaSeekingError,
1638
+ acceptableTimeshift,
1639
+ ]);
1640
+ };
1641
+
1642
+ // Returns the real volume of the audio or video while playing,
1643
+ // no matter what the supposed volume should be
1644
+ const useMediaTagVolume = (mediaRef) => {
1645
+ const [actualVolume, setActualVolume] = useState(1);
1646
+ useEffect(() => {
1647
+ const ref = mediaRef.current;
1648
+ if (!ref) {
1649
+ return;
1650
+ }
1651
+ const onChange = () => {
1652
+ setActualVolume(ref.volume);
1653
+ };
1654
+ ref.addEventListener('volumechange', onChange);
1655
+ return () => ref.removeEventListener('volumechange', onChange);
1656
+ }, [mediaRef]);
1657
+ useEffect(() => {
1658
+ const ref = mediaRef.current;
1659
+ if (!ref) {
1660
+ return;
1661
+ }
1662
+ if (ref.volume !== actualVolume) {
1663
+ setActualVolume(ref.volume);
1664
+ }
1665
+ }, [actualVolume, mediaRef]);
1666
+ return actualVolume;
1667
+ };
1668
+
1669
+ const FLOATING_POINT_ERROR_THRESHOLD = 0.00001;
1670
+ const isApproximatelyTheSame = (num1, num2) => {
1671
+ return Math.abs(num1 - num2) < FLOATING_POINT_ERROR_THRESHOLD;
1672
+ };
1673
+
1674
+ const useSyncVolumeWithMediaTag = ({ volumePropFrame, actualVolume, volume, mediaVolume, mediaRef, }) => {
1675
+ useEffect(() => {
1676
+ const userPreferredVolume = evaluateVolume({
1677
+ frame: volumePropFrame,
1678
+ volume,
1679
+ mediaVolume,
1680
+ allowAmplificationDuringRender: false,
1681
+ });
1682
+ if (!isApproximatelyTheSame(userPreferredVolume, actualVolume) &&
1683
+ mediaRef.current) {
1684
+ mediaRef.current.volume = userPreferredVolume;
1685
+ }
1686
+ }, [actualVolume, volumePropFrame, mediaRef, volume, mediaVolume]);
1687
+ };
1688
+
1689
+ const MediaVolumeContext = createContext({
1690
+ mediaMuted: false,
1691
+ mediaVolume: 1,
1692
+ });
1693
+ const SetMediaVolumeContext = createContext({
1694
+ setMediaMuted: () => {
1695
+ throw new Error('default');
1696
+ },
1697
+ setMediaVolume: () => {
1698
+ throw new Error('default');
1699
+ },
1700
+ });
1701
+ const useMediaVolumeState = () => {
1702
+ const { mediaVolume } = useContext(MediaVolumeContext);
1703
+ const { setMediaVolume } = useContext(SetMediaVolumeContext);
1704
+ return useMemo(() => {
1705
+ return [mediaVolume, setMediaVolume];
1706
+ }, [mediaVolume, setMediaVolume]);
1707
+ };
1708
+ const useMediaMutedState = () => {
1709
+ const { mediaMuted } = useContext(MediaVolumeContext);
1710
+ const { setMediaMuted } = useContext(SetMediaVolumeContext);
1711
+ return useMemo(() => {
1712
+ return [mediaMuted, setMediaMuted];
1713
+ }, [mediaMuted, setMediaMuted]);
1714
+ };
1715
+
1716
+ const EMPTY_AUDIO = 'data:audio/mp3;base64,/+MYxAAJcAV8AAgAABn//////+/gQ5BAMA+D4Pg+BAQBAEAwD4Pg+D4EBAEAQDAPg++hYBH///hUFQVBUFREDQNHmf///////+MYxBUGkAGIMAAAAP/29Xt6lUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDUAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV';
1717
+ const compareProps = (obj1, obj2) => {
1718
+ const keysA = Object.keys(obj1).sort();
1719
+ const keysB = Object.keys(obj2).sort();
1720
+ if (keysA.length !== keysB.length) {
1721
+ return false;
1722
+ }
1723
+ for (let i = 0; i < keysA.length; i++) {
1724
+ // Not the same keys
1725
+ if (keysA[i] !== keysB[i]) {
1726
+ return false;
1727
+ }
1728
+ // Not the same values
1729
+ if (obj1[keysA[i]] !== obj2[keysB[i]]) {
1730
+ return false;
1731
+ }
1732
+ }
1733
+ return true;
1734
+ };
1735
+ const didPropChange = (key, newProp, prevProp) => {
1736
+ // /music.mp3 and http://localhost:3000/music.mp3 are the same
1737
+ if (key === 'src' &&
1738
+ !prevProp.startsWith('data:') &&
1739
+ !newProp.startsWith('data:')) {
1740
+ return (new URL(prevProp, window.location.origin).toString() !==
1741
+ new URL(newProp, window.location.origin).toString());
1742
+ }
1743
+ if (prevProp === newProp) {
1744
+ return false;
1745
+ }
1746
+ return true;
1747
+ };
1748
+ const SharedAudioContext = createContext(null);
1749
+ const SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) => {
1750
+ const audios = useRef([]);
1751
+ const [initialNumberOfAudioTags] = useState(numberOfAudioTags);
1752
+ if (numberOfAudioTags !== initialNumberOfAudioTags) {
1753
+ throw new Error('The number of shared audio tags has changed dynamically. Once you have set this property, you cannot change it afterwards.');
1754
+ }
1755
+ const refs = useMemo(() => {
1756
+ return new Array(numberOfAudioTags).fill(true).map(() => {
1757
+ return { id: Math.random(), ref: createRef() };
1758
+ });
1759
+ }, [numberOfAudioTags]);
1760
+ const takenAudios = useRef(new Array(numberOfAudioTags).fill(false));
1761
+ const rerenderAudios = useCallback(() => {
1762
+ refs.forEach(({ ref, id }) => {
1763
+ var _a;
1764
+ const data = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.id === id);
1765
+ const { current } = ref;
1766
+ if (!current) {
1767
+ // Whole player has been unmounted, the refs don't exist anymore.
1768
+ // It is not an error anymore though
1769
+ return;
1770
+ }
1771
+ if (data === undefined) {
1772
+ current.src = EMPTY_AUDIO;
1773
+ return;
1774
+ }
1775
+ if (!data) {
1776
+ throw new TypeError('Expected audio data to be there');
1777
+ }
1778
+ Object.keys(data.props).forEach((key) => {
1779
+ // @ts-expect-error
1780
+ if (didPropChange(key, data.props[key], current[key])) {
1781
+ // @ts-expect-error
1782
+ current[key] = data.props[key];
1783
+ }
1784
+ });
1785
+ });
1786
+ }, [refs]);
1787
+ const registerAudio = useCallback((aud, audioId) => {
1788
+ var _a, _b;
1789
+ const found = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.audioId === audioId);
1790
+ if (found) {
1791
+ return found;
1792
+ }
1793
+ const firstFreeAudio = takenAudios.current.findIndex((a) => a === false);
1794
+ if (firstFreeAudio === -1) {
1795
+ throw new Error(`Tried to simultaneously mount ${numberOfAudioTags + 1} <Audio /> tags at the same time. With the current settings, the maximum amount of <Audio /> tags is limited to ${numberOfAudioTags} at the same time. Remotion pre-mounts silent audio tags to help avoid browser autoplay restrictions. See https://remotion.dev/docs/player/autoplay#use-the-numberofsharedaudiotags-property for more information on how to increase this limit.`);
1796
+ }
1797
+ const { id, ref } = refs[firstFreeAudio];
1798
+ const cloned = [...takenAudios.current];
1799
+ cloned[firstFreeAudio] = id;
1800
+ takenAudios.current = cloned;
1801
+ const newElem = {
1802
+ props: aud,
1803
+ id,
1804
+ el: ref,
1805
+ audioId,
1806
+ };
1807
+ (_b = audios.current) === null || _b === void 0 ? void 0 : _b.push(newElem);
1808
+ rerenderAudios();
1809
+ return newElem;
1810
+ }, [numberOfAudioTags, refs, rerenderAudios]);
1811
+ const unregisterAudio = useCallback((id) => {
1812
+ var _a;
1813
+ const cloned = [...takenAudios.current];
1814
+ const index = refs.findIndex((r) => r.id === id);
1815
+ if (index === -1) {
1816
+ throw new TypeError('Error occured in ');
1817
+ }
1818
+ cloned[index] = false;
1819
+ takenAudios.current = cloned;
1820
+ audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.filter((a) => a.id !== id);
1821
+ rerenderAudios();
1822
+ }, [refs, rerenderAudios]);
1823
+ const updateAudio = useCallback(({ aud, audioId, id, }) => {
1824
+ var _a;
1825
+ let changed = false;
1826
+ audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.map((prevA) => {
1827
+ if (prevA.id === id) {
1828
+ const isTheSame = compareProps(aud, prevA.props);
1829
+ if (isTheSame) {
1830
+ return prevA;
1831
+ }
1832
+ changed = true;
1833
+ return {
1834
+ ...prevA,
1835
+ props: aud,
1836
+ audioId,
1837
+ };
1838
+ }
1839
+ return prevA;
1840
+ });
1841
+ if (changed) {
1842
+ rerenderAudios();
1843
+ }
1844
+ }, [rerenderAudios]);
1845
+ const playAllAudios = useCallback(() => {
1846
+ refs.forEach((ref) => {
1847
+ var _a;
1848
+ (_a = ref.ref.current) === null || _a === void 0 ? void 0 : _a.play();
1849
+ });
1850
+ }, [refs]);
1851
+ const value = useMemo(() => {
1852
+ return {
1853
+ registerAudio,
1854
+ unregisterAudio,
1855
+ updateAudio,
1856
+ playAllAudios,
1857
+ numberOfAudioTags,
1858
+ };
1859
+ }, [
1860
+ numberOfAudioTags,
1861
+ playAllAudios,
1862
+ registerAudio,
1863
+ unregisterAudio,
1864
+ updateAudio,
1865
+ ]);
1866
+ // Fixing a bug: In React, if a component is unmounted using useInsertionEffect, then
1867
+ // the cleanup function does sometimes not work properly. That is why when we
1868
+ // are changing the composition, we reset the audio state.
1869
+ // TODO: Possibly this does not save the problem completely, since the
1870
+ // if an audio tag that is inside a sequence will also not be removed
1871
+ // from the shared audios.
1872
+ const resetAudio = useCallback(() => {
1873
+ takenAudios.current = new Array(numberOfAudioTags).fill(false);
1874
+ audios.current = [];
1875
+ rerenderAudios();
1876
+ }, [numberOfAudioTags, rerenderAudios]);
1877
+ useEffect(() => {
1878
+ return () => {
1879
+ resetAudio();
1880
+ };
1881
+ }, [component, resetAudio]);
1882
+ return (jsxs(SharedAudioContext.Provider, { value: value, children: [refs.map(({ id, ref }) => {
1883
+ return jsx("audio", { ref: ref, src: EMPTY_AUDIO }, id);
1884
+ }), children] }));
1885
+ };
1886
+ const useSharedAudio = (aud, audioId) => {
1887
+ var _a;
1888
+ const ctx = useContext(SharedAudioContext);
1889
+ /**
1890
+ * We work around this in React 18 so an audio tag will only register itself once
1891
+ */
1892
+ const [elem] = useState(() => {
1893
+ if (ctx && ctx.numberOfAudioTags > 0) {
1894
+ return ctx.registerAudio(aud, audioId);
1895
+ }
1896
+ return {
1897
+ el: React.createRef(),
1898
+ id: Math.random(),
1899
+ props: aud,
1900
+ audioId,
1901
+ };
1902
+ });
1903
+ /**
1904
+ * Effects in React 18 fire twice, and we are looking for a way to only fire it once.
1905
+ * - useInsertionEffect only fires once. If it's available we are in React 18.
1906
+ * - useLayoutEffect only fires once in React 17.
1907
+ *
1908
+ * Need to import it from React to fix React 17 ESM support.
1909
+ */
1910
+ const effectToUse = (_a = React.useInsertionEffect) !== null && _a !== void 0 ? _a : React.useLayoutEffect;
1911
+ if (typeof document !== 'undefined') {
1912
+ effectToUse(() => {
1913
+ if (ctx && ctx.numberOfAudioTags > 0) {
1914
+ ctx.updateAudio({ id: elem.id, aud, audioId });
1915
+ }
1916
+ }, [aud, ctx, elem.id, audioId]);
1917
+ effectToUse(() => {
1918
+ return () => {
1919
+ if (ctx && ctx.numberOfAudioTags > 0) {
1920
+ ctx.unregisterAudio(elem.id);
1921
+ }
1922
+ };
1923
+ }, [ctx, elem.id]);
1924
+ }
1925
+ return elem;
1926
+ };
1927
+
1928
+ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
1929
+ const [initialShouldPreMountAudioElements] = useState(props.shouldPreMountAudioTags);
1930
+ if (props.shouldPreMountAudioTags !== initialShouldPreMountAudioElements) {
1931
+ throw new Error('Cannot change the behavior for pre-mounting audio tags dynamically.');
1932
+ }
1933
+ const [mediaVolume] = useMediaVolumeState();
1934
+ const [mediaMuted] = useMediaMutedState();
1935
+ const volumePropFrame = useFrameForVolumeProp();
1936
+ const { volume, muted, playbackRate, shouldPreMountAudioTags, src, onDuration, acceptableTimeShiftInSeconds, ...nativeProps } = props;
1937
+ if (!src) {
1938
+ throw new TypeError("No 'src' was passed to <Audio>.");
1939
+ }
1940
+ const preloadedSrc = usePreload(src);
1941
+ const propsToPass = useMemo(() => {
1942
+ return {
1943
+ muted: muted || mediaMuted,
1944
+ src: preloadedSrc,
1945
+ ...nativeProps,
1946
+ };
1947
+ }, [mediaMuted, muted, nativeProps, preloadedSrc]);
1948
+ const sequenceContext = useContext(SequenceContext);
1949
+ // Generate a string that's as unique as possible for this asset
1950
+ // but at the same time deterministic. We use it to combat strict mode issues.
1951
+ 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}`, [
1952
+ src,
1953
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
1954
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
1955
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
1956
+ props.muted,
1957
+ props.loop,
1958
+ ]);
1959
+ const audioRef = useSharedAudio(propsToPass, id).el;
1960
+ const actualVolume = useMediaTagVolume(audioRef);
1961
+ useSyncVolumeWithMediaTag({
1962
+ volumePropFrame,
1963
+ actualVolume,
1964
+ volume,
1965
+ mediaVolume,
1966
+ mediaRef: audioRef,
1967
+ });
1968
+ useMediaInTimeline({
1969
+ volume,
1970
+ mediaVolume,
1971
+ mediaRef: audioRef,
1972
+ src,
1973
+ mediaType: 'audio',
1974
+ playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
1975
+ });
1976
+ useMediaPlayback({
1977
+ mediaRef: audioRef,
1978
+ src,
1979
+ mediaType: 'audio',
1980
+ playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
1981
+ onlyWarnForMediaSeekingError: false,
1982
+ acceptableTimeshift: acceptableTimeShiftInSeconds !== null && acceptableTimeShiftInSeconds !== void 0 ? acceptableTimeShiftInSeconds : DEFAULT_ACCEPTABLE_TIMESHIFT,
1983
+ });
1984
+ useImperativeHandle(ref, () => {
1985
+ return audioRef.current;
1986
+ }, [audioRef]);
1987
+ const currentOnDurationCallback = useRef();
1988
+ currentOnDurationCallback.current = onDuration;
1989
+ useEffect(() => {
1990
+ var _a;
1991
+ const { current } = audioRef;
1992
+ if (!current) {
1993
+ return;
1994
+ }
1995
+ if (current.duration) {
1996
+ (_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, current.src, current.duration);
1997
+ return;
1998
+ }
1999
+ const onLoadedMetadata = () => {
2000
+ var _a;
2001
+ (_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, current.src, current.duration);
2002
+ };
2003
+ current.addEventListener('loadedmetadata', onLoadedMetadata);
2004
+ return () => {
2005
+ current.removeEventListener('loadedmetadata', onLoadedMetadata);
2006
+ };
2007
+ }, [audioRef, src]);
2008
+ if (initialShouldPreMountAudioElements) {
2009
+ return null;
2010
+ }
2011
+ return jsx("audio", { ref: audioRef, ...propsToPass });
2012
+ };
2013
+ const AudioForDevelopment = forwardRef(AudioForDevelopmentForwardRefFunction);
2014
+
2015
+ const AssetManager = createContext({
2016
+ registerAsset: () => undefined,
2017
+ unregisterAsset: () => undefined,
2018
+ assets: [],
2019
+ });
2020
+ const AssetManagerProvider = ({ children }) => {
2021
+ const [assets, setAssets] = useState([]);
2022
+ const registerAsset = useCallback((asset) => {
2023
+ setAssets((assts) => {
2024
+ return [...assts, asset];
2025
+ });
2026
+ }, []);
2027
+ const unregisterAsset = useCallback((id) => {
2028
+ setAssets((assts) => {
2029
+ return assts.filter((a) => a.id !== id);
2030
+ });
2031
+ }, []);
2032
+ useLayoutEffect(() => {
2033
+ if (typeof window !== 'undefined') {
2034
+ window.remotion_collectAssets = () => {
2035
+ setAssets([]); // clear assets at next render
2036
+ return assets;
2037
+ };
2038
+ }
2039
+ }, [assets]);
2040
+ const contextValue = useMemo(() => {
2041
+ return {
2042
+ registerAsset,
2043
+ unregisterAsset,
2044
+ assets,
2045
+ };
2046
+ }, [assets, registerAsset, unregisterAsset]);
2047
+ return (jsx(AssetManager.Provider, { value: contextValue, children: children }));
2048
+ };
2049
+
2050
+ if (typeof window !== 'undefined') {
2051
+ window.remotion_renderReady = false;
2052
+ }
2053
+ let handles = [];
2054
+ const timeouts = {};
2055
+ const DELAY_RENDER_CALLSTACK_TOKEN = 'The delayRender was called:';
2056
+ const defaultTimeout = 30000;
2057
+ /**
2058
+ * @description Call this function to tell Remotion to wait before capturing this frame until data has loaded. Use continueRender() to unblock the render.
2059
+ * @param label _optional_ A label to identify the call in case it does time out.
2060
+ * @returns {number} An identifier to be passed to continueRender().
2061
+ * @see [Documentation](https://www.remotion.dev/docs/delay-render)
2062
+ */
2063
+ const delayRender = (label) => {
2064
+ var _a, _b, _c;
2065
+ if (typeof label !== 'string' && typeof label !== 'undefined') {
2066
+ throw new Error('The label parameter of delayRender() must be a string or undefined, got: ' +
2067
+ JSON.stringify(label));
2068
+ }
2069
+ const handle = Math.random();
2070
+ handles.push(handle);
2071
+ const called = (_b = (_a = Error().stack) === null || _a === void 0 ? void 0 : _a.replace(/^Error/g, '')) !== null && _b !== void 0 ? _b : '';
2072
+ if (getRemotionEnvironment() === 'rendering') {
2073
+ const timeoutToUse = typeof window === 'undefined'
2074
+ ? defaultTimeout
2075
+ : ((_c = window.remotion_puppeteerTimeout) !== null && _c !== void 0 ? _c : defaultTimeout) - 2000;
2076
+ timeouts[handle] = setTimeout(() => {
2077
+ const message = [
2078
+ `A delayRender()`,
2079
+ label ? `"${label}"` : null,
2080
+ `was called but not cleared after ${timeoutToUse}ms. See https://remotion.dev/docs/timeout for help.`,
2081
+ DELAY_RENDER_CALLSTACK_TOKEN,
2082
+ called,
2083
+ ]
2084
+ .filter(truthy)
2085
+ .join(' ');
2086
+ throw new Error(message);
2087
+ }, timeoutToUse);
2088
+ }
2089
+ if (typeof window !== 'undefined') {
2090
+ window.remotion_renderReady = false;
2091
+ }
2092
+ return handle;
2093
+ };
2094
+ /**
2095
+ * @description Unblock a render that has been blocked by delayRender()
2096
+ * @param handle The return value of delayRender().
2097
+ * @see [Documentation](https://www.remotion.dev/docs/continue-render)
2098
+ */
2099
+ const continueRender = (handle) => {
2100
+ if (typeof handle === 'undefined') {
2101
+ throw new TypeError('The continueRender() method must be called with a parameter that is the return value of delayRender(). No value was passed.');
2102
+ }
2103
+ if (typeof handle !== 'number') {
2104
+ throw new TypeError('The parameter passed into continueRender() must be the return value of delayRender() which is a number. Got: ' +
2105
+ JSON.stringify(handle));
2106
+ }
2107
+ handles = handles.filter((h) => {
2108
+ if (h === handle) {
2109
+ if (getRemotionEnvironment() === 'rendering') {
2110
+ clearTimeout(timeouts[handle]);
2111
+ }
2112
+ return false;
2113
+ }
2114
+ return true;
2115
+ });
2116
+ if (handles.length === 0 && typeof window !== 'undefined') {
2117
+ window.remotion_renderReady = true;
2118
+ }
2119
+ };
2120
+
2121
+ const AudioForRenderingRefForwardingFunction = (props, ref) => {
2122
+ const audioRef = useRef(null);
2123
+ const absoluteFrame = useTimelinePosition();
2124
+ const volumePropFrame = useFrameForVolumeProp();
2125
+ const frame = useCurrentFrame();
2126
+ const sequenceContext = useContext(SequenceContext);
2127
+ const { registerAsset, unregisterAsset } = useContext(AssetManager);
2128
+ const environment = useRemotionEnvironment();
2129
+ // Generate a string that's as unique as possible for this asset
2130
+ // but at the same time the same on all threads
2131
+ const id = useMemo(() => {
2132
+ var _a;
2133
+ return `audio-${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}`;
2134
+ }, [props.src, sequenceContext]);
2135
+ const { volume: volumeProp, playbackRate, allowAmplificationDuringRender, onDuration, ...nativeProps } = props;
2136
+ const volume = evaluateVolume({
2137
+ volume: volumeProp,
2138
+ frame: volumePropFrame,
2139
+ mediaVolume: 1,
2140
+ allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
2141
+ });
2142
+ useImperativeHandle(ref, () => {
2143
+ return audioRef.current;
2144
+ }, []);
2145
+ useEffect(() => {
2146
+ var _a;
2147
+ if (!props.src) {
2148
+ throw new Error('No src passed');
2149
+ }
2150
+ if (!window.remotion_audioEnabled) {
2151
+ return;
2152
+ }
2153
+ if (props.muted) {
2154
+ return;
2155
+ }
2156
+ if (volume <= 0) {
2157
+ return;
2158
+ }
2159
+ registerAsset({
2160
+ type: 'audio',
2161
+ src: getAbsoluteSrc(props.src),
2162
+ id,
2163
+ frame: absoluteFrame,
2164
+ volume,
2165
+ mediaFrame: frame,
2166
+ playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
2167
+ allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
2168
+ });
2169
+ return () => unregisterAsset(id);
2170
+ }, [
2171
+ props.muted,
2172
+ props.src,
2173
+ registerAsset,
2174
+ absoluteFrame,
2175
+ id,
2176
+ unregisterAsset,
2177
+ volume,
2178
+ volumePropFrame,
2179
+ frame,
2180
+ playbackRate,
2181
+ props.playbackRate,
2182
+ allowAmplificationDuringRender,
2183
+ ]);
2184
+ const { src } = props;
2185
+ // If audio source switches, make new handle
2186
+ if (environment === 'rendering') {
2187
+ // eslint-disable-next-line react-hooks/rules-of-hooks
2188
+ useLayoutEffect(() => {
2189
+ if (process.env.NODE_ENV === 'test') {
2190
+ return;
2191
+ }
2192
+ const newHandle = delayRender('Loading <Audio> duration with src=' + src);
2193
+ const { current } = audioRef;
2194
+ const didLoad = () => {
2195
+ if (current === null || current === void 0 ? void 0 : current.duration) {
2196
+ onDuration(current.src, current.duration);
2197
+ }
2198
+ continueRender(newHandle);
2199
+ };
2200
+ if (current === null || current === void 0 ? void 0 : current.duration) {
2201
+ onDuration(current.src, current.duration);
2202
+ continueRender(newHandle);
2203
+ }
2204
+ else {
2205
+ current === null || current === void 0 ? void 0 : current.addEventListener('loadedmetadata', didLoad, { once: true });
2206
+ }
2207
+ // If tag gets unmounted, clear pending handles because video metadata is not going to load
2208
+ return () => {
2209
+ current === null || current === void 0 ? void 0 : current.removeEventListener('loadedmetadata', didLoad);
2210
+ continueRender(newHandle);
2211
+ };
2212
+ }, [src, onDuration]);
2213
+ }
2214
+ return jsx("audio", { ref: audioRef, ...nativeProps });
2215
+ };
2216
+ const AudioForRendering = forwardRef(AudioForRenderingRefForwardingFunction);
2217
+
2218
+ const AudioRefForwardingFunction = (props, ref) => {
2219
+ var _a;
2220
+ const audioContext = useContext(SharedAudioContext);
2221
+ const { startFrom, endAt, ...otherProps } = props;
2222
+ const { loop, ...propsOtherThanLoop } = props;
2223
+ const { fps } = useVideoConfig();
2224
+ const environment = useRemotionEnvironment();
2225
+ const { durations, setDurations } = useContext(DurationsContext);
2226
+ if (typeof props.src !== 'string') {
2227
+ throw new TypeError(`The \`<Audio>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
2228
+ }
2229
+ const onError = useCallback((e) => {
2230
+ console.log(e.currentTarget.error);
2231
+ cancelRender(new Error(`Could not play audio with src ${otherProps.src}: ${e.currentTarget.error}. See https://remotion.dev/docs/media-playback-error for help.`));
2232
+ }, [otherProps.src]);
2233
+ const onDuration = useCallback((src, durationInSeconds) => {
2234
+ setDurations({ type: 'got-duration', durationInSeconds, src });
2235
+ }, [setDurations]);
2236
+ if (loop && props.src && durations[getAbsoluteSrc(props.src)] !== undefined) {
2237
+ const duration = Math.floor(durations[getAbsoluteSrc(props.src)] * fps);
2238
+ const playbackRate = (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1;
2239
+ const actualDuration = duration / playbackRate;
2240
+ return (jsx(Loop, { layout: "none", durationInFrames: Math.floor(actualDuration), children: jsx(Audio, { ...propsOtherThanLoop, ref: ref }) }));
2241
+ }
2242
+ if (typeof startFrom !== 'undefined' || typeof endAt !== 'undefined') {
2243
+ validateStartFromProps(startFrom, endAt);
2244
+ const startFromFrameNo = startFrom !== null && startFrom !== void 0 ? startFrom : 0;
2245
+ const endAtFrameNo = endAt !== null && endAt !== void 0 ? endAt : Infinity;
2246
+ return (jsx(Sequence, { layout: "none", from: 0 - startFromFrameNo, showInTimeline: false, durationInFrames: endAtFrameNo, children: jsx(Audio, { ...otherProps, ref: ref }) }));
2247
+ }
2248
+ validateMediaProps(props, 'Audio');
2249
+ if (environment === 'rendering') {
2250
+ return (jsx(AudioForRendering, { onDuration: onDuration, ...props, ref: ref, onError: onError }));
2251
+ }
2252
+ return (jsx(AudioForDevelopment, { shouldPreMountAudioTags: audioContext !== null && audioContext.numberOfAudioTags > 0, ...props, ref: ref, onError: onError, onDuration: onDuration }));
2253
+ };
2254
+ /**
2255
+ * @description With this component, you can add audio to your video. All audio formats which are supported by Chromium are supported by the component.
2256
+ * @see [Documentation](https://www.remotion.dev/docs/audio)
2257
+ */
2258
+ const Audio = forwardRef(AudioRefForwardingFunction);
2259
+
2260
+ const validateFolderName = (name) => {
2261
+ if (name === undefined || name === null) {
2262
+ throw new TypeError('You must pass a name to a <Folder />.');
2263
+ }
2264
+ if (typeof name !== 'string') {
2265
+ throw new TypeError(`The "name" you pass into <Folder /> must be a string. Got: ${typeof name}`);
2266
+ }
2267
+ if (!isFolderNameValid(name)) {
2268
+ throw new Error(`Folder name can only contain a-z, A-Z, 0-9 and -. You passed ${name}`);
2269
+ }
2270
+ };
2271
+ const getRegex$1 = () => /^([a-zA-Z0-9-])+$/g;
2272
+ const isFolderNameValid = (name) => name.match(getRegex$1());
2273
+
2274
+ const FolderContext = createContext({
2275
+ folderName: null,
2276
+ parentName: null,
2277
+ });
2278
+ /**
2279
+ * @description By wrapping a <Composition /> inside a <Folder />, you can visually categorize it in your sidebar, should you have many compositions.
2280
+ * @see [Documentation](https://www.remotion.dev/docs/folder)
2281
+ */
2282
+ const Folder = ({ name, children, }) => {
2283
+ const parent = useContext(FolderContext);
2284
+ const { registerFolder, unregisterFolder } = useContext(CompositionManager);
2285
+ validateFolderName(name);
2286
+ const parentNameArr = [parent.parentName, parent.folderName].filter(truthy);
2287
+ const parentName = parentNameArr.length === 0 ? null : parentNameArr.join('/');
2288
+ const value = useMemo(() => {
2289
+ return {
2290
+ folderName: name,
2291
+ parentName,
2292
+ };
2293
+ }, [name, parentName]);
2294
+ useEffect(() => {
2295
+ registerFolder(name, parentName);
2296
+ return () => {
2297
+ unregisterFolder(name, parentName);
2298
+ };
2299
+ }, [name, parent.folderName, parentName, registerFolder, unregisterFolder]);
2300
+ return (jsx(FolderContext.Provider, { value: value, children: children }));
2301
+ };
2302
+
2303
+ const rotate = {
2304
+ transform: `rotate(90deg)`,
2305
+ };
2306
+ const ICON_SIZE = 40;
2307
+ const label = {
2308
+ color: 'white',
2309
+ fontSize: 14,
2310
+ fontFamily: 'sans-serif',
2311
+ };
2312
+ const container = {
2313
+ justifyContent: 'center',
2314
+ alignItems: 'center',
2315
+ };
2316
+ const Loading = () => {
2317
+ return (jsxs(AbsoluteFill, { style: container, id: "remotion-comp-loading", children: [jsx("style", { type: "text/css", children: `
2318
+ @keyframes anim {
2319
+ from {
2320
+ opacity: 0
2321
+ }
2322
+ to {
2323
+ opacity: 1
2324
+ }
2325
+ }
2326
+ #remotion-comp-loading {
2327
+ animation: anim 2s;
2328
+ animation-fill-mode: forwards;
2329
+ }
2330
+ ` }), jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "-100 -100 400 400", style: rotate, children: jsx("path", { fill: "#555", stroke: "#555", strokeWidth: "100", strokeLinejoin: "round", d: "M 2 172 a 196 100 0 0 0 195 5 A 196 240 0 0 0 100 2.259 A 196 240 0 0 0 2 172 z" }) }), jsxs("p", { style: label, children: ["Resolving ", '<Suspense>', "..."] })] }));
2331
+ };
2332
+
2333
+ let _portalNode = null;
2334
+ const portalNode = () => {
2335
+ if (!_portalNode) {
2336
+ if (typeof document === 'undefined') {
2337
+ throw new Error('Tried to call an API that only works in the browser from outside the browser');
2338
+ }
2339
+ _portalNode = document.createElement('div');
2340
+ _portalNode.style.position = 'absolute';
2341
+ _portalNode.style.top = '0px';
2342
+ _portalNode.style.left = '0px';
2343
+ _portalNode.style.right = '0px';
2344
+ _portalNode.style.bottom = '0px';
2345
+ _portalNode.style.width = '100%';
2346
+ _portalNode.style.height = '100%';
2347
+ _portalNode.style.display = 'flex';
2348
+ _portalNode.style.flexDirection = 'column';
2349
+ }
2350
+ return _portalNode;
2351
+ };
2352
+
2353
+ // Expected, it can be any component props
2354
+ const useLazyComponent = (compProps) => {
2355
+ const lazy = useMemo(() => {
2356
+ if ('lazyComponent' in compProps) {
2357
+ return React.lazy(compProps.lazyComponent);
2358
+ }
2359
+ if ('component' in compProps) {
2360
+ // In SSR, suspense is not yet supported, we cannot use React.lazy
2361
+ if (typeof document === 'undefined') {
2362
+ return compProps.component;
2363
+ }
2364
+ return React.lazy(() => Promise.resolve({ default: compProps.component }));
2365
+ }
2366
+ throw new Error("You must pass either 'component' or 'lazyComponent'");
2367
+ // Very important to leave the dependencies as they are, or instead
2368
+ // the player will remount on every frame.
2369
+ // @ts-expect-error
2370
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2371
+ }, [compProps.component, compProps.lazyComponent]);
2372
+ return lazy;
2373
+ };
2374
+
2375
+ const validateCompositionId = (id) => {
2376
+ if (!isCompositionIdValid(id)) {
2377
+ throw new Error(`Composition id can only contain a-z, A-Z, 0-9 and -. You passed ${id}`);
2378
+ }
2379
+ };
2380
+ const getRegex = () => /^([a-zA-Z0-9-])+$/g;
2381
+ const isCompositionIdValid = (id) => id.match(getRegex());
2382
+ const invalidCompositionErrorMessage = `Composition ID must match ${String(getRegex())}`;
2383
+
2384
+ const validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
2385
+ if (!defaultProps) {
2386
+ return;
2387
+ }
2388
+ if (typeof defaultProps !== 'object') {
2389
+ throw new Error(`"${name}" must be an object, but you passed a value of type ${typeof defaultProps}`);
2390
+ }
2391
+ if (Array.isArray(defaultProps)) {
2392
+ throw new Error(`"${name}" must be an object, an array was passed ${compositionId ? `for composition "${compositionId}"` : ''}`);
2393
+ }
2394
+ };
2395
+
2396
+ const validateFps = (fps, location, isGif) => {
2397
+ if (typeof fps !== 'number') {
2398
+ throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
2399
+ }
2400
+ if (!Number.isFinite(fps)) {
2401
+ throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
2402
+ }
2403
+ if (isNaN(fps)) {
2404
+ throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
2405
+ }
2406
+ if (fps <= 0) {
2407
+ throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
2408
+ }
2409
+ if (isGif && fps > 50) {
2410
+ throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
2411
+ }
2412
+ };
2413
+
2414
+ const Fallback = () => {
2415
+ useEffect(() => {
2416
+ const fallback = delayRender('Waiting for Root component to unsuspend');
2417
+ return () => continueRender(fallback);
2418
+ }, []);
2419
+ return null;
2420
+ };
2421
+ /**
2422
+ * @description This component is used to register a video to make it renderable and make it show in the sidebar, in dev mode.
2423
+ * @see [Documentation](https://www.remotion.dev/docs/composition)
2424
+ */
2425
+ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, schema, ...compProps }) => {
2426
+ var _a, _b;
2427
+ const { registerComposition, unregisterComposition } = useContext(CompositionManager);
2428
+ const video = useVideo();
2429
+ const lazy = useLazyComponent(compProps);
2430
+ const nonce = useNonce();
2431
+ const environment = useRemotionEnvironment();
2432
+ const canUseComposition = useContext(CanUseRemotionHooks);
2433
+ if (canUseComposition) {
2434
+ if (environment === 'player-development' ||
2435
+ environment === 'player-production') {
2436
+ throw new Error('<Composition> was mounted inside the `component` that was passed to the <Player>. See https://remotion.dev/docs/wrong-composition-mount for help.');
2437
+ }
2438
+ throw new Error('<Composition> mounted inside another composition. See https://remotion.dev/docs/wrong-composition-mount for help.');
2439
+ }
2440
+ const { folderName, parentName } = useContext(FolderContext);
2441
+ useEffect(() => {
2442
+ var _a;
2443
+ // Ensure it's a URL safe id
2444
+ if (!id) {
2445
+ throw new Error('No id for composition passed.');
2446
+ }
2447
+ validateCompositionId(id);
2448
+ validateDimension(width, 'width', 'of the <Composition/> component');
2449
+ validateDimension(height, 'height', 'of the <Composition/> component');
2450
+ validateDurationInFrames({
2451
+ durationInFrames,
2452
+ component: 'of the <Composition/> component',
2453
+ allowFloats: false,
2454
+ });
2455
+ validateFps(fps, 'as a prop of the <Composition/> component', false);
2456
+ validateDefaultAndInputProps(defaultProps, 'defaultProps', id);
2457
+ registerComposition({
2458
+ durationInFrames,
2459
+ fps,
2460
+ height,
2461
+ width,
2462
+ id,
2463
+ folderName,
2464
+ component: lazy,
2465
+ defaultProps: defaultProps,
2466
+ nonce,
2467
+ parentFolderName: parentName,
2468
+ schema: schema !== null && schema !== void 0 ? schema : null,
2469
+ calculateMetadata: (_a = compProps.calculateMetadata) !== null && _a !== void 0 ? _a : null,
2470
+ });
2471
+ return () => {
2472
+ unregisterComposition(id);
2473
+ };
2474
+ }, [
2475
+ durationInFrames,
2476
+ fps,
2477
+ height,
2478
+ lazy,
2479
+ id,
2480
+ folderName,
2481
+ defaultProps,
2482
+ registerComposition,
2483
+ unregisterComposition,
2484
+ width,
2485
+ nonce,
2486
+ parentName,
2487
+ schema,
2488
+ compProps.calculateMetadata,
2489
+ ]);
2490
+ const resolved = useResolvedVideoConfig(id);
2491
+ if (environment === 'preview' && video && video.component === lazy) {
2492
+ const Comp = lazy;
2493
+ if (resolved === null || resolved.type !== 'success') {
2494
+ return null;
2495
+ }
2496
+ return createPortal(jsx(ClipComposition, { children: jsx(CanUseRemotionHooksProvider, { children: jsx(Suspense, { fallback: jsx(Loading, {}), children: jsx(Comp, { ...((_a = resolved.result.defaultProps) !== null && _a !== void 0 ? _a : {}) }) }) }) }), portalNode());
2497
+ }
2498
+ if (environment === 'rendering' && video && video.component === lazy) {
2499
+ const Comp = lazy;
2500
+ if (resolved === null || resolved.type !== 'success') {
2501
+ return null;
2502
+ }
2503
+ return createPortal(jsx(CanUseRemotionHooksProvider, { children: jsx(Suspense, { fallback: jsx(Fallback, {}), children: jsx(Comp, { ...((_b = resolved.result.defaultProps) !== null && _b !== void 0 ? _b : {}) }) }) }), portalNode());
2504
+ }
2505
+ return null;
2506
+ };
2507
+ const ClipComposition = ({ children }) => {
2508
+ const { clipRegion } = useContext(NativeLayersContext);
2509
+ const style = useMemo(() => {
2510
+ return {
2511
+ display: 'flex',
2512
+ flexDirection: 'row',
2513
+ opacity: clipRegion === 'hide' ? 0 : 1,
2514
+ clipPath: clipRegion && clipRegion !== 'hide'
2515
+ ? `polygon(${clipRegion.x}px ${clipRegion.y}px, ${clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.y}px)`
2516
+ : undefined,
2517
+ };
2518
+ }, [clipRegion]);
2519
+ return jsx(AbsoluteFill, { style: style, children: children });
2520
+ };
2521
+
2522
+ // Taken from https://github.com/facebook/react-native/blob/0b9ea60b4fee8cacc36e7160e31b91fc114dbc0d/Libraries/Animated/src/bezier.js
2523
+ const NEWTON_ITERATIONS = 4;
2524
+ const NEWTON_MIN_SLOPE = 0.001;
2525
+ const SUBDIVISION_PRECISION = 0.0000001;
2526
+ const SUBDIVISION_MAX_ITERATIONS = 10;
2527
+ const kSplineTableSize = 11;
2528
+ const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
2529
+ const float32ArraySupported = typeof Float32Array === 'function';
2530
+ function a(aA1, aA2) {
2531
+ return 1.0 - 3.0 * aA2 + 3.0 * aA1;
2532
+ }
2533
+ function b(aA1, aA2) {
2534
+ return 3.0 * aA2 - 6.0 * aA1;
2535
+ }
2536
+ function c(aA1) {
2537
+ return 3.0 * aA1;
2538
+ }
2539
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
2540
+ function calcBezier(aT, aA1, aA2) {
2541
+ return ((a(aA1, aA2) * aT + b(aA1, aA2)) * aT + c(aA1)) * aT;
2542
+ }
2543
+ // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
2544
+ function getSlope(aT, aA1, aA2) {
2545
+ return 3.0 * a(aA1, aA2) * aT * aT + 2.0 * b(aA1, aA2) * aT + c(aA1);
2546
+ }
2547
+ function binarySubdivide({ aX, _aA, _aB, mX1, mX2, }) {
2548
+ let currentX;
2549
+ let currentT;
2550
+ let i = 0;
2551
+ let aA = _aA;
2552
+ let aB = _aB;
2553
+ do {
2554
+ currentT = aA + (aB - aA) / 2.0;
2555
+ currentX = calcBezier(currentT, mX1, mX2) - aX;
2556
+ if (currentX > 0.0) {
2557
+ aB = currentT;
2558
+ }
2559
+ else {
2560
+ aA = currentT;
2561
+ }
2562
+ } while (Math.abs(currentX) > SUBDIVISION_PRECISION &&
2563
+ ++i < SUBDIVISION_MAX_ITERATIONS);
2564
+ return currentT;
2565
+ }
2566
+ function newtonRaphsonIterate(aX, _aGuessT, mX1, mX2) {
2567
+ let aGuessT = _aGuessT;
2568
+ for (let i = 0; i < NEWTON_ITERATIONS; ++i) {
2569
+ const currentSlope = getSlope(aGuessT, mX1, mX2);
2570
+ if (currentSlope === 0.0) {
2571
+ return aGuessT;
2572
+ }
2573
+ const currentX = calcBezier(aGuessT, mX1, mX2) - aX;
2574
+ aGuessT -= currentX / currentSlope;
2575
+ }
2576
+ return aGuessT;
2577
+ }
2578
+ function bezier(mX1, mY1, mX2, mY2) {
2579
+ if (!(mX1 >= 0 && mX1 <= 1 && mX2 >= 0 && mX2 <= 1)) {
2580
+ throw new Error('bezier x values must be in [0, 1] range');
2581
+ }
2582
+ // Precompute samples table
2583
+ const sampleValues = float32ArraySupported
2584
+ ? new Float32Array(kSplineTableSize)
2585
+ : new Array(kSplineTableSize);
2586
+ if (mX1 !== mY1 || mX2 !== mY2) {
2587
+ for (let i = 0; i < kSplineTableSize; ++i) {
2588
+ sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
2589
+ }
2590
+ }
2591
+ function getTForX(aX) {
2592
+ let intervalStart = 0.0;
2593
+ let currentSample = 1;
2594
+ const lastSample = kSplineTableSize - 1;
2595
+ for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
2596
+ intervalStart += kSampleStepSize;
2597
+ }
2598
+ --currentSample;
2599
+ // Interpolate to provide an initial guess for t
2600
+ const dist = (aX - sampleValues[currentSample]) /
2601
+ (sampleValues[currentSample + 1] - sampleValues[currentSample]);
2602
+ const guessForT = intervalStart + dist * kSampleStepSize;
2603
+ const initialSlope = getSlope(guessForT, mX1, mX2);
2604
+ if (initialSlope >= NEWTON_MIN_SLOPE) {
2605
+ return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
2606
+ }
2607
+ if (initialSlope === 0.0) {
2608
+ return guessForT;
2609
+ }
2610
+ return binarySubdivide({
2611
+ aX,
2612
+ _aA: intervalStart,
2613
+ _aB: intervalStart + kSampleStepSize,
2614
+ mX1,
2615
+ mX2,
2616
+ });
2617
+ }
2618
+ return function (x) {
2619
+ if (mX1 === mY1 && mX2 === mY2) {
2620
+ return x; // linear
2621
+ }
2622
+ // Because JavaScript number are imprecise, we should guarantee the extremes are right.
2623
+ if (x === 0) {
2624
+ return 0;
2625
+ }
2626
+ if (x === 1) {
2627
+ return 1;
2628
+ }
2629
+ return calcBezier(getTForX(x), mY1, mY2);
2630
+ };
2631
+ }
2632
+
2633
+ // Taken from https://github.com/facebook/react-native/blob/0b9ea60b4fee8cacc36e7160e31b91fc114dbc0d/Libraries/Animated/src/Easing.js
2634
+ /**
2635
+ * @description The Easing module implements common easing functions. You can use it with the interpolate() API.
2636
+ * @see [Documentation](https://www.remotion.dev/docs/easing)
2637
+ */
2638
+ class Easing {
2639
+ static step0(n) {
2640
+ return n > 0 ? 1 : 0;
2641
+ }
2642
+ static step1(n) {
2643
+ return n >= 1 ? 1 : 0;
2644
+ }
2645
+ static linear(t) {
2646
+ return t;
2647
+ }
2648
+ static ease(t) {
2649
+ return Easing.bezier(0.42, 0, 1, 1)(t);
2650
+ }
2651
+ static quad(t) {
2652
+ return t * t;
2653
+ }
2654
+ static cubic(t) {
2655
+ return t * t * t;
2656
+ }
2657
+ static poly(n) {
2658
+ return (t) => t ** n;
2659
+ }
2660
+ static sin(t) {
2661
+ return 1 - Math.cos((t * Math.PI) / 2);
2662
+ }
2663
+ static circle(t) {
2664
+ return 1 - Math.sqrt(1 - t * t);
2665
+ }
2666
+ static exp(t) {
2667
+ return 2 ** (10 * (t - 1));
2668
+ }
2669
+ static elastic(bounciness = 1) {
2670
+ const p = bounciness * Math.PI;
2671
+ return (t) => 1 - Math.cos((t * Math.PI) / 2) ** 3 * Math.cos(t * p);
2672
+ }
2673
+ static back(s = 1.70158) {
2674
+ return (t) => t * t * ((s + 1) * t - s);
2675
+ }
2676
+ static bounce(t) {
2677
+ if (t < 1 / 2.75) {
2678
+ return 7.5625 * t * t;
2679
+ }
2680
+ if (t < 2 / 2.75) {
2681
+ const t2_ = t - 1.5 / 2.75;
2682
+ return 7.5625 * t2_ * t2_ + 0.75;
2683
+ }
2684
+ if (t < 2.5 / 2.75) {
2685
+ const t2_ = t - 2.25 / 2.75;
2686
+ return 7.5625 * t2_ * t2_ + 0.9375;
2687
+ }
2688
+ const t2 = t - 2.625 / 2.75;
2689
+ return 7.5625 * t2 * t2 + 0.984375;
2690
+ }
2691
+ static bezier(x1, y1, x2, y2) {
2692
+ return bezier(x1, y1, x2, y2);
2693
+ }
2694
+ static in(easing) {
2695
+ return easing;
2696
+ }
2697
+ static out(easing) {
2698
+ return (t) => 1 - easing(1 - t);
2699
+ }
2700
+ static inOut(easing) {
2701
+ return (t) => {
2702
+ if (t < 0.5) {
2703
+ return easing(t * 2) / 2;
2704
+ }
2705
+ return 1 - easing((1 - t) * 2) / 2;
2706
+ };
2707
+ }
2708
+ }
2709
+
2710
+ /**
2711
+ * @description This method freezes all of its children to the frame that you specify as a prop
2712
+ * @see [Documentation](https://www.remotion.dev/docs/freeze)
2713
+ */
2714
+ const Freeze = ({ frame, children }) => {
2715
+ if (typeof frame === 'undefined') {
2716
+ throw new Error(`The <Freeze /> component requires a 'frame' prop, but none was passed.`);
2717
+ }
2718
+ if (typeof frame !== 'number') {
2719
+ throw new Error(`The 'frame' prop of <Freeze /> must be a number, but is of type ${typeof frame}`);
2720
+ }
2721
+ if (Number.isNaN(frame)) {
2722
+ throw new Error(`The 'frame' prop of <Freeze /> must be a real number, but it is NaN.`);
2723
+ }
2724
+ if (!Number.isFinite(frame)) {
2725
+ throw new Error(`The 'frame' prop of <Freeze /> must be a finite number, but it is ${frame}.`);
2726
+ }
2727
+ const context = useContext(TimelineContext);
2728
+ const value = useMemo(() => {
2729
+ return {
2730
+ ...context,
2731
+ playing: false,
2732
+ imperativePlaying: {
2733
+ current: false,
2734
+ },
2735
+ frame,
2736
+ };
2737
+ }, [context, frame]);
2738
+ return (jsx(TimelineContext.Provider, { value: value, children: jsx(SequenceContext.Provider, { value: null, children: children }) }));
2739
+ };
2740
+
2741
+ let warnedServer = false;
2742
+ let warnedPlayer = false;
2743
+ const warnServerOnce = () => {
2744
+ if (warnedServer) {
2745
+ return;
2746
+ }
2747
+ warnedServer = true;
2748
+ console.warn('Called getStaticFiles() on the server. The API is only available in the browser. An empty array was returned.');
2749
+ };
2750
+ const warnPlayerOnce = () => {
2751
+ if (warnedPlayer) {
2752
+ return;
2753
+ }
2754
+ warnedPlayer = true;
2755
+ console.warn('Called getStaticFiles() while using the Remotion Player. The API is only available while using the Remotion Studio. An empty array was returned.');
2756
+ };
2757
+ /**
2758
+ * @description The function array containing all files in the public/ folder. You can reference them by using staticFile().
2759
+ * @see [Documentation](https://www.remotion.dev/docs/getstaticfiles)
2760
+ */
2761
+ const getStaticFiles = () => {
2762
+ if (typeof document === 'undefined') {
2763
+ warnServerOnce();
2764
+ return [];
2765
+ }
2766
+ if (window.remotion_isPlayer) {
2767
+ warnPlayerOnce();
2768
+ return [];
2769
+ }
2770
+ return window.remotion_staticFiles;
2771
+ };
2772
+
2773
+ const IFrameRefForwarding = ({ onLoad, onError, ...props }, ref) => {
2774
+ const [handle] = useState(() => delayRender(`Loading <IFrame> with source ${props.src}`));
2775
+ const didLoad = useCallback((e) => {
2776
+ continueRender(handle);
2777
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e);
2778
+ }, [handle, onLoad]);
2779
+ const didGetError = useCallback((e) => {
2780
+ continueRender(handle);
2781
+ if (onError) {
2782
+ onError(e);
2783
+ }
2784
+ else {
2785
+ console.error('Error loading iframe:', e, 'Handle the event using the onError() prop to make this message disappear.');
2786
+ }
2787
+ }, [handle, onError]);
2788
+ return jsx("iframe", { ...props, ref: ref, onError: didGetError, onLoad: didLoad });
2789
+ };
2790
+ /**
2791
+ * @description The <IFrame /> can be used like a regular <iframe> HTML tag.
2792
+ * @see [Documentation](https://www.remotion.dev/docs/iframe)
2793
+ */
2794
+ const IFrame = forwardRef(IFrameRefForwarding);
2795
+
2796
+ function exponentialBackoff(errorCount) {
2797
+ return 1000 * 2 ** (errorCount - 1);
2798
+ }
2799
+ const ImgRefForwarding = ({ onError, maxRetries = 2, src, ...props }, ref) => {
2800
+ const imageRef = useRef(null);
2801
+ const errors = useRef({});
2802
+ if (!src) {
2803
+ throw new Error('No "src" prop was passed to <Img>.');
2804
+ }
2805
+ useImperativeHandle(ref, () => {
2806
+ return imageRef.current;
2807
+ }, []);
2808
+ const actualSrc = usePreload(src);
2809
+ const retryIn = useCallback((timeout) => {
2810
+ if (!imageRef.current) {
2811
+ return;
2812
+ }
2813
+ const currentSrc = imageRef.current.src;
2814
+ setTimeout(() => {
2815
+ var _a;
2816
+ if (!imageRef.current) {
2817
+ // Component has been unmounted, do not retry
2818
+ return;
2819
+ }
2820
+ const newSrc = (_a = imageRef.current) === null || _a === void 0 ? void 0 : _a.src;
2821
+ if (newSrc !== currentSrc) {
2822
+ // src has changed, do not retry
2823
+ return;
2824
+ }
2825
+ imageRef.current.removeAttribute('src');
2826
+ imageRef.current.setAttribute('src', newSrc);
2827
+ }, timeout);
2828
+ }, []);
2829
+ const didGetError = useCallback((e) => {
2830
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
2831
+ if (!errors.current) {
2832
+ return;
2833
+ }
2834
+ errors.current[(_a = imageRef.current) === null || _a === void 0 ? void 0 : _a.src] =
2835
+ ((_c = errors.current[(_b = imageRef.current) === null || _b === void 0 ? void 0 : _b.src]) !== null && _c !== void 0 ? _c : 0) + 1;
2836
+ if (onError &&
2837
+ ((_e = errors.current[(_d = imageRef.current) === null || _d === void 0 ? void 0 : _d.src]) !== null && _e !== void 0 ? _e : 0) > maxRetries) {
2838
+ onError(e);
2839
+ return;
2840
+ }
2841
+ if (((_g = errors.current[(_f = imageRef.current) === null || _f === void 0 ? void 0 : _f.src]) !== null && _g !== void 0 ? _g : 0) <= maxRetries) {
2842
+ const backoff = exponentialBackoff((_j = errors.current[(_h = imageRef.current) === null || _h === void 0 ? void 0 : _h.src]) !== null && _j !== void 0 ? _j : 0);
2843
+ console.warn(`Could not load image with source ${(_k = imageRef.current) === null || _k === void 0 ? void 0 : _k.src}, retrying again in ${backoff}ms`);
2844
+ retryIn(backoff);
2845
+ return;
2846
+ }
2847
+ cancelRender('Error loading image with src: ' + ((_l = imageRef.current) === null || _l === void 0 ? void 0 : _l.src));
2848
+ }, [maxRetries, onError, retryIn]);
2849
+ if (typeof window !== 'undefined') {
2850
+ // eslint-disable-next-line react-hooks/rules-of-hooks
2851
+ useLayoutEffect(() => {
2852
+ if (process.env.NODE_ENV === 'test') {
2853
+ return;
2854
+ }
2855
+ const newHandle = delayRender('Loading <Img> with src=' + src);
2856
+ const { current } = imageRef;
2857
+ const onComplete = () => {
2858
+ var _a, _b, _c, _d;
2859
+ if (((_b = errors.current[(_a = imageRef.current) === null || _a === void 0 ? void 0 : _a.src]) !== null && _b !== void 0 ? _b : 0) > 0) {
2860
+ delete errors.current[(_c = imageRef.current) === null || _c === void 0 ? void 0 : _c.src];
2861
+ console.info(`Retry successful - ${(_d = imageRef.current) === null || _d === void 0 ? void 0 : _d.src} is now loaded`);
2862
+ }
2863
+ continueRender(newHandle);
2864
+ };
2865
+ const didLoad = () => {
2866
+ onComplete();
2867
+ };
2868
+ if (current === null || current === void 0 ? void 0 : current.complete) {
2869
+ onComplete();
2870
+ }
2871
+ else {
2872
+ current === null || current === void 0 ? void 0 : current.addEventListener('load', didLoad, { once: true });
2873
+ }
2874
+ // If tag gets unmounted, clear pending handles because image is not going to load
2875
+ return () => {
2876
+ current === null || current === void 0 ? void 0 : current.removeEventListener('load', didLoad);
2877
+ continueRender(newHandle);
2878
+ };
2879
+ }, [src]);
2880
+ }
2881
+ return (jsx("img", { ...props, ref: imageRef, src: actualSrc, onError: didGetError }));
2882
+ };
2883
+ /**
2884
+ * @description Works just like a regular HTML img tag. When you use the <Img> tag, Remotion will ensure that the image is loaded before rendering the frame.
2885
+ * @see [Documentation](https://www.remotion.dev/docs/img)
2886
+ */
2887
+ const Img = forwardRef(ImgRefForwarding);
2888
+
2889
+ const compositionsRef = React.createRef();
2890
+ const CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
2891
+ var _a;
2892
+ // Wontfix, expected to have
2893
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2894
+ const [compositions, setCompositions] = useState([]);
2895
+ const currentcompositionsRef = useRef(compositions);
2896
+ const [currentComposition, setCurrentComposition] = useState(null);
2897
+ const [folders, setFolders] = useState([]);
2898
+ const [currentCompositionMetadata, setCurrentCompositionMetadata] = useState(null);
2899
+ const updateCompositions = useCallback((
2900
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2901
+ updateComps) => {
2902
+ setCompositions((comps) => {
2903
+ const updated = updateComps(comps);
2904
+ currentcompositionsRef.current = updated;
2905
+ return updated;
2906
+ });
2907
+ }, []);
2908
+ const registerComposition = useCallback((comp) => {
2909
+ updateCompositions((comps) => {
2910
+ if (comps.find((c) => c.id === comp.id)) {
2911
+ throw new Error(`Multiple composition with id ${comp.id} are registered.`);
2912
+ }
2913
+ const value = [...comps, comp]
2914
+ .slice()
2915
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2916
+ .sort((a, b) => a.nonce - b.nonce);
2917
+ return value;
2918
+ });
2919
+ }, [updateCompositions]);
2920
+ const unregisterComposition = useCallback((id) => {
2921
+ setCompositions((comps) => {
2922
+ return comps.filter((c) => c.id !== id);
2923
+ });
2924
+ }, []);
2925
+ const registerFolder = useCallback((name, parent) => {
2926
+ setFolders((prevFolders) => {
2927
+ return [
2928
+ ...prevFolders,
2929
+ {
2930
+ name,
2931
+ parent,
2932
+ },
2933
+ ];
2934
+ });
2935
+ }, []);
2936
+ const unregisterFolder = useCallback((name, parent) => {
2937
+ setFolders((prevFolders) => {
2938
+ return prevFolders.filter((p) => !(p.name === name && p.parent === parent));
2939
+ });
2940
+ }, []);
2941
+ useImperativeHandle(compositionsRef, () => {
2942
+ return {
2943
+ getCompositions: () => currentcompositionsRef.current,
2944
+ };
2945
+ }, []);
2946
+ const composition = compositions.find((c) => c.id === currentComposition);
2947
+ const contextValue = useMemo(() => {
2948
+ return {
2949
+ compositions,
2950
+ registerComposition,
2951
+ unregisterComposition,
2952
+ currentComposition,
2953
+ setCurrentComposition,
2954
+ folders,
2955
+ registerFolder,
2956
+ unregisterFolder,
2957
+ currentCompositionMetadata,
2958
+ setCurrentCompositionMetadata,
2959
+ };
2960
+ }, [
2961
+ compositions,
2962
+ registerComposition,
2963
+ unregisterComposition,
2964
+ currentComposition,
2965
+ folders,
2966
+ registerFolder,
2967
+ unregisterFolder,
2968
+ currentCompositionMetadata,
2969
+ ]);
2970
+ return (jsx(CompositionManager.Provider, { value: contextValue, children: jsx(SequenceManagerProvider, { children: jsx(AssetManagerProvider, { children: jsx(ResolveCompositionConfig, { children: jsx(SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, component: (_a = composition === null || composition === void 0 ? void 0 : composition.component) !== null && _a !== void 0 ? _a : null, children: children }) }) }) }) }));
2971
+ };
2972
+
2973
+ const injected = {};
2974
+ const injectCSS = (css) => {
2975
+ // Skip in node
2976
+ if (typeof document === 'undefined') {
2977
+ return;
2978
+ }
2979
+ if (injected[css]) {
2980
+ return;
2981
+ }
2982
+ const head = document.head || document.getElementsByTagName('head')[0];
2983
+ const style = document.createElement('style');
2984
+ style.appendChild(document.createTextNode(css));
2985
+ head.prepend(style);
2986
+ injected[css] = true;
2987
+ };
2988
+ const OFFTHREAD_VIDEO_CLASS_NAME = '__remotion_offthreadvideo';
2989
+ const makeDefaultCSS = (scope, backgroundColor) => {
2990
+ if (!scope) {
2991
+ return `
2992
+ * {
2993
+ box-sizing: border-box;
2994
+ }
2995
+ body {
2996
+ margin: 0;
2997
+ background-color: ${backgroundColor};
2998
+ }
2999
+ .${OFFTHREAD_VIDEO_CLASS_NAME} {
3000
+ object-fit: contain;
3001
+ }
3002
+ `;
3003
+ }
3004
+ return `
3005
+ ${scope} * {
3006
+ box-sizing: border-box;
3007
+ }
3008
+ ${scope} *:-webkit-full-screen {
3009
+ width: 100%;
3010
+ height: 100%;
3011
+ }
3012
+ ${scope} .${OFFTHREAD_VIDEO_CLASS_NAME} {
3013
+ object-fit: contain;
3014
+ }
3015
+ `;
3016
+ };
3017
+
3018
+ var CSSUtils = /*#__PURE__*/Object.freeze({
3019
+ __proto__: null,
3020
+ injectCSS: injectCSS,
3021
+ OFFTHREAD_VIDEO_CLASS_NAME: OFFTHREAD_VIDEO_CLASS_NAME,
3022
+ makeDefaultCSS: makeDefaultCSS
3023
+ });
3024
+
3025
+ const REMOTION_STUDIO_CONTAINER_ELEMENT = '__remotion-studio-container';
3026
+ const getPreviewDomElement = () => {
3027
+ return document.getElementById(REMOTION_STUDIO_CONTAINER_ELEMENT);
3028
+ };
3029
+
3030
+ /**
3031
+ * Copied from:
3032
+ * https://github.com/software-mansion/react-native-reanimated/blob/master/src/reanimated2/Colors.ts
3033
+ */
3034
+ // var INTEGER = '[-+]?\\d+';
3035
+ const NUMBER = '[-+]?\\d*\\.?\\d+';
3036
+ const PERCENTAGE = NUMBER + '%';
3037
+ function call(...args) {
3038
+ return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)';
3039
+ }
3040
+ function getMatchers() {
3041
+ const cachedMatchers = {
3042
+ rgb: undefined,
3043
+ rgba: undefined,
3044
+ hsl: undefined,
3045
+ hsla: undefined,
3046
+ hex3: undefined,
3047
+ hex4: undefined,
3048
+ hex5: undefined,
3049
+ hex6: undefined,
3050
+ hex8: undefined,
3051
+ };
3052
+ if (cachedMatchers.rgb === undefined) {
3053
+ cachedMatchers.rgb = new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER));
3054
+ cachedMatchers.rgba = new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER));
3055
+ cachedMatchers.hsl = new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE));
3056
+ cachedMatchers.hsla = new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER));
3057
+ cachedMatchers.hex3 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
3058
+ cachedMatchers.hex4 =
3059
+ /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
3060
+ cachedMatchers.hex6 = /^#([0-9a-fA-F]{6})$/;
3061
+ cachedMatchers.hex8 = /^#([0-9a-fA-F]{8})$/;
3062
+ }
3063
+ return cachedMatchers;
3064
+ }
3065
+ function hue2rgb(p, q, t) {
3066
+ if (t < 0) {
3067
+ t += 1;
3068
+ }
3069
+ if (t > 1) {
3070
+ t -= 1;
3071
+ }
3072
+ if (t < 1 / 6) {
3073
+ return p + (q - p) * 6 * t;
3074
+ }
3075
+ if (t < 1 / 2) {
3076
+ return q;
3077
+ }
3078
+ if (t < 2 / 3) {
3079
+ return p + (q - p) * (2 / 3 - t) * 6;
3080
+ }
3081
+ return p;
3082
+ }
3083
+ function hslToRgb(h, s, l) {
3084
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
3085
+ const p = 2 * l - q;
3086
+ const r = hue2rgb(p, q, h + 1 / 3);
3087
+ const g = hue2rgb(p, q, h);
3088
+ const b = hue2rgb(p, q, h - 1 / 3);
3089
+ return ((Math.round(r * 255) << 24) |
3090
+ (Math.round(g * 255) << 16) |
3091
+ (Math.round(b * 255) << 8));
3092
+ }
3093
+ function parse255(str) {
3094
+ const int = Number.parseInt(str, 10);
3095
+ if (int < 0) {
3096
+ return 0;
3097
+ }
3098
+ if (int > 255) {
3099
+ return 255;
3100
+ }
3101
+ return int;
3102
+ }
3103
+ function parse360(str) {
3104
+ const int = Number.parseFloat(str);
3105
+ return (((int % 360) + 360) % 360) / 360;
3106
+ }
3107
+ function parse1(str) {
3108
+ const num = Number.parseFloat(str);
3109
+ if (num < 0) {
3110
+ return 0;
3111
+ }
3112
+ if (num > 1) {
3113
+ return 255;
3114
+ }
3115
+ return Math.round(num * 255);
3116
+ }
3117
+ function parsePercentage(str) {
3118
+ // parseFloat conveniently ignores the final %
3119
+ const int = Number.parseFloat(str);
3120
+ if (int < 0) {
3121
+ return 0;
3122
+ }
3123
+ if (int > 100) {
3124
+ return 1;
3125
+ }
3126
+ return int / 100;
3127
+ }
3128
+ const names = {
3129
+ transparent: 0x00000000,
3130
+ // http://www.w3.org/TR/css3-color/#svg-color
3131
+ aliceblue: 0xf0f8ffff,
3132
+ antiquewhite: 0xfaebd7ff,
3133
+ aqua: 0x00ffffff,
3134
+ aquamarine: 0x7fffd4ff,
3135
+ azure: 0xf0ffffff,
3136
+ beige: 0xf5f5dcff,
3137
+ bisque: 0xffe4c4ff,
3138
+ black: 0x000000ff,
3139
+ blanchedalmond: 0xffebcdff,
3140
+ blue: 0x0000ffff,
3141
+ blueviolet: 0x8a2be2ff,
3142
+ brown: 0xa52a2aff,
3143
+ burlywood: 0xdeb887ff,
3144
+ burntsienna: 0xea7e5dff,
3145
+ cadetblue: 0x5f9ea0ff,
3146
+ chartreuse: 0x7fff00ff,
3147
+ chocolate: 0xd2691eff,
3148
+ coral: 0xff7f50ff,
3149
+ cornflowerblue: 0x6495edff,
3150
+ cornsilk: 0xfff8dcff,
3151
+ crimson: 0xdc143cff,
3152
+ cyan: 0x00ffffff,
3153
+ darkblue: 0x00008bff,
3154
+ darkcyan: 0x008b8bff,
3155
+ darkgoldenrod: 0xb8860bff,
3156
+ darkgray: 0xa9a9a9ff,
3157
+ darkgreen: 0x006400ff,
3158
+ darkgrey: 0xa9a9a9ff,
3159
+ darkkhaki: 0xbdb76bff,
3160
+ darkmagenta: 0x8b008bff,
3161
+ darkolivegreen: 0x556b2fff,
3162
+ darkorange: 0xff8c00ff,
3163
+ darkorchid: 0x9932ccff,
3164
+ darkred: 0x8b0000ff,
3165
+ darksalmon: 0xe9967aff,
3166
+ darkseagreen: 0x8fbc8fff,
3167
+ darkslateblue: 0x483d8bff,
3168
+ darkslategray: 0x2f4f4fff,
3169
+ darkslategrey: 0x2f4f4fff,
3170
+ darkturquoise: 0x00ced1ff,
3171
+ darkviolet: 0x9400d3ff,
3172
+ deeppink: 0xff1493ff,
3173
+ deepskyblue: 0x00bfffff,
3174
+ dimgray: 0x696969ff,
3175
+ dimgrey: 0x696969ff,
3176
+ dodgerblue: 0x1e90ffff,
3177
+ firebrick: 0xb22222ff,
3178
+ floralwhite: 0xfffaf0ff,
3179
+ forestgreen: 0x228b22ff,
3180
+ fuchsia: 0xff00ffff,
3181
+ gainsboro: 0xdcdcdcff,
3182
+ ghostwhite: 0xf8f8ffff,
3183
+ gold: 0xffd700ff,
3184
+ goldenrod: 0xdaa520ff,
3185
+ gray: 0x808080ff,
3186
+ green: 0x008000ff,
3187
+ greenyellow: 0xadff2fff,
3188
+ grey: 0x808080ff,
3189
+ honeydew: 0xf0fff0ff,
3190
+ hotpink: 0xff69b4ff,
3191
+ indianred: 0xcd5c5cff,
3192
+ indigo: 0x4b0082ff,
3193
+ ivory: 0xfffff0ff,
3194
+ khaki: 0xf0e68cff,
3195
+ lavender: 0xe6e6faff,
3196
+ lavenderblush: 0xfff0f5ff,
3197
+ lawngreen: 0x7cfc00ff,
3198
+ lemonchiffon: 0xfffacdff,
3199
+ lightblue: 0xadd8e6ff,
3200
+ lightcoral: 0xf08080ff,
3201
+ lightcyan: 0xe0ffffff,
3202
+ lightgoldenrodyellow: 0xfafad2ff,
3203
+ lightgray: 0xd3d3d3ff,
3204
+ lightgreen: 0x90ee90ff,
3205
+ lightgrey: 0xd3d3d3ff,
3206
+ lightpink: 0xffb6c1ff,
3207
+ lightsalmon: 0xffa07aff,
3208
+ lightseagreen: 0x20b2aaff,
3209
+ lightskyblue: 0x87cefaff,
3210
+ lightslategray: 0x778899ff,
3211
+ lightslategrey: 0x778899ff,
3212
+ lightsteelblue: 0xb0c4deff,
3213
+ lightyellow: 0xffffe0ff,
3214
+ lime: 0x00ff00ff,
3215
+ limegreen: 0x32cd32ff,
3216
+ linen: 0xfaf0e6ff,
3217
+ magenta: 0xff00ffff,
3218
+ maroon: 0x800000ff,
3219
+ mediumaquamarine: 0x66cdaaff,
3220
+ mediumblue: 0x0000cdff,
3221
+ mediumorchid: 0xba55d3ff,
3222
+ mediumpurple: 0x9370dbff,
3223
+ mediumseagreen: 0x3cb371ff,
3224
+ mediumslateblue: 0x7b68eeff,
3225
+ mediumspringgreen: 0x00fa9aff,
3226
+ mediumturquoise: 0x48d1ccff,
3227
+ mediumvioletred: 0xc71585ff,
3228
+ midnightblue: 0x191970ff,
3229
+ mintcream: 0xf5fffaff,
3230
+ mistyrose: 0xffe4e1ff,
3231
+ moccasin: 0xffe4b5ff,
3232
+ navajowhite: 0xffdeadff,
3233
+ navy: 0x000080ff,
3234
+ oldlace: 0xfdf5e6ff,
3235
+ olive: 0x808000ff,
3236
+ olivedrab: 0x6b8e23ff,
3237
+ orange: 0xffa500ff,
3238
+ orangered: 0xff4500ff,
3239
+ orchid: 0xda70d6ff,
3240
+ palegoldenrod: 0xeee8aaff,
3241
+ palegreen: 0x98fb98ff,
3242
+ paleturquoise: 0xafeeeeff,
3243
+ palevioletred: 0xdb7093ff,
3244
+ papayawhip: 0xffefd5ff,
3245
+ peachpuff: 0xffdab9ff,
3246
+ peru: 0xcd853fff,
3247
+ pink: 0xffc0cbff,
3248
+ plum: 0xdda0ddff,
3249
+ powderblue: 0xb0e0e6ff,
3250
+ purple: 0x800080ff,
3251
+ rebeccapurple: 0x663399ff,
3252
+ red: 0xff0000ff,
3253
+ rosybrown: 0xbc8f8fff,
3254
+ royalblue: 0x4169e1ff,
3255
+ saddlebrown: 0x8b4513ff,
3256
+ salmon: 0xfa8072ff,
3257
+ sandybrown: 0xf4a460ff,
3258
+ seagreen: 0x2e8b57ff,
3259
+ seashell: 0xfff5eeff,
3260
+ sienna: 0xa0522dff,
3261
+ silver: 0xc0c0c0ff,
3262
+ skyblue: 0x87ceebff,
3263
+ slateblue: 0x6a5acdff,
3264
+ slategray: 0x708090ff,
3265
+ slategrey: 0x708090ff,
3266
+ snow: 0xfffafaff,
3267
+ springgreen: 0x00ff7fff,
3268
+ steelblue: 0x4682b4ff,
3269
+ tan: 0xd2b48cff,
3270
+ teal: 0x008080ff,
3271
+ thistle: 0xd8bfd8ff,
3272
+ tomato: 0xff6347ff,
3273
+ turquoise: 0x40e0d0ff,
3274
+ violet: 0xee82eeff,
3275
+ wheat: 0xf5deb3ff,
3276
+ white: 0xffffffff,
3277
+ whitesmoke: 0xf5f5f5ff,
3278
+ yellow: 0xffff00ff,
3279
+ yellowgreen: 0x9acd32ff,
3280
+ };
3281
+ function normalizeColor(color) {
3282
+ const matchers = getMatchers();
3283
+ let match;
3284
+ // Ordered based on occurrences on Facebook codebase
3285
+ if (matchers.hex6) {
3286
+ if ((match = matchers.hex6.exec(color))) {
3287
+ return Number.parseInt(match[1] + 'ff', 16) >>> 0;
3288
+ }
3289
+ }
3290
+ if (names[color] !== undefined) {
3291
+ return names[color];
3292
+ }
3293
+ if (matchers.rgb) {
3294
+ if ((match = matchers.rgb.exec(color))) {
3295
+ return (
3296
+ // b
3297
+ ((parse255(match[1]) << 24) | // r
3298
+ (parse255(match[2]) << 16) | // g
3299
+ (parse255(match[3]) << 8) |
3300
+ 0x000000ff) >>> // a
3301
+ 0);
3302
+ }
3303
+ }
3304
+ if (matchers.rgba) {
3305
+ if ((match = matchers.rgba.exec(color))) {
3306
+ return (
3307
+ // b
3308
+ ((parse255(match[1]) << 24) | // r
3309
+ (parse255(match[2]) << 16) | // g
3310
+ (parse255(match[3]) << 8) |
3311
+ parse1(match[4])) >>> // a
3312
+ 0);
3313
+ }
3314
+ }
3315
+ if (matchers.hex3) {
3316
+ if ((match = matchers.hex3.exec(color))) {
3317
+ return (Number.parseInt(match[1] +
3318
+ match[1] + // r
3319
+ match[2] +
3320
+ match[2] + // g
3321
+ match[3] +
3322
+ match[3] + // b
3323
+ 'ff', // a
3324
+ 16) >>> 0);
3325
+ }
3326
+ }
3327
+ // https://drafts.csswg.org/css-color-4/#hex-notation
3328
+ if (matchers.hex8) {
3329
+ if ((match = matchers.hex8.exec(color))) {
3330
+ return Number.parseInt(match[1], 16) >>> 0;
3331
+ }
3332
+ }
3333
+ if (matchers.hex4) {
3334
+ if ((match = matchers.hex4.exec(color))) {
3335
+ return (Number.parseInt(match[1] +
3336
+ match[1] + // r
3337
+ match[2] +
3338
+ match[2] + // g
3339
+ match[3] +
3340
+ match[3] + // b
3341
+ match[4] +
3342
+ match[4], // a
3343
+ 16) >>> 0);
3344
+ }
3345
+ }
3346
+ if (matchers.hsl) {
3347
+ if ((match = matchers.hsl.exec(color))) {
3348
+ return ((hslToRgb(parse360(match[1]), // h
3349
+ parsePercentage(match[2]), // s
3350
+ parsePercentage(match[3]) // l
3351
+ ) |
3352
+ 0x000000ff) >>> // a
3353
+ 0);
3354
+ }
3355
+ }
3356
+ if (matchers.hsla) {
3357
+ if ((match = matchers.hsla.exec(color))) {
3358
+ return ((hslToRgb(parse360(match[1]), // h
3359
+ parsePercentage(match[2]), // s
3360
+ parsePercentage(match[3]) // l
3361
+ ) |
3362
+ parse1(match[4])) >>> // a
3363
+ 0);
3364
+ }
3365
+ }
3366
+ throw new Error(`invalid color string ${color} provided`);
3367
+ }
3368
+ const opacity = (c) => {
3369
+ return ((c >> 24) & 255) / 255;
3370
+ };
3371
+ const red = (c) => {
3372
+ return (c >> 16) & 255;
3373
+ };
3374
+ const green = (c) => {
3375
+ return (c >> 8) & 255;
3376
+ };
3377
+ const blue = (c) => {
3378
+ return c & 255;
3379
+ };
3380
+ const rgbaColor = (r, g, b, alpha) => {
3381
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
3382
+ };
3383
+ function processColor(color) {
3384
+ const normalizedColor = normalizeColor(color);
3385
+ return ((normalizedColor << 24) | (normalizedColor >>> 8)) >>> 0; // argb
3386
+ }
3387
+ const interpolateColorsRGB = (value, inputRange, colors) => {
3388
+ const [r, g, b, a] = [red, green, blue, opacity].map((f) => {
3389
+ const unrounded = interpolate(value, inputRange, colors.map((c) => f(c)), {
3390
+ extrapolateLeft: 'clamp',
3391
+ extrapolateRight: 'clamp',
3392
+ });
3393
+ if (f === opacity) {
3394
+ return Number(unrounded.toFixed(3));
3395
+ }
3396
+ return Math.round(unrounded);
3397
+ });
3398
+ return rgbaColor(r, g, b, a);
3399
+ };
3400
+ /**
3401
+ * @description This function allows you to map a range of values to colors using a concise syntax.
3402
+ * @see [Documentation](https://www.remotion.dev/docs/interpolate-colors)
3403
+ */
3404
+ const interpolateColors = (input, inputRange, outputRange) => {
3405
+ if (typeof input === 'undefined') {
3406
+ throw new TypeError('input can not be undefined');
3407
+ }
3408
+ if (typeof inputRange === 'undefined') {
3409
+ throw new TypeError('inputRange can not be undefined');
3410
+ }
3411
+ if (typeof outputRange === 'undefined') {
3412
+ throw new TypeError('outputRange can not be undefined');
3413
+ }
3414
+ if (inputRange.length !== outputRange.length) {
3415
+ throw new TypeError('inputRange (' +
3416
+ inputRange.length +
3417
+ ' values provided) and outputRange (' +
3418
+ outputRange.length +
3419
+ ' values provided) must have the same length');
3420
+ }
3421
+ const processedOutputRange = outputRange.map((c) => processColor(c));
3422
+ return interpolateColorsRGB(input, inputRange, processedOutputRange);
3423
+ };
3424
+
3425
+ let Root = null;
3426
+ let listeners = [];
3427
+ /**
3428
+ * @description This function registers the root component of the Remotion project
3429
+ * @see [Documentation](https://www.remotion.dev/docs/register-root)
3430
+ */
3431
+ const registerRoot = (comp) => {
3432
+ if (!comp) {
3433
+ throw new Error(`You must pass a React component to registerRoot(), but ${JSON.stringify(comp)} was passed.`);
3434
+ }
3435
+ if (Root) {
3436
+ throw new Error('registerRoot() was called more than once.');
3437
+ }
3438
+ Root = comp;
3439
+ listeners.forEach((l) => {
3440
+ l(comp);
3441
+ });
3442
+ };
3443
+ const getRoot = () => {
3444
+ return Root;
3445
+ };
3446
+ const waitForRoot = (fn) => {
3447
+ if (Root) {
3448
+ fn(Root);
3449
+ return () => undefined;
3450
+ }
3451
+ listeners.push(fn);
3452
+ return () => {
3453
+ listeners = listeners.filter((l) => l !== fn);
3454
+ };
3455
+ };
3456
+
3457
+ const RemotionRoot = ({ children, numberOfAudioTags }) => {
3458
+ var _a;
3459
+ const [remotionRootId] = useState(() => String(random(null)));
3460
+ const [frame, setFrame] = useState((_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0);
3461
+ const [playing, setPlaying] = useState(false);
3462
+ const imperativePlaying = useRef(false);
3463
+ const [fastRefreshes, setFastRefreshes] = useState(0);
3464
+ const [playbackRate, setPlaybackRate] = useState(1);
3465
+ const audioAndVideoTags = useRef([]);
3466
+ if (typeof window !== 'undefined') {
3467
+ // eslint-disable-next-line react-hooks/rules-of-hooks
3468
+ useLayoutEffect(() => {
3469
+ window.remotion_setFrame = (f) => {
3470
+ const id = delayRender(`Setting the current frame to ${f}`);
3471
+ setFrame(f);
3472
+ requestAnimationFrame(() => continueRender(id));
3473
+ };
3474
+ window.remotion_isPlayer = false;
3475
+ }, []);
3476
+ }
3477
+ const timelineContextValue = useMemo(() => {
3478
+ return {
3479
+ frame,
3480
+ playing,
3481
+ imperativePlaying,
3482
+ rootId: remotionRootId,
3483
+ playbackRate,
3484
+ setPlaybackRate,
3485
+ audioAndVideoTags,
3486
+ };
3487
+ }, [frame, playbackRate, playing, remotionRootId]);
3488
+ const setTimelineContextValue = useMemo(() => {
3489
+ return {
3490
+ setFrame,
3491
+ setPlaying,
3492
+ };
3493
+ }, []);
3494
+ const nonceContext = useMemo(() => {
3495
+ let counter = 0;
3496
+ return {
3497
+ getNonce: () => counter++,
3498
+ fastRefreshes,
3499
+ };
3500
+ }, [fastRefreshes]);
3501
+ useEffect(() => {
3502
+ if (typeof __webpack_module__ !== 'undefined') {
3503
+ if (__webpack_module__.hot) {
3504
+ __webpack_module__.hot.addStatusHandler((status) => {
3505
+ if (status === 'idle') {
3506
+ setFastRefreshes((i) => i + 1);
3507
+ }
3508
+ });
3509
+ }
3510
+ }
3511
+ }, []);
3512
+ return (jsx(NonceContext.Provider, { value: nonceContext, children: jsx(TimelineContext.Provider, { value: timelineContextValue, children: jsx(SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx(EditorPropsProvider, { children: jsx(PrefetchProvider, { children: jsx(NativeLayersProvider, { children: jsx(CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: jsx(DurationsContextProvider, { children: children }) }) }) }) }) }) }) }));
3513
+ };
3514
+
3515
+ const getEnvVariables = () => {
3516
+ if (getRemotionEnvironment() === 'rendering') {
3517
+ const param = window.remotion_envVariables;
3518
+ if (!param) {
3519
+ return {};
3520
+ }
3521
+ return { ...JSON.parse(param), NODE_ENV: process.env.NODE_ENV };
3522
+ }
3523
+ if (getRemotionEnvironment() === 'preview') {
3524
+ // For the Preview, we already set the environment variables in index-html.ts.
3525
+ // We just add NODE_ENV here.
3526
+ return {
3527
+ NODE_ENV: 'development',
3528
+ };
3529
+ }
3530
+ throw new Error('Can only call getEnvVariables() if environment is `rendering` or `preview`');
3531
+ };
3532
+ const setupEnvVariables = () => {
3533
+ const env = getEnvVariables();
3534
+ if (!window.process) {
3535
+ window.process = {};
3536
+ }
3537
+ if (!window.process.env) {
3538
+ window.process.env = {};
3539
+ }
3540
+ Object.keys(env).forEach((key) => {
3541
+ window.process.env[key] = env[key];
3542
+ });
3543
+ };
3544
+
3545
+ const validateFrame = ({ allowFloats, durationInFrames, frame, }) => {
3546
+ if (typeof frame === 'undefined') {
3547
+ throw new TypeError(`Argument missing for parameter "frame"`);
3548
+ }
3549
+ if (typeof frame !== 'number') {
3550
+ throw new TypeError(`Argument passed for "frame" is not a number: ${frame}`);
3551
+ }
3552
+ if (!Number.isFinite(frame)) {
3553
+ throw new RangeError(`Frame ${frame} is not finite`);
3554
+ }
3555
+ if (frame % 1 !== 0 && !allowFloats) {
3556
+ throw new RangeError(`Argument for frame must be an integer, but got ${frame}`);
3557
+ }
3558
+ if (frame < 0 && frame < -durationInFrames) {
3559
+ throw new RangeError(`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the lowest frame that can be rendered is ${-durationInFrames}`);
3560
+ }
3561
+ if (frame > durationInFrames - 1) {
3562
+ throw new RangeError(`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the highest frame that can be rendered is ${durationInFrames - 1}`);
3563
+ }
3564
+ };
3565
+
3566
+ function useRemotionContexts() {
3567
+ const compositionManagerCtx = React.useContext(CompositionManager);
3568
+ const timelineContext = React.useContext(TimelineContext);
3569
+ const setTimelineContext = React.useContext(SetTimelineContext);
3570
+ const sequenceContext = React.useContext(SequenceContext);
3571
+ const nonceContext = React.useContext(NonceContext);
3572
+ const canUseRemotionHooksContext = React.useContext(CanUseRemotionHooks);
3573
+ const nativeLayersContext = React.useContext(NativeLayersContext);
3574
+ const preloadContext = React.useContext(PreloadContext);
3575
+ const resolveCompositionContext = React.useContext(ResolveCompositionContext);
3576
+ const assetManagerContext = React.useContext(AssetManager);
3577
+ const sequenceManagerContext = React.useContext(SequenceManager);
3578
+ return useMemo(() => ({
3579
+ compositionManagerCtx,
3580
+ timelineContext,
3581
+ setTimelineContext,
3582
+ sequenceContext,
3583
+ nonceContext,
3584
+ canUseRemotionHooksContext,
3585
+ nativeLayersContext,
3586
+ preloadContext,
3587
+ resolveCompositionContext,
3588
+ assetManagerContext,
3589
+ sequenceManagerContext,
3590
+ }), [
3591
+ compositionManagerCtx,
3592
+ nonceContext,
3593
+ sequenceContext,
3594
+ setTimelineContext,
3595
+ timelineContext,
3596
+ canUseRemotionHooksContext,
3597
+ nativeLayersContext,
3598
+ preloadContext,
3599
+ resolveCompositionContext,
3600
+ assetManagerContext,
3601
+ sequenceManagerContext,
3602
+ ]);
3603
+ }
3604
+ const RemotionContextProvider = (props) => {
3605
+ const { children, contexts } = props;
3606
+ return (jsx(CanUseRemotionHooks.Provider, { value: contexts.canUseRemotionHooksContext, children: jsx(NonceContext.Provider, { value: contexts.nonceContext, children: jsx(NativeLayersContext.Provider, { value: contexts.nativeLayersContext, children: jsx(PreloadContext.Provider, { value: contexts.preloadContext, children: jsx(CompositionManager.Provider, { value: contexts.compositionManagerCtx, children: jsx(SequenceManager.Provider, { value: contexts.sequenceManagerContext, children: jsx(AssetManager.Provider, { value: contexts.assetManagerContext, children: jsx(ResolveCompositionContext.Provider, { value: contexts.resolveCompositionContext, children: jsx(TimelineContext.Provider, { value: contexts.timelineContext, children: jsx(SetTimelineContext.Provider, { value: contexts.setTimelineContext, children: jsx(SequenceContext.Provider, { value: contexts.sequenceContext, children: children }) }) }) }) }) }) }) }) }) }) }));
3607
+ };
3608
+
3609
+ const Timeline = TimelinePosition;
3610
+ // Mark them as Internals so use don't assume this is public
3611
+ // API and are less likely to use it
3612
+ const Internals = {
3613
+ useUnsafeVideoConfig,
3614
+ Timeline,
3615
+ CompositionManager,
3616
+ SequenceManager,
3617
+ RemotionRoot,
3618
+ useVideo,
3619
+ getRoot,
3620
+ useMediaVolumeState,
3621
+ useMediaMutedState,
3622
+ useLazyComponent,
3623
+ truthy,
3624
+ SequenceContext,
3625
+ useRemotionContexts,
3626
+ RemotionContextProvider,
3627
+ CSSUtils,
3628
+ setupEnvVariables,
3629
+ MediaVolumeContext,
3630
+ SetMediaVolumeContext,
3631
+ validateDurationInFrames,
3632
+ validateFps,
3633
+ validateDefaultAndInputProps,
3634
+ validateDimension,
3635
+ getRemotionEnvironment,
3636
+ SharedAudioContext,
3637
+ SharedAudioContextProvider,
3638
+ invalidCompositionErrorMessage,
3639
+ isCompositionIdValid,
3640
+ getPreviewDomElement,
3641
+ compositionsRef,
3642
+ DELAY_RENDER_CALLSTACK_TOKEN,
3643
+ portalNode,
3644
+ waitForRoot,
3645
+ CanUseRemotionHooksProvider,
3646
+ CanUseRemotionHooks,
3647
+ PrefetchProvider,
3648
+ DurationsContextProvider,
3649
+ IsPlayerContextProvider,
3650
+ useIsPlayer,
3651
+ useRemotionEnvironment,
3652
+ validateFrame,
3653
+ EditorPropsProvider,
3654
+ EditorPropsContext,
3655
+ usePreload,
3656
+ processColor,
3657
+ NonceContext,
3658
+ resolveVideoConfig,
3659
+ useResolvedVideoConfig,
3660
+ resolveCompositionsRef,
3661
+ ResolveCompositionConfig,
3662
+ REMOTION_STUDIO_CONTAINER_ELEMENT,
3663
+ AssetManager,
3664
+ bundleName: 'bundle.js',
3665
+ };
3666
+
3667
+ const flattenChildren = (children) => {
3668
+ const childrenArray = React.Children.toArray(children);
3669
+ return childrenArray.reduce((flatChildren, child) => {
3670
+ if (child.type === React.Fragment) {
3671
+ return flatChildren.concat(flattenChildren(child.props
3672
+ .children));
3673
+ }
3674
+ flatChildren.push(child);
3675
+ return flatChildren;
3676
+ }, []);
3677
+ };
3678
+
3679
+ const SeriesSequenceRefForwardingFunction = ({ children }, _ref) => {
3680
+ // Discard ref
3681
+ // eslint-disable-next-line react/jsx-no-useless-fragment
3682
+ return jsx(Fragment, { children: children });
3683
+ };
3684
+ const SeriesSequence = forwardRef(SeriesSequenceRefForwardingFunction);
3685
+ /**
3686
+ * @description with this component, you can easily stitch together scenes that should play sequentially after another.
3687
+ * @see [Documentation](https://www.remotion.dev/docs/series)
3688
+ */
3689
+ const Series = ({ children }) => {
3690
+ const childrenValue = useMemo(() => {
3691
+ let startFrame = 0;
3692
+ const flattenedChildren = flattenChildren(children);
3693
+ return Children.map(flattenedChildren, (child, i) => {
3694
+ var _a;
3695
+ const castedChild = child;
3696
+ if (typeof castedChild === 'string') {
3697
+ // Don't throw if it's just some accidential whitespace
3698
+ if (castedChild.trim() === '') {
3699
+ return null;
3700
+ }
3701
+ throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as it's children, but you passed a string "${castedChild}"`);
3702
+ }
3703
+ if (castedChild.type !== SeriesSequence) {
3704
+ throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as it's children, but got ${castedChild} instead`);
3705
+ }
3706
+ const debugInfo = `index = ${i}, duration = ${castedChild.props.durationInFrames}`;
3707
+ if (!(castedChild === null || castedChild === void 0 ? void 0 : castedChild.props.children)) {
3708
+ throw new TypeError(`A <Series.Sequence /> component (${debugInfo}) was detected to not have any children. Delete it to fix this error.`);
3709
+ }
3710
+ const durationInFramesProp = castedChild.props.durationInFrames;
3711
+ const { durationInFrames, children: _children, ...passedProps } = castedChild.props;
3712
+ if (i !== flattenedChildren.length - 1 ||
3713
+ durationInFramesProp !== Infinity) {
3714
+ validateDurationInFrames({
3715
+ durationInFrames: durationInFramesProp,
3716
+ component: `of a <Series.Sequence /> component`,
3717
+ allowFloats: true,
3718
+ });
3719
+ }
3720
+ const offset = (_a = castedChild.props.offset) !== null && _a !== void 0 ? _a : 0;
3721
+ if (Number.isNaN(offset)) {
3722
+ throw new TypeError(`The "offset" property of a <Series.Sequence /> must not be NaN, but got NaN (${debugInfo}).`);
3723
+ }
3724
+ if (!Number.isFinite(offset)) {
3725
+ throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
3726
+ }
3727
+ if (offset % 1 !== 0) {
3728
+ throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
3729
+ }
3730
+ const currentStartFrame = startFrame + offset;
3731
+ startFrame += durationInFramesProp + offset;
3732
+ return (jsx(Sequence, { from: currentStartFrame, durationInFrames: durationInFramesProp, ...passedProps, ref: castedChild.ref, children: child }));
3733
+ });
3734
+ }, [children]);
3735
+ /* eslint-disable react/jsx-no-useless-fragment */
3736
+ return jsx(Fragment, { children: childrenValue });
3737
+ };
3738
+ Series.Sequence = SeriesSequence;
3739
+
3740
+ const validateSpringDuration = (dur) => {
3741
+ if (typeof dur === 'undefined') {
3742
+ return;
3743
+ }
3744
+ if (typeof dur !== 'number') {
3745
+ throw new TypeError(`A "duration" of a spring must be a "number" but is "${typeof dur}"`);
3746
+ }
3747
+ if (Number.isNaN(dur)) {
3748
+ throw new TypeError('A "duration" of a spring is NaN, which it must not be');
3749
+ }
3750
+ if (!Number.isFinite(dur)) {
3751
+ throw new TypeError('A "duration" of a spring must be finite, but is ' + dur);
3752
+ }
3753
+ if (dur <= 0) {
3754
+ throw new TypeError('A "duration" of a spring must be positive, but is ' + dur);
3755
+ }
3756
+ };
3757
+
3758
+ const defaultSpringConfig = {
3759
+ damping: 10,
3760
+ mass: 1,
3761
+ stiffness: 100,
3762
+ overshootClamping: false,
3763
+ };
3764
+ const advanceCache = {};
3765
+ function advance({ animation, now, config, }) {
3766
+ const { toValue, lastTimestamp, current, velocity } = animation;
3767
+ const deltaTime = Math.min(now - lastTimestamp, 64);
3768
+ const c = config.damping;
3769
+ const m = config.mass;
3770
+ const k = config.stiffness;
3771
+ const cacheKey = [
3772
+ toValue,
3773
+ lastTimestamp,
3774
+ current,
3775
+ velocity,
3776
+ c,
3777
+ m,
3778
+ k,
3779
+ now,
3780
+ ].join('-');
3781
+ if (advanceCache[cacheKey]) {
3782
+ return advanceCache[cacheKey];
3783
+ }
3784
+ const v0 = -velocity;
3785
+ const x0 = toValue - current;
3786
+ const zeta = c / (2 * Math.sqrt(k * m)); // damping ratio
3787
+ const omega0 = Math.sqrt(k / m); // undamped angular frequency of the oscillator (rad/ms)
3788
+ const omega1 = omega0 * Math.sqrt(1 - zeta ** 2); // exponential decay
3789
+ const t = deltaTime / 1000;
3790
+ const sin1 = Math.sin(omega1 * t);
3791
+ const cos1 = Math.cos(omega1 * t);
3792
+ // under damped
3793
+ const underDampedEnvelope = Math.exp(-zeta * omega0 * t);
3794
+ const underDampedFrag1 = underDampedEnvelope *
3795
+ (sin1 * ((v0 + zeta * omega0 * x0) / omega1) + x0 * cos1);
3796
+ const underDampedPosition = toValue - underDampedFrag1;
3797
+ // This looks crazy -- it's actually just the derivative of the oscillation function
3798
+ const underDampedVelocity = zeta * omega0 * underDampedFrag1 -
3799
+ underDampedEnvelope *
3800
+ (cos1 * (v0 + zeta * omega0 * x0) - omega1 * x0 * sin1);
3801
+ // critically damped
3802
+ const criticallyDampedEnvelope = Math.exp(-omega0 * t);
3803
+ const criticallyDampedPosition = toValue - criticallyDampedEnvelope * (x0 + (v0 + omega0 * x0) * t);
3804
+ const criticallyDampedVelocity = criticallyDampedEnvelope *
3805
+ (v0 * (t * omega0 - 1) + t * x0 * omega0 * omega0);
3806
+ const animationNode = {
3807
+ toValue,
3808
+ prevPosition: current,
3809
+ lastTimestamp: now,
3810
+ current: zeta < 1 ? underDampedPosition : criticallyDampedPosition,
3811
+ velocity: zeta < 1 ? underDampedVelocity : criticallyDampedVelocity,
3812
+ };
3813
+ advanceCache[cacheKey] = animationNode;
3814
+ return animationNode;
3815
+ }
3816
+ const calculationCache = {};
3817
+ function springCalculation({ from = 0, to = 1, frame, fps, config = {}, }) {
3818
+ const cacheKey = [
3819
+ from,
3820
+ to,
3821
+ frame,
3822
+ fps,
3823
+ config.damping,
3824
+ config.mass,
3825
+ config.overshootClamping,
3826
+ config.stiffness,
3827
+ ].join('-');
3828
+ if (calculationCache[cacheKey]) {
3829
+ return calculationCache[cacheKey];
3830
+ }
3831
+ let animation = {
3832
+ lastTimestamp: 0,
3833
+ current: from,
3834
+ toValue: to,
3835
+ velocity: 0,
3836
+ prevPosition: 0,
3837
+ };
3838
+ const frameClamped = Math.max(0, frame);
3839
+ const unevenRest = frameClamped % 1;
3840
+ for (let f = 0; f <= Math.floor(frameClamped); f++) {
3841
+ if (f === Math.floor(frameClamped)) {
3842
+ f += unevenRest;
3843
+ }
3844
+ const time = (f / fps) * 1000;
3845
+ animation = advance({
3846
+ animation,
3847
+ now: time,
3848
+ config: {
3849
+ ...defaultSpringConfig,
3850
+ ...config,
3851
+ },
3852
+ });
3853
+ }
3854
+ calculationCache[cacheKey] = animation;
3855
+ return animation;
3856
+ }
3857
+
3858
+ /**
3859
+ * @description The function returns how long it takes for a spring animation to settle
3860
+ * @see [Documentation](https://www.remotion.dev/docs/measure-spring)
3861
+ */
3862
+ function measureSpring({ fps, config = {}, threshold = 0.005, from = 0, to = 1, }) {
3863
+ if (typeof threshold !== 'number') {
3864
+ throw new TypeError(`threshold must be a number, got ${threshold} of type ${typeof threshold}`);
3865
+ }
3866
+ if (threshold === 0) {
3867
+ return Infinity;
3868
+ }
3869
+ if (threshold === 1) {
3870
+ return 0;
3871
+ }
3872
+ if (isNaN(threshold)) {
3873
+ throw new TypeError('Threshold is NaN');
3874
+ }
3875
+ if (!Number.isFinite(threshold)) {
3876
+ throw new TypeError('Threshold is not finite');
3877
+ }
3878
+ if (threshold < 0) {
3879
+ throw new TypeError('Threshold is below 0');
3880
+ }
3881
+ validateFps(fps, 'to the measureSpring() function', false);
3882
+ const range = Math.abs(from - to);
3883
+ let frame = 0;
3884
+ let finishedFrame = 0;
3885
+ const calc = () => {
3886
+ return springCalculation({
3887
+ fps,
3888
+ frame,
3889
+ config,
3890
+ from,
3891
+ to,
3892
+ });
3893
+ };
3894
+ let animation = calc();
3895
+ const calcDifference = () => {
3896
+ return (Math.abs(animation.current - animation.toValue) /
3897
+ (range === 0 ? 1 : range));
3898
+ };
3899
+ let difference = calcDifference();
3900
+ while (difference >= threshold) {
3901
+ frame++;
3902
+ animation = calc();
3903
+ difference = calcDifference();
3904
+ }
3905
+ // Since spring is bouncy, just because it's under the threshold we
3906
+ // cannot be sure it's done. We need to animate further until it stays in the
3907
+ // threshold for, say, 20 frames.
3908
+ finishedFrame = frame;
3909
+ for (let i = 0; i < 20; i++) {
3910
+ frame++;
3911
+ animation = calc();
3912
+ difference = calcDifference();
3913
+ if (difference >= threshold) {
3914
+ i = 0;
3915
+ finishedFrame = frame + 1;
3916
+ }
3917
+ }
3918
+ return finishedFrame;
3919
+ }
3920
+
3921
+ /**
3922
+ * @description Calculates a position based on physical parameters, start and end value, and time.
3923
+ * @see [Documentation](https://www.remotion.dev/docs/spring)
3924
+ * @param {number} frame The current time value. Most of the time you want to pass in the return value of useCurrentFrame.
3925
+ * @param {number} fps The framerate at which the animation runs. Pass in the value obtained by `useVideoConfig()`.
3926
+ * @param {?boolean} reverse Whether the animation plays in reverse or not. Default `false`.
3927
+ * @param {?Object} config optional object that allows you to customize the physical properties of the animation.
3928
+ * @param {number} [config.mass=1] The weight of the spring. If you reduce the mass, the animation becomes faster!
3929
+ * @param {number} [config.damping=10] How hard the animation decelerates.
3930
+ * @param {number} [config.stiffness=100] Affects bounciness of the animation.
3931
+ * @param {boolean} [config.overshootClamping=false] Whether to prevent the animation going beyond the target value.
3932
+ * @param {?number} [config.from] The initial value of the animation. Default `0`
3933
+ * @param {?number} [config.to] The end value of the animation. Default `1`
3934
+ * @param {?number} [config.durationInFrames] Stretch the duration of an animation to a set value.. Default `undefined`
3935
+ * @param {?number} [config.durationThreshold] How close to the end the animation is considered to be done. Default `0.005`
3936
+ * @param {?number} [config.delay] Delay the animation for this amount of frames. Default `0`
3937
+ */
3938
+ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durationInFrames: passedDurationInFrames, durationRestThreshold, delay = 0, reverse = false, }) {
3939
+ validateSpringDuration(passedDurationInFrames);
3940
+ validateFrame({
3941
+ frame: passedFrame,
3942
+ durationInFrames: Infinity,
3943
+ allowFloats: true,
3944
+ });
3945
+ validateFps(fps, 'to spring()', false);
3946
+ const needsToCalculateNaturalDuration = reverse || typeof passedDurationInFrames !== 'undefined';
3947
+ const naturalDuration = needsToCalculateNaturalDuration
3948
+ ? measureSpring({
3949
+ fps,
3950
+ config,
3951
+ from,
3952
+ to,
3953
+ threshold: durationRestThreshold,
3954
+ })
3955
+ : undefined;
3956
+ const naturalDurationGetter = needsToCalculateNaturalDuration
3957
+ ? {
3958
+ get: () => naturalDuration,
3959
+ }
3960
+ : {
3961
+ get: () => {
3962
+ throw new Error('did not calculate natural duration, this is an error with Remotion. Please report');
3963
+ },
3964
+ };
3965
+ const frame = (reverse
3966
+ ? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
3967
+ : passedFrame) - delay;
3968
+ const spr = springCalculation({
3969
+ fps,
3970
+ frame: passedDurationInFrames === undefined
3971
+ ? frame
3972
+ : frame / (passedDurationInFrames / naturalDurationGetter.get()),
3973
+ config,
3974
+ from,
3975
+ to,
3976
+ });
3977
+ if (!config.overshootClamping) {
3978
+ return spr.current;
3979
+ }
3980
+ if (to >= from) {
3981
+ return Math.min(spr.current, to);
3982
+ }
3983
+ return Math.max(spr.current, to);
3984
+ }
3985
+
3986
+ const problematicCharacters = {
3987
+ '%3A': ':',
3988
+ '%2F': '/',
3989
+ '%3F': '?',
3990
+ '%23': '#',
3991
+ '%5B': '[',
3992
+ '%5D': ']',
3993
+ '%40': '@',
3994
+ '%21': '!',
3995
+ '%24': '$',
3996
+ '%26': '&',
3997
+ '%27': "'",
3998
+ '%28': '(',
3999
+ '%29': ')',
4000
+ '%2A': '*',
4001
+ '%2B': '+',
4002
+ '%2C': ',',
4003
+ '%3B': ';',
4004
+ };
4005
+ const didWarn = {};
4006
+ const warnOnce = (message) => {
4007
+ if (didWarn[message]) {
4008
+ return;
4009
+ }
4010
+ console.warn(message);
4011
+ didWarn[message] = true;
4012
+ };
4013
+ const includesHexOfUnsafeChar = (path) => {
4014
+ for (const key of Object.keys(problematicCharacters)) {
4015
+ if (path.includes(key)) {
4016
+ return { containsHex: true, hexCode: key };
4017
+ }
4018
+ }
4019
+ return { containsHex: false };
4020
+ };
4021
+ const trimLeadingSlash = (path) => {
4022
+ if (path.startsWith('/')) {
4023
+ return trimLeadingSlash(path.substring(1));
4024
+ }
4025
+ return path;
4026
+ };
4027
+ const inner = (path) => {
4028
+ if (typeof window !== 'undefined' && window.remotion_staticBase) {
4029
+ return `${window.remotion_staticBase}/${trimLeadingSlash(path)}`;
4030
+ }
4031
+ return `/${trimLeadingSlash(path)}`;
4032
+ };
4033
+ /**
4034
+ * @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
4035
+ * @see [Documentation](https://www.remotion.dev/docs/staticfile)
4036
+ */
4037
+ const staticFile = (path) => {
4038
+ if (path.startsWith('http://') || path.startsWith('https://')) {
4039
+ throw new TypeError(`staticFile() does not support remote URLs - got "${path}". Instead, pass the URL without wrapping it in staticFile(). See: https://remotion.dev/docs/staticfile-remote-urls`);
4040
+ }
4041
+ if (path.startsWith('..') || path.startsWith('./')) {
4042
+ throw new TypeError(`staticFile() does not support relative paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
4043
+ }
4044
+ if (path.startsWith('/Users') ||
4045
+ path.startsWith('/home') ||
4046
+ path.startsWith('/tmp') ||
4047
+ path.startsWith('/etc') ||
4048
+ path.startsWith('/opt') ||
4049
+ path.startsWith('/var') ||
4050
+ path.startsWith('C:') ||
4051
+ path.startsWith('D:') ||
4052
+ path.startsWith('E:')) {
4053
+ throw new TypeError(`staticFile() does not support absolute paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
4054
+ }
4055
+ if (path.startsWith('public/')) {
4056
+ throw new TypeError(`Do not include the public/ prefix when using staticFile() - got "${path}". See: https://remotion.dev/docs/staticfile-relative-paths`);
4057
+ }
4058
+ const includesHex = includesHexOfUnsafeChar(path);
4059
+ if (includesHex.containsHex) {
4060
+ warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). The encoding gets automatically handled by staticFile() `);
4061
+ }
4062
+ const preparsed = inner(encodeURIComponent(path));
4063
+ if (!preparsed.startsWith('/')) {
4064
+ return `/${preparsed}`;
4065
+ }
4066
+ return preparsed;
4067
+ };
4068
+
4069
+ /**
4070
+ * @description A `<Still />` is a `<Composition />` that is only 1 frame long.
4071
+ * @see [Documentation](https://www.remotion.dev/docs/still)
4072
+ */
4073
+ const Still = (props) => {
4074
+ const newProps = {
4075
+ ...props,
4076
+ durationInFrames: 1,
4077
+ fps: 1,
4078
+ };
4079
+ // @ts-expect-error TypeScript does not understand it, but should still fail on type mismatch
4080
+ return React.createElement((Composition), newProps);
4081
+ };
4082
+
4083
+ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate, src, muted, allowAmplificationDuringRender, transparent = false, ...props }) => {
4084
+ const absoluteFrame = useTimelinePosition();
4085
+ const frame = useCurrentFrame();
4086
+ const volumePropsFrame = useFrameForVolumeProp();
4087
+ const videoConfig = useUnsafeVideoConfig();
4088
+ const sequenceContext = useContext(SequenceContext);
4089
+ const mediaStartsAt = useMediaStartsAt();
4090
+ const { registerAsset, unregisterAsset } = useContext(AssetManager);
4091
+ if (!src) {
4092
+ throw new TypeError('No `src` was passed to <OffthreadVideo>.');
4093
+ }
4094
+ // Generate a string that's as unique as possible for this asset
4095
+ // but at the same time the same on all threads
4096
+ const id = useMemo(() => `offthreadvideo-${random(src !== null && src !== void 0 ? src : '')}-${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}`, [
4097
+ src,
4098
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
4099
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
4100
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
4101
+ ]);
4102
+ if (!videoConfig) {
4103
+ throw new Error('No video config found');
4104
+ }
4105
+ const volume = evaluateVolume({
4106
+ volume: volumeProp,
4107
+ frame: volumePropsFrame,
4108
+ mediaVolume: 1,
4109
+ allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
4110
+ });
4111
+ useEffect(() => {
4112
+ if (!src) {
4113
+ throw new Error('No src passed');
4114
+ }
4115
+ if (!window.remotion_audioEnabled) {
4116
+ return;
4117
+ }
4118
+ if (muted) {
4119
+ return;
4120
+ }
4121
+ if (volume <= 0) {
4122
+ return;
4123
+ }
4124
+ registerAsset({
4125
+ type: 'video',
4126
+ src: getAbsoluteSrc(src),
4127
+ id,
4128
+ frame: absoluteFrame,
4129
+ volume,
4130
+ mediaFrame: frame,
4131
+ playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
4132
+ allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
4133
+ });
4134
+ return () => unregisterAsset(id);
4135
+ }, [
4136
+ muted,
4137
+ src,
4138
+ registerAsset,
4139
+ id,
4140
+ unregisterAsset,
4141
+ volume,
4142
+ frame,
4143
+ absoluteFrame,
4144
+ playbackRate,
4145
+ allowAmplificationDuringRender,
4146
+ ]);
4147
+ const currentTime = useMemo(() => {
4148
+ return (getExpectedMediaFrameUncorrected({
4149
+ frame,
4150
+ playbackRate: playbackRate || 1,
4151
+ startFrom: -mediaStartsAt,
4152
+ }) / videoConfig.fps);
4153
+ }, [frame, mediaStartsAt, playbackRate, videoConfig.fps]);
4154
+ const actualSrc = useMemo(() => {
4155
+ return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(currentTime)}&transparent=${String(transparent)}`;
4156
+ }, [currentTime, src, transparent]);
4157
+ const onErr = useCallback((e) => {
4158
+ onError === null || onError === void 0 ? void 0 : onError(e);
4159
+ }, [onError]);
4160
+ const className = useMemo(() => {
4161
+ return [OFFTHREAD_VIDEO_CLASS_NAME, props.className]
4162
+ .filter(truthy)
4163
+ .join(' ');
4164
+ }, [props.className]);
4165
+ return (jsx(Img, { src: actualSrc, className: className, ...props, onError: onErr }));
4166
+ };
4167
+
4168
+ const toSeconds = (time, fps) => {
4169
+ return Math.round((time / fps) * 100) / 100;
4170
+ };
4171
+ const isSubsetOfDuration = (prevStartFrom, newStartFrom, prevDuration, newDuration) => {
4172
+ return (prevStartFrom <= newStartFrom &&
4173
+ prevStartFrom + prevDuration >= newStartFrom + newDuration);
4174
+ };
4175
+ const useAppendVideoFragment = ({ actualSrc: initialActualSrc, actualFrom: initialActualFrom, duration: initialDuration, fps, }) => {
4176
+ const actualFromRef = useRef(initialActualFrom);
4177
+ const actualDuration = useRef(initialDuration);
4178
+ const actualSrc = useRef(initialActualSrc);
4179
+ if (!isSubsetOfDuration || initialActualSrc !== actualSrc.current) {
4180
+ actualFromRef.current = initialActualFrom;
4181
+ actualDuration.current = initialDuration;
4182
+ actualSrc.current = initialActualSrc;
4183
+ }
4184
+ const appended = appendVideoFragment({
4185
+ actualSrc: actualSrc.current,
4186
+ actualFrom: actualFromRef.current,
4187
+ duration: actualDuration.current,
4188
+ fps,
4189
+ });
4190
+ return appended;
4191
+ };
4192
+ // https://github.com/remotion-dev/remotion/issues/1655
4193
+ const isIOSSafariCase = (actualSrc) => {
4194
+ return typeof window === 'undefined'
4195
+ ? false
4196
+ : /iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
4197
+ Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/)) &&
4198
+ actualSrc.startsWith('blob:');
4199
+ };
4200
+ const appendVideoFragment = ({ actualSrc, actualFrom, duration, fps, }) => {
4201
+ var _a;
4202
+ if (isIOSSafariCase(actualSrc)) {
4203
+ return actualSrc;
4204
+ }
4205
+ if (actualSrc.startsWith('data:')) {
4206
+ return actualSrc;
4207
+ }
4208
+ const existingHash = Boolean(new URL(actualSrc, (_a = (typeof window === 'undefined' ? null : window.location.href)) !== null && _a !== void 0 ? _a : 'http://localhost:3000').hash);
4209
+ if (existingHash) {
4210
+ return actualSrc;
4211
+ }
4212
+ if (!Number.isFinite(actualFrom)) {
4213
+ return actualSrc;
4214
+ }
4215
+ actualSrc += `#t=${toSeconds(-actualFrom, fps)}`;
4216
+ if (!Number.isFinite(duration)) {
4217
+ return actualSrc;
4218
+ }
4219
+ actualSrc += `,${toSeconds(duration, fps)}`;
4220
+ return actualSrc;
4221
+ };
4222
+
4223
+ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
4224
+ var _a, _b;
4225
+ const videoRef = useRef(null);
4226
+ const volumePropFrame = useFrameForVolumeProp();
4227
+ const { fps, durationInFrames } = useVideoConfig();
4228
+ const parentSequence = useContext(SequenceContext);
4229
+ const { volume, muted, playbackRate, onlyWarnForMediaSeekingError, src, onDuration,
4230
+ // @ts-expect-error
4231
+ acceptableTimeShift, acceptableTimeShiftInSeconds, ...nativeProps } = props;
4232
+ if (typeof acceptableTimeShift !== 'undefined') {
4233
+ throw new Error('acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.');
4234
+ }
4235
+ const actualVolume = useMediaTagVolume(videoRef);
4236
+ const [mediaVolume] = useMediaVolumeState();
4237
+ const [mediaMuted] = useMediaMutedState();
4238
+ useMediaInTimeline({
4239
+ mediaRef: videoRef,
4240
+ volume,
4241
+ mediaVolume,
4242
+ mediaType: 'video',
4243
+ src,
4244
+ playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
4245
+ });
4246
+ useSyncVolumeWithMediaTag({
4247
+ volumePropFrame,
4248
+ actualVolume,
4249
+ volume,
4250
+ mediaVolume,
4251
+ mediaRef: videoRef,
4252
+ });
4253
+ useMediaPlayback({
4254
+ mediaRef: videoRef,
4255
+ src,
4256
+ mediaType: 'video',
4257
+ playbackRate: (_b = props.playbackRate) !== null && _b !== void 0 ? _b : 1,
4258
+ onlyWarnForMediaSeekingError,
4259
+ acceptableTimeshift: acceptableTimeShiftInSeconds !== null && acceptableTimeShiftInSeconds !== void 0 ? acceptableTimeShiftInSeconds : DEFAULT_ACCEPTABLE_TIMESHIFT,
4260
+ });
4261
+ const actualFrom = parentSequence
4262
+ ? parentSequence.relativeFrom + parentSequence.cumulatedFrom
4263
+ : 0;
4264
+ const duration = parentSequence
4265
+ ? Math.min(parentSequence.durationInFrames, durationInFrames)
4266
+ : durationInFrames;
4267
+ const actualSrc = useAppendVideoFragment({
4268
+ actualSrc: usePreload(src),
4269
+ actualFrom,
4270
+ duration,
4271
+ fps,
4272
+ });
4273
+ useImperativeHandle(ref, () => {
4274
+ return videoRef.current;
4275
+ }, []);
4276
+ useEffect(() => {
4277
+ const { current } = videoRef;
4278
+ if (!current) {
4279
+ return;
4280
+ }
4281
+ const errorHandler = () => {
4282
+ var _a;
4283
+ if (current === null || current === void 0 ? void 0 : current.error) {
4284
+ console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
4285
+ // If user is handling the error, we don't cause an unhandled exception
4286
+ if (props.onError) {
4287
+ return;
4288
+ }
4289
+ 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.`);
4290
+ }
4291
+ else {
4292
+ throw new Error('The browser threw an error');
4293
+ }
4294
+ };
4295
+ current.addEventListener('error', errorHandler, { once: true });
4296
+ return () => {
4297
+ current.removeEventListener('error', errorHandler);
4298
+ };
4299
+ }, [props.onError, src]);
4300
+ const currentOnDurationCallback = useRef();
4301
+ currentOnDurationCallback.current = onDuration;
4302
+ useEffect(() => {
4303
+ var _a;
4304
+ const { current } = videoRef;
4305
+ if (!current) {
4306
+ return;
4307
+ }
4308
+ if (current.duration) {
4309
+ (_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, src, current.duration);
4310
+ return;
4311
+ }
4312
+ const onLoadedMetadata = () => {
4313
+ var _a;
4314
+ (_a = currentOnDurationCallback.current) === null || _a === void 0 ? void 0 : _a.call(currentOnDurationCallback, src, current.duration);
4315
+ };
4316
+ current.addEventListener('loadedmetadata', onLoadedMetadata);
4317
+ return () => {
4318
+ current.removeEventListener('loadedmetadata', onLoadedMetadata);
4319
+ };
4320
+ }, [src]);
4321
+ return (jsx("video", { ref: videoRef, muted: muted || mediaMuted, playsInline: true, src: actualSrc, ...nativeProps }));
4322
+ };
4323
+ // Copy types from forwardRef but not necessary to remove ref
4324
+ const VideoForDevelopment = forwardRef(VideoForDevelopmentRefForwardingFunction);
4325
+
4326
+ /**
4327
+ * @description This method imports and displays a video, similar to <Video />. During rendering, it extracts the exact frame from the video and displays it in an <img> tag
4328
+ * @see [Documentation](https://www.remotion.dev/docs/offthreadvideo)
4329
+ */
4330
+ const OffthreadVideo = (props) => {
4331
+ const { startFrom, endAt, imageFormat, ...otherProps } = props;
4332
+ const environment = useRemotionEnvironment();
4333
+ const onDuration = useCallback(() => undefined, []);
4334
+ if (typeof props.src !== 'string') {
4335
+ throw new TypeError(`The \`<OffthreadVideo>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
4336
+ }
4337
+ if (props.imageFormat) {
4338
+ throw new TypeError(`The \`<OffthreadVideo>\` tag does no longer accept \`imageFormat\`. Use the \`transparent\` prop if you want to render a transparent video.`);
4339
+ }
4340
+ if (typeof startFrom !== 'undefined' || typeof endAt !== 'undefined') {
4341
+ validateStartFromProps(startFrom, endAt);
4342
+ const startFromFrameNo = startFrom !== null && startFrom !== void 0 ? startFrom : 0;
4343
+ const endAtFrameNo = endAt !== null && endAt !== void 0 ? endAt : Infinity;
4344
+ return (jsx(Sequence, { layout: "none", from: 0 - startFromFrameNo, showInTimeline: false, durationInFrames: endAtFrameNo, children: jsx(OffthreadVideo, { ...otherProps }) }));
4345
+ }
4346
+ validateMediaProps(props, 'Video');
4347
+ if (environment === 'rendering') {
4348
+ return (jsx(OffthreadVideoForRendering, { imageFormat: imageFormat, ...otherProps }));
4349
+ }
4350
+ return (jsx(VideoForDevelopment, { onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...otherProps }));
4351
+ };
4352
+
4353
+ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, ...props }, ref) => {
4354
+ const absoluteFrame = useTimelinePosition();
4355
+ const frame = useCurrentFrame();
4356
+ const volumePropsFrame = useFrameForVolumeProp();
4357
+ const videoConfig = useUnsafeVideoConfig();
4358
+ const videoRef = useRef(null);
4359
+ const sequenceContext = useContext(SequenceContext);
4360
+ const mediaStartsAt = useMediaStartsAt();
4361
+ const environment = useRemotionEnvironment();
4362
+ const { registerAsset, unregisterAsset } = useContext(AssetManager);
4363
+ // Generate a string that's as unique as possible for this asset
4364
+ // but at the same time the same on all threads
4365
+ const id = useMemo(() => {
4366
+ var _a;
4367
+ return `video-${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}`;
4368
+ }, [
4369
+ props.src,
4370
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
4371
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
4372
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
4373
+ ]);
4374
+ if (!videoConfig) {
4375
+ throw new Error('No video config found');
4376
+ }
4377
+ const volume = evaluateVolume({
4378
+ volume: volumeProp,
4379
+ frame: volumePropsFrame,
4380
+ mediaVolume: 1,
4381
+ allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
4382
+ });
4383
+ useEffect(() => {
4384
+ if (!props.src) {
4385
+ throw new Error('No src passed');
4386
+ }
4387
+ if (props.muted) {
4388
+ return;
4389
+ }
4390
+ if (volume <= 0) {
4391
+ return;
4392
+ }
4393
+ if (!window.remotion_audioEnabled) {
4394
+ return;
4395
+ }
4396
+ registerAsset({
4397
+ type: 'video',
4398
+ src: getAbsoluteSrc(props.src),
4399
+ id,
4400
+ frame: absoluteFrame,
4401
+ volume,
4402
+ mediaFrame: frame,
4403
+ playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
4404
+ allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
4405
+ });
4406
+ return () => unregisterAsset(id);
4407
+ }, [
4408
+ props.muted,
4409
+ props.src,
4410
+ registerAsset,
4411
+ id,
4412
+ unregisterAsset,
4413
+ volume,
4414
+ frame,
4415
+ absoluteFrame,
4416
+ playbackRate,
4417
+ allowAmplificationDuringRender,
4418
+ ]);
4419
+ useImperativeHandle(ref, () => {
4420
+ return videoRef.current;
4421
+ }, []);
4422
+ useEffect(() => {
4423
+ if (!window.remotion_videoEnabled) {
4424
+ return;
4425
+ }
4426
+ const { current } = videoRef;
4427
+ if (!current) {
4428
+ return;
4429
+ }
4430
+ const currentTime = (() => {
4431
+ return getMediaTime({
4432
+ fps: videoConfig.fps,
4433
+ frame,
4434
+ src: props.src,
4435
+ playbackRate: playbackRate || 1,
4436
+ startFrom: -mediaStartsAt,
4437
+ mediaType: 'video',
4438
+ });
4439
+ })();
4440
+ const handle = delayRender(`Rendering <Video /> with src="${props.src}"`);
4441
+ if (process.env.NODE_ENV === 'test') {
4442
+ continueRender(handle);
4443
+ return;
4444
+ }
4445
+ if (isApproximatelyTheSame(current.currentTime, currentTime)) {
4446
+ if (current.readyState >= 2) {
4447
+ continueRender(handle);
4448
+ return;
4449
+ }
4450
+ const loadedDataHandler = () => {
4451
+ continueRender(handle);
4452
+ };
4453
+ current.addEventListener('loadeddata', loadedDataHandler, { once: true });
4454
+ return () => {
4455
+ current.removeEventListener('loadeddata', loadedDataHandler);
4456
+ };
4457
+ }
4458
+ current.currentTime = currentTime;
4459
+ const seekedHandler = () => {
4460
+ warnAboutNonSeekableMedia(current, 'exception');
4461
+ if (window.navigator.platform.startsWith('Mac')) {
4462
+ // Improve me: This is ensures frame perfectness but slows down render.
4463
+ // Please see this issue for context: https://github.com/remotion-dev/remotion/issues/200
4464
+ // Only affects macOS since it uses VideoToolbox decoding.
4465
+ setTimeout(() => {
4466
+ continueRender(handle);
4467
+ }, 100);
4468
+ }
4469
+ else {
4470
+ continueRender(handle);
4471
+ }
4472
+ };
4473
+ current.addEventListener('seeked', seekedHandler, { once: true });
4474
+ const endedHandler = () => {
4475
+ continueRender(handle);
4476
+ };
4477
+ current.addEventListener('ended', endedHandler, { once: true });
4478
+ const errorHandler = () => {
4479
+ var _a;
4480
+ if (current === null || current === void 0 ? void 0 : current.error) {
4481
+ console.error('Error occurred in video', current === null || current === void 0 ? void 0 : current.error);
4482
+ // If user is handling the error, we don't cause an unhandled exception
4483
+ if (onError) {
4484
+ return;
4485
+ }
4486
+ 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.`);
4487
+ }
4488
+ else {
4489
+ throw new Error('The browser threw an error');
4490
+ }
4491
+ };
4492
+ current.addEventListener('error', errorHandler, { once: true });
4493
+ // If video skips to another frame or unmounts, we clear the created handle
4494
+ return () => {
4495
+ current.removeEventListener('ended', endedHandler);
4496
+ current.removeEventListener('error', errorHandler);
4497
+ current.removeEventListener('seeked', seekedHandler);
4498
+ continueRender(handle);
4499
+ };
4500
+ }, [
4501
+ volumePropsFrame,
4502
+ props.src,
4503
+ playbackRate,
4504
+ videoConfig.fps,
4505
+ frame,
4506
+ mediaStartsAt,
4507
+ onError,
4508
+ ]);
4509
+ const { src } = props;
4510
+ // If video source switches, make new handle
4511
+ if (environment === 'rendering') {
4512
+ // eslint-disable-next-line react-hooks/rules-of-hooks
4513
+ useLayoutEffect(() => {
4514
+ if (process.env.NODE_ENV === 'test') {
4515
+ return;
4516
+ }
4517
+ const newHandle = delayRender('Loading <Video> duration with src=' + src);
4518
+ const { current } = videoRef;
4519
+ const didLoad = () => {
4520
+ if (current === null || current === void 0 ? void 0 : current.duration) {
4521
+ onDuration(src, current.duration);
4522
+ }
4523
+ continueRender(newHandle);
4524
+ };
4525
+ if (current === null || current === void 0 ? void 0 : current.duration) {
4526
+ onDuration(src, current.duration);
4527
+ continueRender(newHandle);
4528
+ }
4529
+ else {
4530
+ current === null || current === void 0 ? void 0 : current.addEventListener('loadedmetadata', didLoad, { once: true });
4531
+ }
4532
+ // If tag gets unmounted, clear pending handles because video metadata is not going to load
4533
+ return () => {
4534
+ current === null || current === void 0 ? void 0 : current.removeEventListener('loadedmetadata', didLoad);
4535
+ continueRender(newHandle);
4536
+ };
4537
+ }, [src, onDuration]);
4538
+ }
4539
+ return jsx("video", { ref: videoRef, ...props, onError: onError });
4540
+ };
4541
+ const VideoForRendering = forwardRef(VideoForRenderingForwardFunction);
4542
+
4543
+ const VideoForwardingFunction = (props, ref) => {
4544
+ var _a;
4545
+ const { startFrom, endAt, ...otherProps } = props;
4546
+ const { loop, ...propsOtherThanLoop } = props;
4547
+ const { fps } = useVideoConfig();
4548
+ const environment = useRemotionEnvironment();
4549
+ const { durations, setDurations } = useContext(DurationsContext);
4550
+ if (typeof ref === 'string') {
4551
+ throw new Error('string refs are not supported');
4552
+ }
4553
+ if (typeof props.src !== 'string') {
4554
+ throw new TypeError(`The \`<Video>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
4555
+ }
4556
+ const onDuration = useCallback((src, durationInSeconds) => {
4557
+ setDurations({ type: 'got-duration', durationInSeconds, src });
4558
+ }, [setDurations]);
4559
+ if (loop && props.src && durations[getAbsoluteSrc(props.src)] !== undefined) {
4560
+ const naturalDuration = durations[getAbsoluteSrc(props.src)] * fps;
4561
+ const playbackRate = (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1;
4562
+ const durationInFrames = Math.floor(naturalDuration / playbackRate);
4563
+ return (jsx(Loop, { durationInFrames: durationInFrames, children: jsx(Video, { ...propsOtherThanLoop, ref: ref }) }));
4564
+ }
4565
+ if (typeof startFrom !== 'undefined' || typeof endAt !== 'undefined') {
4566
+ validateStartFromProps(startFrom, endAt);
4567
+ const startFromFrameNo = startFrom !== null && startFrom !== void 0 ? startFrom : 0;
4568
+ const endAtFrameNo = endAt !== null && endAt !== void 0 ? endAt : Infinity;
4569
+ return (jsx(Sequence, { layout: "none", from: 0 - startFromFrameNo, showInTimeline: false, durationInFrames: endAtFrameNo, children: jsx(Video, { ...otherProps, ref: ref }) }));
4570
+ }
4571
+ validateMediaProps(props, 'Video');
4572
+ if (environment === 'rendering') {
4573
+ return (jsx(VideoForRendering, { onDuration: onDuration, ...otherProps, ref: ref }));
4574
+ }
4575
+ return (jsx(VideoForDevelopment, { onlyWarnForMediaSeekingError: false, ...otherProps, ref: ref, onDuration: onDuration }));
4576
+ };
4577
+ const forward = forwardRef;
4578
+ /**
4579
+ * @description allows you to include a video file in your Remotion project. It wraps the native HTMLVideoElement.
4580
+ * @see [Documentation](https://www.remotion.dev/docs/video)
4581
+ */
4582
+ const Video = forward(VideoForwardingFunction);
4583
+
4584
+ checkMultipleRemotionVersions();
4585
+ const Experimental = {
4586
+ /**
4587
+ * @description This is a special component that will cause Remotion to only partially capture the frame of the video.
4588
+ * @see [Documentation](https://www.remotion.dev/docs/clipper)
4589
+ */
4590
+ Clipper,
4591
+ /**
4592
+ * @description This is a special component, that, when rendered, will skip rendering the frame altogether.
4593
+ * @see [Documentation](https://www.remotion.dev/docs/null)
4594
+ */
4595
+ Null,
4596
+ useIsPlayer,
4597
+ };
4598
+ const proxyObj = {};
4599
+ const Config = new Proxy(proxyObj, {
4600
+ get(_, prop) {
4601
+ if (prop === 'Bundling' ||
4602
+ prop === 'Rendering' ||
4603
+ prop === 'Log' ||
4604
+ prop === 'Puppeteer' ||
4605
+ prop === 'Output') {
4606
+ return Config;
4607
+ }
4608
+ return () => {
4609
+ console.warn('⚠️ The CLI configuration has been extracted from Remotion Core.');
4610
+ console.warn('Update the import from the config file:');
4611
+ console.warn();
4612
+ console.warn('- Delete:');
4613
+ console.warn('import {Config} from "remotion";');
4614
+ console.warn('+ Replace:');
4615
+ console.warn('import {Config} from "@remotion/cli/config";');
4616
+ console.warn();
4617
+ console.warn('For more information, see https://v4.remotion.dev/docs/4-0-migration.');
4618
+ process.exit(1);
4619
+ };
4620
+ },
4621
+ });
4622
+
4623
+ export { AbsoluteFill, Audio, Composition, Config, Easing, Experimental, Folder, FolderContext, Freeze, IFrame, Img, Internals, Loop, OffthreadVideo, Sequence, Series, Still, VERSION, Video, cancelRender, continueRender, delayRender, getInputProps, getStaticFiles, interpolate, interpolateColors, measureSpring, prefetch, random, registerRoot, spring, staticFile, useCurrentFrame, useVideoConfig };