@remotion/cli 3.3.19 → 3.3.26

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 (38) hide show
  1. package/dist/config/log.d.ts +1 -1
  2. package/dist/editor/components/InlineAction.d.ts +1 -1
  3. package/dist/editor/components/InlineAction.js +3 -1
  4. package/dist/editor/components/NewComposition/RemInput.d.ts +3 -1
  5. package/dist/editor/components/RenderModal/RenderModal.js +98 -30
  6. package/dist/editor/components/RenderQueue/actions.d.ts +4 -2
  7. package/dist/editor/components/RenderQueue/actions.js +7 -4
  8. package/dist/editor/helpers/client-id.d.ts +17 -0
  9. package/dist/editor/helpers/client-id.js +46 -0
  10. package/dist/editor/helpers/use-file-existence.js +12 -3
  11. package/dist/event-source-events.d.ts +4 -0
  12. package/dist/event-source.js +3 -0
  13. package/dist/get-cli-options.d.ts +1 -1
  14. package/dist/index.d.ts +3 -3
  15. package/dist/preview-server/file-existence-watchers.d.ts +5 -2
  16. package/dist/preview-server/file-existence-watchers.js +23 -7
  17. package/dist/preview-server/public-folder.d.ts +8 -3
  18. package/dist/preview-server/public-folder.js +11 -10
  19. package/dist/preview-server/render-queue/job.d.ts +2 -0
  20. package/dist/preview-server/render-queue/process-still.d.ts +2 -1
  21. package/dist/preview-server/render-queue/process-still.js +2 -1
  22. package/dist/preview-server/render-queue/process-video.d.ts +2 -1
  23. package/dist/preview-server/render-queue/process-video.js +7 -3
  24. package/dist/preview-server/render-queue/queue.d.ts +2 -1
  25. package/dist/preview-server/render-queue/queue.js +22 -3
  26. package/dist/preview-server/routes/add-render.js +1 -2
  27. package/dist/preview-server/routes/subscribe-to-file-existence.js +2 -2
  28. package/dist/preview-server/routes/unsubscribe-from-file-existence.js +5 -1
  29. package/dist/preview-server/routes.d.ts +2 -2
  30. package/dist/preview-server/routes.js +6 -5
  31. package/dist/preview-server/start-server.d.ts +6 -1
  32. package/dist/preview-server/start-server.js +6 -9
  33. package/dist/preview.js +29 -2
  34. package/dist/render-flows/render.d.ts +7 -3
  35. package/dist/render-flows/render.js +40 -37
  36. package/dist/render-flows/still.d.ts +2 -1
  37. package/dist/render-flows/still.js +4 -6
  38. package/package.json +9 -10
@@ -1,3 +1,3 @@
1
1
  import type { LogLevel } from '@remotion/renderer';
2
- export declare const getLogLevel: () => "error" | "verbose" | "info" | "warn";
2
+ export declare const getLogLevel: () => "verbose" | "error" | "info" | "warn";
3
3
  export declare const setLogLevel: (newLogLevel: LogLevel) => void;
@@ -1,5 +1,5 @@
1
1
  import type { PropsWithChildren } from 'react';
2
2
  import React from 'react';
3
3
  export declare const InlineAction: React.FC<PropsWithChildren<{
4
- onClick: React.MouseEventHandler<HTMLButtonElement> | undefined;
4
+ onClick: React.MouseEventHandler<HTMLAnchorElement> | undefined;
5
5
  }>>;
@@ -27,6 +27,8 @@ const InlineAction = ({ children, onClick }) => {
27
27
  opacity: hovered ? 1 : 0.6,
28
28
  };
29
29
  }, [hovered]);
30
- return ((0, jsx_runtime_1.jsx)("button", { onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, type: "button", onClick: onClick, style: style, tabIndex: tabIndex, children: children }));
30
+ return (
31
+ // <div> because cannot use button inside a button
32
+ (0, jsx_runtime_1.jsx)("a", { onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, onClick: onClick, style: style, tabIndex: tabIndex, children: children }));
31
33
  };
32
34
  exports.InlineAction = InlineAction;
@@ -1,3 +1,5 @@
1
1
  import React from 'react';
2
+ declare type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
2
3
  export declare const inputBaseStyle: React.CSSProperties;
3
- export declare const RemotionInput: (props: React.ClassAttributes<HTMLInputElement> & React.InputHTMLAttributes<HTMLInputElement> & React.RefAttributes<HTMLInputElement | null>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
4
+ export declare const RemotionInput: React.ForwardRefExoticComponent<Pick<Props, "key" | keyof React.InputHTMLAttributes<HTMLInputElement>> & React.RefAttributes<HTMLInputElement>>;
5
+ export {};
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RenderModal = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // TODO: refactor such that importing from '@remotion/renderer/src/get-extension-from-codec' is no longer needed
6
+ const get_extension_from_codec_1 = require("@remotion/renderer/src/get-extension-from-codec");
5
7
  const react_1 = require("react");
6
8
  const Button_1 = require("../../../preview-server/error-overlay/remotion-overlay/Button");
7
9
  const colors_1 = require("../../helpers/colors");
@@ -36,7 +38,14 @@ const reducer = (state, action) => {
36
38
  }
37
39
  return state;
38
40
  };
39
- const container = {};
41
+ const container = {
42
+ display: 'flex',
43
+ flexDirection: 'row',
44
+ alignItems: 'center',
45
+ padding: '12px 16px',
46
+ width: '100%',
47
+ borderBottom: '1px solid black',
48
+ };
40
49
  const optionRow = {
41
50
  display: 'flex',
42
51
  flexDirection: 'row',
@@ -86,6 +95,9 @@ const RenderModal = ({ compositionId, initialFrame, initialImageFormat, initialQ
86
95
  const [state, dispatch] = (0, react_1.useReducer)(reducer, initialState);
87
96
  const [frame, setFrame] = (0, react_1.useState)(() => initialFrame);
88
97
  const [imageFormat, setImageFormat] = (0, react_1.useState)(() => initialImageFormat);
98
+ const [videoCodec, setVideoCodec] = (0, react_1.useState)('h264');
99
+ const [videoImageFormat, setVideoImageFormat] = (0, react_1.useState)('jpeg');
100
+ const [renderMode, setRenderMode] = (0, react_1.useState)('still');
89
101
  const [quality, setQuality] = (0, react_1.useState)(() => initialQuality !== null && initialQuality !== void 0 ? initialQuality : 80);
90
102
  const [scale, setScale] = (0, react_1.useState)(() => initialScale);
91
103
  const [verbose, setVerboseLogging] = (0, react_1.useState)(() => initialVerbose);
@@ -98,22 +110,24 @@ const RenderModal = ({ compositionId, initialFrame, initialImageFormat, initialQ
98
110
  const onValueChange = (0, react_1.useCallback)((e) => {
99
111
  setOutName(e.target.value);
100
112
  }, []);
101
- const setPng = (0, react_1.useCallback)(() => {
102
- setImageFormat('png');
113
+ const getStringBeforeSuffix = (0, react_1.useCallback)((fileName) => {
114
+ const dotPos = fileName.lastIndexOf('.');
115
+ const bitBeforeDot = fileName.substring(0, dotPos);
116
+ return bitBeforeDot;
117
+ }, []);
118
+ const setCodec = (0, react_1.useCallback)((codec) => {
119
+ setVideoCodec(codec);
103
120
  setOutName((prev) => {
104
- if (prev.endsWith('.jpeg') || prev.endsWith('.jpg')) {
105
- return prev.replace(/.jpe?g$/g, '.png');
106
- }
107
- return prev;
121
+ const codecSuffix = (0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, 'final');
122
+ const newFileName = getStringBeforeSuffix(prev) + '.' + codecSuffix;
123
+ return newFileName;
108
124
  });
109
125
  }, []);
110
- const setJpeg = (0, react_1.useCallback)(() => {
111
- setImageFormat('jpeg');
126
+ const setStillFormat = (0, react_1.useCallback)((format) => {
127
+ setImageFormat(format);
112
128
  setOutName((prev) => {
113
- if (prev.endsWith('.png')) {
114
- return prev.replace(/.png$/g, '.jpeg');
115
- }
116
- return prev;
129
+ const newFileName = getStringBeforeSuffix(prev) + '.' + format;
130
+ return newFileName;
117
131
  });
118
132
  }, []);
119
133
  const onClickStill = (0, react_1.useCallback)(() => {
@@ -154,12 +168,12 @@ const RenderModal = ({ compositionId, initialFrame, initialImageFormat, initialQ
154
168
  (0, actions_1.addVideoRenderJob)({
155
169
  compositionId,
156
170
  outName,
157
- imageFormat,
171
+ imageFormat: videoImageFormat,
158
172
  quality: imageFormat === 'jpeg' ? quality : null,
159
173
  scale,
160
174
  verbose,
161
175
  // TODO: Make this configurable
162
- codec: 'h264',
176
+ codec: videoCodec,
163
177
  })
164
178
  .then(() => {
165
179
  dispatchIfMounted({ type: 'succeed' });
@@ -177,6 +191,8 @@ const RenderModal = ({ compositionId, initialFrame, initialImageFormat, initialQ
177
191
  scale,
178
192
  setSelectedModal,
179
193
  verbose,
194
+ videoCodec,
195
+ videoImageFormat,
180
196
  ]);
181
197
  const onQualityChangedDirectly = (0, react_1.useCallback)((newQuality) => {
182
198
  setQuality(newQuality);
@@ -227,36 +243,88 @@ const RenderModal = ({ compositionId, initialFrame, initialImageFormat, initialQ
227
243
  return [
228
244
  {
229
245
  label: 'PNG',
230
- onClick: setPng,
246
+ onClick: renderMode === 'still'
247
+ ? () => setStillFormat('png')
248
+ : () => setVideoImageFormat('png'),
231
249
  key: 'png',
232
- selected: imageFormat === 'png',
250
+ selected: renderMode === 'still'
251
+ ? imageFormat === 'png'
252
+ : videoImageFormat === 'png',
233
253
  },
234
254
  {
235
255
  label: 'JPEG',
236
- onClick: setJpeg,
256
+ onClick: renderMode === 'still'
257
+ ? () => setStillFormat('jpeg')
258
+ : () => setVideoImageFormat('jpeg'),
237
259
  key: 'jpeg',
238
- selected: imageFormat === 'jpeg',
260
+ selected: renderMode === 'still'
261
+ ? imageFormat === 'jpeg'
262
+ : videoImageFormat === 'jpeg',
263
+ },
264
+ ];
265
+ }, [imageFormat, renderMode, setStillFormat, videoImageFormat]);
266
+ const videoCodecOptions = (0, react_1.useMemo)(() => {
267
+ const codecs = [
268
+ 'h264',
269
+ 'h265',
270
+ 'vp8',
271
+ 'vp9',
272
+ 'mp3',
273
+ 'aac',
274
+ 'wav',
275
+ 'prores',
276
+ 'h264-mkv',
277
+ 'gif',
278
+ ];
279
+ return codecs.map((codec) => {
280
+ return {
281
+ label: codec,
282
+ onClick: () => setCodec(codec),
283
+ key: codec,
284
+ selected: videoCodec === codec,
285
+ };
286
+ });
287
+ }, [setCodec, videoCodec]);
288
+ const renderTabOptions = (0, react_1.useMemo)(() => {
289
+ return [
290
+ {
291
+ label: 'Still',
292
+ onClick: () => {
293
+ setRenderMode('still');
294
+ setStillFormat(imageFormat);
295
+ },
296
+ key: 'still',
297
+ selected: renderMode === 'still',
298
+ },
299
+ {
300
+ label: 'Video',
301
+ onClick: () => {
302
+ setRenderMode('video');
303
+ setCodec(videoCodec);
304
+ },
305
+ key: 'video',
306
+ selected: renderMode === 'video',
239
307
  },
240
308
  ];
241
- }, [imageFormat, setJpeg, setPng]);
309
+ }, [imageFormat, renderMode, setCodec, setStillFormat, videoCodec]);
242
310
  const onVerboseLoggingChanged = (0, react_1.useCallback)((e) => {
243
311
  setVerboseLogging(e.target.checked);
244
312
  }, []);
245
- return ((0, jsx_runtime_1.jsxs)(ModalContainer_1.ModalContainer, { onOutsideClick: onQuit, onEscape: onQuit, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.NewCompHeader, { title: `Render ${compositionId}` }), (0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Format" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Output name" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(RemInput_1.RemotionInput
313
+ return ((0, jsx_runtime_1.jsxs)(ModalContainer_1.ModalContainer, { onOutsideClick: onQuit, onEscape: onQuit, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.NewCompHeader, { title: `Render ${compositionId}` }), (0, jsx_runtime_1.jsx)("div", { style: container, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: renderTabOptions }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: renderMode === 'still' ? 'Format' : 'Codec' }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: renderMode === 'still' ? imageFormatOptions : videoCodecOptions }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Output name" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(RemInput_1.RemotionInput
246
314
  // TODO: Validate and reject folders or weird file names
247
315
  , {
248
316
  // TODO: Validate and reject folders or weird file names
249
- warning: existence, style: input, type: "text", value: outName, onChange: onValueChange }), existence ? ((0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { align: "flex-end", message: "Will be overwritten" })) : null] }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Frame" }), (0, jsx_runtime_1.jsxs)("div", { style: rightRow, children: [(0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger
250
- // TODO: Hide if it is a still
251
- , {
317
+ warning: existence, style: input, type: "text", value: outName, onChange: onValueChange }), existence ? ((0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { align: "flex-end", message: "Will be overwritten" })) : null] }) })] }), (0, jsx_runtime_1.jsx)("div", { style: optionRow, children: renderMode === 'still' && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Frame" }), (0, jsx_runtime_1.jsxs)("div", { style: rightRow, children: [(0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger
252
318
  // TODO: Hide if it is a still
253
- value: frame, onChange: onFrameChanged,
254
- // TODO: Actual frame
255
- placeholder: "0-100", onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0,
256
- // TODO: Add actual frame
257
- max: Infinity }), ' '] })] }), (0, jsx_runtime_1.jsxs)(CollapsableOptions_1.CollapsableOptions, { showLabel: "Show advanced settings", hideLabel: "Hide advanced settings", children: [(0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Scale" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: scale, onChange: onScaleChanged, placeholder: "0.1-10",
319
+ , {
320
+ // TODO: Hide if it is a still
321
+ value: frame, onChange: onFrameChanged,
322
+ // TODO: Actual frame
323
+ placeholder: "0-100", onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0,
324
+ // TODO: Add actual frame
325
+ max: Infinity }), ' '] })] })) }), (0, jsx_runtime_1.jsxs)(CollapsableOptions_1.CollapsableOptions, { showLabel: "Show advanced settings", hideLabel: "Hide advanced settings", children: [(0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Scale" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: scale, onChange: onScaleChanged, placeholder: "0.1-10",
258
326
  // TODO: Does not allow non-integer steps
259
327
  // TODO: Cannot click and type in 0.2
260
- onValueChange: onScaleSetDirectly, name: "scale", step: 0.05, min: MIN_SCALE, max: MAX_SCALE }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Verbose logging" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)("input", { type: 'checkbox', checked: verbose, onChange: onVerboseLoggingChanged }) })] }), imageFormat === 'jpeg' && ((0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "JPEG Quality" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: quality, onChange: onQualityChanged, placeholder: "0-100", onValueChange: onQualityChangedDirectly, name: "quality", step: 1, min: MIN_QUALITY, max: MAX_QUALITY }) })] }))] }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsxs)("div", { style: buttonRow, children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { autoFocus: true, onClick: onClickVideo, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render video' : 'Rendering...' }), (0, jsx_runtime_1.jsx)(Button_1.Button, { autoFocus: true, onClick: onClickStill, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render' : 'Rendering...' })] })] })] }));
328
+ onValueChange: onScaleSetDirectly, name: "scale", step: 0.05, min: MIN_SCALE, max: MAX_SCALE }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Verbose logging" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)("input", { type: 'checkbox', checked: verbose, onChange: onVerboseLoggingChanged }) })] }), renderMode === 'video' && ((0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Image Format" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions }) })] })), (imageFormat === 'jpeg' || videoImageFormat === 'jpeg') && ((0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "JPEG Quality" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: quality, onChange: onQualityChanged, placeholder: "0-100", onValueChange: onQualityChangedDirectly, name: "quality", step: 1, min: MIN_QUALITY, max: MAX_QUALITY }) })] }))] }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsx)("div", { style: buttonRow, children: renderMode === 'still' ? ((0, jsx_runtime_1.jsx)(Button_1.Button, { autoFocus: true, onClick: onClickStill, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render still' : 'Rendering...' })) : ((0, jsx_runtime_1.jsx)(Button_1.Button, { autoFocus: true, onClick: onClickVideo, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render video' : 'Rendering...' })) })] })] }));
261
329
  };
262
330
  exports.RenderModal = RenderModal;
@@ -20,11 +20,13 @@ export declare const addVideoRenderJob: ({ compositionId, outName, imageFormat,
20
20
  verbose: boolean;
21
21
  codec: Codec;
22
22
  }) => Promise<undefined>;
23
- export declare const unsubscribeFromFileExistenceWatcher: ({ file }: {
23
+ export declare const unsubscribeFromFileExistenceWatcher: ({ file, clientId, }: {
24
24
  file: string;
25
+ clientId: string;
25
26
  }) => Promise<undefined>;
26
- export declare const subscribeToFileExistenceWatcher: ({ file, }: {
27
+ export declare const subscribeToFileExistenceWatcher: ({ file, clientId, }: {
27
28
  file: string;
29
+ clientId: string;
28
30
  }) => Promise<boolean>;
29
31
  export declare const openInFileExplorer: ({ directory }: {
30
32
  directory: string;
@@ -51,12 +51,15 @@ const addVideoRenderJob = ({ compositionId, outName, imageFormat, quality, scale
51
51
  });
52
52
  };
53
53
  exports.addVideoRenderJob = addVideoRenderJob;
54
- const unsubscribeFromFileExistenceWatcher = ({ file }) => {
55
- return (0, exports.callApi)('/api/unsubscribe-from-file-existence', { file });
54
+ const unsubscribeFromFileExistenceWatcher = ({ file, clientId, }) => {
55
+ return (0, exports.callApi)('/api/unsubscribe-from-file-existence', { file, clientId });
56
56
  };
57
57
  exports.unsubscribeFromFileExistenceWatcher = unsubscribeFromFileExistenceWatcher;
58
- const subscribeToFileExistenceWatcher = async ({ file, }) => {
59
- const { exists } = await (0, exports.callApi)('/api/subscribe-to-file-existence', { file });
58
+ const subscribeToFileExistenceWatcher = async ({ file, clientId, }) => {
59
+ const { exists } = await (0, exports.callApi)('/api/subscribe-to-file-existence', {
60
+ file,
61
+ clientId,
62
+ });
60
63
  return exists;
61
64
  };
62
65
  exports.subscribeToFileExistenceWatcher = subscribeToFileExistenceWatcher;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ declare type PreviewServerState = {
3
+ type: 'init';
4
+ } | {
5
+ type: 'connected';
6
+ clientId: string;
7
+ } | {
8
+ type: 'disconnected';
9
+ };
10
+ export declare const PreviewServerConnectionCtx: React.Context<PreviewServerState>;
11
+ export declare const previewServerConnectionRef: React.RefObject<{
12
+ set: (jobs: PreviewServerState) => void;
13
+ }>;
14
+ export declare const PreviewServerConnection: React.FC<{
15
+ children: React.ReactNode;
16
+ }>;
17
+ export {};
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.PreviewServerConnection = exports.previewServerConnectionRef = exports.PreviewServerConnectionCtx = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const react_1 = __importStar(require("react"));
29
+ exports.PreviewServerConnectionCtx = react_1.default.createContext({
30
+ type: 'init',
31
+ });
32
+ exports.previewServerConnectionRef = (0, react_1.createRef)();
33
+ const PreviewServerConnection = ({ children }) => {
34
+ const [state, setState] = react_1.default.useState({
35
+ type: 'init',
36
+ });
37
+ (0, react_1.useImperativeHandle)(exports.previewServerConnectionRef, () => {
38
+ return {
39
+ set: (newState) => {
40
+ setState(newState);
41
+ },
42
+ };
43
+ }, []);
44
+ return ((0, jsx_runtime_1.jsx)(exports.PreviewServerConnectionCtx.Provider, { value: state, children: children }));
45
+ };
46
+ exports.PreviewServerConnection = PreviewServerConnection;
@@ -4,20 +4,29 @@ exports.useFileExistence = void 0;
4
4
  const react_1 = require("react");
5
5
  const event_source_1 = require("../../event-source");
6
6
  const actions_1 = require("../components/RenderQueue/actions");
7
+ const client_id_1 = require("./client-id");
7
8
  const useFileExistence = (outName) => {
8
9
  const [exists, setExists] = (0, react_1.useState)(false);
10
+ const state = (0, react_1.useContext)(client_id_1.PreviewServerConnectionCtx);
11
+ const clientId = state.type === 'connected' ? state.clientId : undefined;
9
12
  const currentOutName = (0, react_1.useRef)('');
10
13
  currentOutName.current = outName;
11
14
  (0, react_1.useEffect)(() => {
12
- (0, actions_1.subscribeToFileExistenceWatcher)({ file: outName }).then((_exists) => {
15
+ if (!clientId) {
16
+ return;
17
+ }
18
+ (0, actions_1.subscribeToFileExistenceWatcher)({
19
+ file: outName,
20
+ clientId,
21
+ }).then((_exists) => {
13
22
  if (currentOutName.current === outName) {
14
23
  setExists(_exists);
15
24
  }
16
25
  });
17
26
  return () => {
18
- (0, actions_1.unsubscribeFromFileExistenceWatcher)({ file: outName });
27
+ (0, actions_1.unsubscribeFromFileExistenceWatcher)({ file: outName, clientId });
19
28
  };
20
- }, [outName]);
29
+ }, [clientId, outName]);
21
30
  (0, react_1.useEffect)(() => {
22
31
  const listener = (event) => {
23
32
  if (event.type !== 'watched-file-deleted') {
@@ -1,3 +1,4 @@
1
+ import type { StaticFile } from 'remotion';
1
2
  export declare type EventSourceEvent = {
2
3
  type: 'new-input-props';
3
4
  newProps: object;
@@ -6,4 +7,7 @@ export declare type EventSourceEvent = {
6
7
  } | {
7
8
  type: 'new-env-variables';
8
9
  newEnvVariables: Record<string, string>;
10
+ } | {
11
+ type: 'new-public-folder';
12
+ files: StaticFile[];
9
13
  };
@@ -11,6 +11,9 @@ const openEventSource = () => {
11
11
  newEvent.type === 'new-env-variables') {
12
12
  window.location.reload();
13
13
  }
14
+ if (newEvent.type === 'new-public-folder') {
15
+ window.remotion_staticFiles = newEvent.files;
16
+ }
14
17
  });
15
18
  source.addEventListener('open', () => {
16
19
  var _a;
@@ -30,7 +30,7 @@ export declare const getCliOptions: (options: {
30
30
  browserExecutable: BrowserExecutable;
31
31
  ffmpegExecutable: import("@remotion/renderer").FfmpegExecutable;
32
32
  ffprobeExecutable: import("@remotion/renderer").FfmpegExecutable;
33
- logLevel: "error" | "verbose" | "info" | "warn";
33
+ logLevel: "verbose" | "error" | "info" | "warn";
34
34
  scale: number;
35
35
  chromiumOptions: ChromiumOptions;
36
36
  overwrite: boolean;
package/dist/index.d.ts CHANGED
@@ -88,7 +88,7 @@ export declare const CliInternals: {
88
88
  browserExecutable: import("@remotion/renderer").BrowserExecutable;
89
89
  ffmpegExecutable: import("@remotion/renderer").FfmpegExecutable;
90
90
  ffprobeExecutable: import("@remotion/renderer").FfmpegExecutable;
91
- logLevel: "error" | "verbose" | "info" | "warn";
91
+ logLevel: "verbose" | "error" | "info" | "warn";
92
92
  scale: number;
93
93
  chromiumOptions: import("@remotion/renderer").ChromiumOptions;
94
94
  overwrite: boolean;
@@ -135,7 +135,7 @@ export declare const CliInternals: {
135
135
  source: string;
136
136
  };
137
137
  minimist: typeof minimist;
138
- selectComposition: (validCompositions: import("remotion").TCompMetadata[]) => Promise<{
138
+ selectComposition: (validCompositions: import("remotion/.").TCompMetadata[]) => Promise<{
139
139
  compositionId: string;
140
140
  reason: string;
141
141
  }>;
@@ -145,5 +145,5 @@ export declare const CliInternals: {
145
145
  reason: string;
146
146
  };
147
147
  getImageFormat: (codec: import("@remotion/renderer").CodecOrUndefined) => "png" | "jpeg" | "none";
148
- printCompositions: (compositions: import("remotion").TCompMetadata[]) => void;
148
+ printCompositions: (compositions: import("remotion/.").TCompMetadata[]) => void;
149
149
  };
@@ -1,10 +1,13 @@
1
- export declare const subscribeToFileExistenceWatchers: ({ file: relativeFile, remotionRoot, }: {
1
+ export declare const subscribeToFileExistenceWatchers: ({ file: relativeFile, remotionRoot, clientId, }: {
2
2
  file: string;
3
3
  remotionRoot: string;
4
+ clientId: string;
4
5
  }) => {
5
6
  exists: boolean;
6
7
  };
7
- export declare const unsubscribeFromFileExistenceWatchers: ({ file, remotionRoot, }: {
8
+ export declare const unsubscribeFromFileExistenceWatchers: ({ file, remotionRoot, clientId, }: {
8
9
  file: string;
9
10
  remotionRoot: string;
11
+ clientId: string;
10
12
  }) => void;
13
+ export declare const unsubscribeClientFileExistenceWatchers: (clientId: string) => void;
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.unsubscribeFromFileExistenceWatchers = exports.subscribeToFileExistenceWatchers = void 0;
6
+ exports.unsubscribeClientFileExistenceWatchers = exports.unsubscribeFromFileExistenceWatchers = exports.subscribeToFileExistenceWatchers = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const file_watcher_1 = require("../file-watcher");
9
9
  const live_events_1 = require("./live-events");
10
10
  const fileExistenceWatchers = {};
11
- const subscribeToFileExistenceWatchers = ({ file: relativeFile, remotionRoot, }) => {
11
+ const subscribeToFileExistenceWatchers = ({ file: relativeFile, remotionRoot, clientId, }) => {
12
12
  const file = path_1.default.resolve(remotionRoot, relativeFile);
13
13
  const { unwatch, exists } = (0, file_watcher_1.installFileWatcher)({
14
14
  file,
@@ -33,14 +33,30 @@ const subscribeToFileExistenceWatchers = ({ file: relativeFile, remotionRoot, })
33
33
  }
34
34
  },
35
35
  });
36
- fileExistenceWatchers[file] = unwatch;
36
+ if (!fileExistenceWatchers[clientId]) {
37
+ fileExistenceWatchers[clientId] = {};
38
+ }
39
+ fileExistenceWatchers[clientId][file] = unwatch;
37
40
  return { exists };
38
41
  };
39
42
  exports.subscribeToFileExistenceWatchers = subscribeToFileExistenceWatchers;
40
- const unsubscribeFromFileExistenceWatchers = ({ file, remotionRoot, }) => {
41
- var _a;
43
+ const unsubscribeFromFileExistenceWatchers = ({ file, remotionRoot, clientId, }) => {
44
+ var _a, _b;
42
45
  const actualPath = path_1.default.resolve(remotionRoot, file);
43
- (_a = fileExistenceWatchers[actualPath]) === null || _a === void 0 ? void 0 : _a.call(fileExistenceWatchers);
44
- delete fileExistenceWatchers[actualPath];
46
+ if (!fileExistenceWatchers[clientId]) {
47
+ return;
48
+ }
49
+ (_b = (_a = fileExistenceWatchers[clientId])[actualPath]) === null || _b === void 0 ? void 0 : _b.call(_a);
50
+ delete fileExistenceWatchers[clientId][actualPath];
45
51
  };
46
52
  exports.unsubscribeFromFileExistenceWatchers = unsubscribeFromFileExistenceWatchers;
53
+ const unsubscribeClientFileExistenceWatchers = (clientId) => {
54
+ if (!fileExistenceWatchers[clientId]) {
55
+ return;
56
+ }
57
+ Object.values(fileExistenceWatchers[clientId]).forEach((unwatch) => {
58
+ unwatch();
59
+ });
60
+ delete fileExistenceWatchers[clientId];
61
+ };
62
+ exports.unsubscribeClientFileExistenceWatchers = unsubscribeClientFileExistenceWatchers;
@@ -1,12 +1,17 @@
1
1
  import type { StaticFile } from 'remotion';
2
- export declare const initPublicFolderWatch: ({ publicDir, remotionRoot, onUpdate, }: {
2
+ export declare const initPublicFolderWatch: ({ publicDir, onUpdate, staticHash, }: {
3
3
  publicDir: string;
4
4
  remotionRoot: string;
5
5
  onUpdate: () => void;
6
+ staticHash: string;
6
7
  }) => void;
7
- export declare const watchPublicFolder: ({ publicDir, remotionRoot, onUpdate, }: {
8
+ export declare const fetchFolder: ({ publicDir, staticHash, }: {
9
+ publicDir: string;
10
+ staticHash: string;
11
+ }) => void;
12
+ export declare const watchPublicFolder: ({ publicDir, onUpdate, staticHash, }: {
8
13
  publicDir: string;
9
- remotionRoot: string;
10
14
  onUpdate: () => void;
15
+ staticHash: string;
11
16
  }) => void;
12
17
  export declare const getFiles: () => StaticFile[];
@@ -3,32 +3,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getFiles = exports.watchPublicFolder = exports.initPublicFolderWatch = void 0;
6
+ exports.getFiles = exports.watchPublicFolder = exports.fetchFolder = exports.initPublicFolderWatch = void 0;
7
7
  const bundler_1 = require("@remotion/bundler");
8
8
  const fs_1 = require("fs");
9
9
  const path_1 = __importDefault(require("path"));
10
- const write_files_definition_file_1 = require("./write-files-definition-file");
11
10
  let files = [];
12
- const initPublicFolderWatch = ({ publicDir, remotionRoot, onUpdate, }) => {
13
- fetchFolder({ publicDir, remotionRoot });
14
- (0, exports.watchPublicFolder)({ publicDir, remotionRoot, onUpdate });
11
+ const initPublicFolderWatch = ({ publicDir, onUpdate, staticHash, }) => {
12
+ (0, exports.fetchFolder)({ publicDir, staticHash });
13
+ (0, exports.watchPublicFolder)({ publicDir, onUpdate, staticHash });
15
14
  };
16
15
  exports.initPublicFolderWatch = initPublicFolderWatch;
17
- const fetchFolder = ({ publicDir, remotionRoot, }) => {
16
+ const fetchFolder = ({ publicDir, staticHash, }) => {
18
17
  files = bundler_1.BundlerInternals.readRecursively({
19
18
  folder: '.',
20
19
  startPath: publicDir,
20
+ staticHash,
21
+ limit: 1000,
21
22
  }).map((f) => {
22
23
  return {
23
24
  ...f,
24
- path: f.path.split(path_1.default.sep).join('/'),
25
+ name: f.name.split(path_1.default.sep).join('/'),
25
26
  };
26
27
  });
27
- (0, write_files_definition_file_1.writeFilesDefinitionFile)(files, remotionRoot);
28
28
  };
29
- const watchPublicFolder = ({ publicDir, remotionRoot, onUpdate, }) => {
29
+ exports.fetchFolder = fetchFolder;
30
+ const watchPublicFolder = ({ publicDir, onUpdate, staticHash, }) => {
30
31
  (0, fs_1.watch)(publicDir, { recursive: true }, () => {
31
- fetchFolder({ publicDir, remotionRoot });
32
+ (0, exports.fetchFolder)({ publicDir, staticHash });
32
33
  onUpdate();
33
34
  });
34
35
  };
@@ -69,11 +69,13 @@ export declare type OpenInFileExplorerRequest = {
69
69
  };
70
70
  export declare type SubscribeToFileExistenceRequest = {
71
71
  file: string;
72
+ clientId: string;
72
73
  };
73
74
  export declare type SubscribeToFileExistenceResponse = {
74
75
  exists: boolean;
75
76
  };
76
77
  export declare type UnsubscribeFromFileExistenceRequest = {
77
78
  file: string;
79
+ clientId: string;
78
80
  };
79
81
  export {};
@@ -1,7 +1,8 @@
1
1
  import type { JobProgressCallback, RenderJob } from './job';
2
- export declare const processStill: ({ job, remotionRoot, entryPoint, onProgress, }: {
2
+ export declare const processStill: ({ job, remotionRoot, entryPoint, onProgress, addCleanupCallback, }: {
3
3
  job: RenderJob;
4
4
  remotionRoot: string;
5
5
  entryPoint: string;
6
6
  onProgress: JobProgressCallback;
7
+ addCleanupCallback: (cb: () => Promise<void>) => void;
7
8
  }) => Promise<void>;
@@ -4,7 +4,7 @@ exports.processStill = void 0;
4
4
  const convert_entry_point_to_serve_url_1 = require("../../convert-entry-point-to-serve-url");
5
5
  const get_cli_options_1 = require("../../get-cli-options");
6
6
  const still_1 = require("../../render-flows/still");
7
- const processStill = async ({ job, remotionRoot, entryPoint, onProgress, }) => {
7
+ const processStill = async ({ job, remotionRoot, entryPoint, onProgress, addCleanupCallback, }) => {
8
8
  var _a;
9
9
  if (job.type !== 'still') {
10
10
  throw new Error('Expected still job');
@@ -42,6 +42,7 @@ const processStill = async ({ job, remotionRoot, entryPoint, onProgress, }) => {
42
42
  logLevel: job.verbose ? 'verbose' : 'info',
43
43
  onProgress,
44
44
  indentOutput: true,
45
+ addCleanupCallback,
45
46
  });
46
47
  // TODO: Allow cancel signal
47
48
  // TODO: Accept CLI options
@@ -1,7 +1,8 @@
1
1
  import type { JobProgressCallback, RenderJob } from './job';
2
- export declare const processVideoJob: ({ job, remotionRoot, entryPoint, onProgress, }: {
2
+ export declare const processVideoJob: ({ job, remotionRoot, entryPoint, onProgress, addCleanupCallback, }: {
3
3
  job: RenderJob;
4
4
  remotionRoot: string;
5
5
  entryPoint: string;
6
6
  onProgress: JobProgressCallback;
7
+ addCleanupCallback: (cb: () => Promise<void>) => void;
7
8
  }) => Promise<void>;