@remotion/studio-server 4.0.540 → 4.0.541
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codemods/get-node-path-remappings.d.ts +5 -2
- package/dist/codemods/get-node-path-remappings.js +7 -1
- package/dist/file-watcher.d.ts +1 -0
- package/dist/file-watcher.js +9 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/preview-server/api-routes.js +4 -0
- package/dist/preview-server/commit-node-codemod.d.ts +27 -0
- package/dist/preview-server/commit-node-codemod.js +68 -0
- package/dist/preview-server/hot-middleware/index.js +11 -7
- package/dist/preview-server/prerendered-scene.d.ts +25 -0
- package/dist/preview-server/prerendered-scene.js +86 -0
- package/dist/preview-server/resolve-compiled-sequence-paths.d.ts +12 -0
- package/dist/preview-server/resolve-compiled-sequence-paths.js +155 -0
- package/dist/preview-server/routes/add-effect-keyframe.js +1 -1
- package/dist/preview-server/routes/add-keyframes.js +17 -9
- package/dist/preview-server/routes/add-render.js +24 -2
- package/dist/preview-server/routes/add-sequence-keyframe.js +1 -1
- package/dist/preview-server/routes/can-update-sequence-props.js +17 -4
- package/dist/preview-server/routes/delete-nodes.js +1 -1
- package/dist/preview-server/routes/duplicate-nodes.js +1 -1
- package/dist/preview-server/routes/invalidate-bundle.js +1 -1
- package/dist/preview-server/routes/prerendered-scene-info.d.ts +3 -0
- package/dist/preview-server/routes/prerendered-scene-info.js +31 -0
- package/dist/preview-server/routes/reorder-sequence.js +1 -1
- package/dist/preview-server/routes/replace-video-source.js +25 -78
- package/dist/preview-server/routes/restore-prerendered-scene.d.ts +3 -0
- package/dist/preview-server/routes/restore-prerendered-scene.js +38 -0
- package/dist/preview-server/routes/save-effect-props.js +1 -1
- package/dist/preview-server/routes/save-sequence-props.js +3 -1
- package/dist/preview-server/routes/split-sequences.js +1 -1
- package/dist/preview-server/routes/split-video-from-audio.js +1 -1
- package/dist/preview-server/routes/subscribe-to-sequence-props.js +50 -15
- package/dist/preview-server/routes/unwrap-node.js +1 -1
- package/dist/preview-server/routes/update-effect-keyframe-settings.js +1 -1
- package/dist/preview-server/routes/update-sequence-keyframe-settings.js +1 -1
- package/dist/preview-server/routes/wrap-node.js +1 -1
- package/dist/preview-server/sequence-node-path-mutation-build.d.ts +2 -0
- package/dist/preview-server/sequence-node-path-mutation-build.js +221 -0
- package/dist/preview-server/sequence-node-path-mutation.d.ts +2 -1
- package/dist/preview-server/sequence-node-path-mutation.js +14 -2
- package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
- package/dist/preview-server/sequence-props-watchers.js +6 -2
- package/dist/preview-server/serve-static.js +3 -0
- package/dist/preview-server/undo-stack.d.ts +1 -1
- package/dist/preview-server/undo-stack.js +14 -2
- package/dist/preview-server/watch-ignore-next-change.d.ts +1 -1
- package/dist/preview-server/watch-ignore-next-change.js +3 -3
- package/dist/routes.js +91 -28
- package/package.json +8 -8
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { File } from '@babel/types';
|
|
2
1
|
import type { SequenceNodePath } from 'remotion';
|
|
3
2
|
export type CapturedJsxNodePath = {
|
|
4
3
|
nodePath: SequenceNodePath;
|
|
4
|
+
location: {
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
} | null;
|
|
5
8
|
};
|
|
6
|
-
export declare const captureJsxNodePaths: (
|
|
9
|
+
export declare const captureJsxNodePaths: (source: string) => CapturedJsxNodePath[];
|
|
@@ -34,14 +34,20 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.captureJsxNodePaths = void 0;
|
|
37
|
+
const codemods_1 = require("@remotion/codemods");
|
|
37
38
|
const recast = __importStar(require("recast"));
|
|
38
39
|
const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
|
|
39
|
-
const
|
|
40
|
+
const parse_ast_1 = require("./parse-ast");
|
|
41
|
+
const captureJsxNodePaths = (source) => {
|
|
42
|
+
const ast = (0, parse_ast_1.parseAst)(source);
|
|
40
43
|
const captured = [];
|
|
41
44
|
recast.visit(ast, {
|
|
42
45
|
visitJSXOpeningElement(path) {
|
|
43
46
|
captured.push({
|
|
44
47
|
nodePath: (0, can_update_sequence_props_1.getNodePathForRecastPath)(path, ast),
|
|
48
|
+
location: path.node.loc
|
|
49
|
+
? codemods_1.CodemodsInternals.getJsxSourceLocation(source, path.node.loc.start)
|
|
50
|
+
: null,
|
|
45
51
|
});
|
|
46
52
|
return this.traverse(path);
|
|
47
53
|
},
|
package/dist/file-watcher.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export type FileChangeEvent = {
|
|
|
23
23
|
sourceVersion: SourceFileVersion | null;
|
|
24
24
|
};
|
|
25
25
|
type OnChange = (event: FileChangeEvent) => void;
|
|
26
|
+
export declare const subscribeToStudioSourceWrites: (listener: (file: string, contents: string) => void) => () => boolean;
|
|
26
27
|
export type FileWatcherRegistry = {
|
|
27
28
|
readonly sourceVersionSessionId: string;
|
|
28
29
|
installFileWatcher: (options: {
|
package/dist/file-watcher.js
CHANGED
|
@@ -33,10 +33,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.writeFileAndNotifyFileWatchers = exports.installFileWatcher = exports.getFileWatcherRegistry = exports.setFileWatcherRegistry = exports.getSourceVersionSessionId = exports.createFileWatcherRegistry = void 0;
|
|
36
|
+
exports.writeFileAndNotifyFileWatchers = exports.installFileWatcher = exports.getFileWatcherRegistry = exports.setFileWatcherRegistry = exports.getSourceVersionSessionId = exports.createFileWatcherRegistry = exports.subscribeToStudioSourceWrites = void 0;
|
|
37
37
|
const node_crypto_1 = require("node:crypto");
|
|
38
38
|
const node_fs_1 = __importStar(require("node:fs"));
|
|
39
39
|
const watch_ignore_next_change_1 = require("./preview-server/watch-ignore-next-change");
|
|
40
|
+
const sourceWriteListeners = new Set();
|
|
41
|
+
const subscribeToStudioSourceWrites = (listener) => {
|
|
42
|
+
sourceWriteListeners.add(listener);
|
|
43
|
+
return () => sourceWriteListeners.delete(listener);
|
|
44
|
+
};
|
|
45
|
+
exports.subscribeToStudioSourceWrites = subscribeToStudioSourceWrites;
|
|
40
46
|
const getRegistryKey = (file, existenceOnly) => existenceOnly ? `${file}\0existence-only` : file;
|
|
41
47
|
const createFileWatcherRegistry = () => {
|
|
42
48
|
const sharedWatchers = new Map();
|
|
@@ -148,6 +154,8 @@ const createFileWatcherRegistry = () => {
|
|
|
148
154
|
(0, watch_ignore_next_change_1.prepareBundlerForFileWrite)(file);
|
|
149
155
|
(0, node_fs_1.writeFileSync)(file, content);
|
|
150
156
|
const sourceVersion = nextSourceVersion();
|
|
157
|
+
for (const listener of sourceWriteListeners)
|
|
158
|
+
listener(file, content);
|
|
151
159
|
const shared = sharedWatchers.get(getRegistryKey(file, false));
|
|
152
160
|
if (!shared) {
|
|
153
161
|
return sourceVersion;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,9 @@ import { getPackageManagerSpawnOptions } from './helpers/package-manager-spawn-o
|
|
|
12
12
|
import { getConfiguredMaxTimelineTracks, getMaxTimelineTracks, resetMaxTimelineTracks, setMaxTimelineTracks } from './max-timeline-tracks';
|
|
13
13
|
import { getPackageManager } from './preview-server/get-package-manager';
|
|
14
14
|
import { waitForLiveEventsListener } from './preview-server/live-events';
|
|
15
|
+
import { replaceWithPrerenderedVideo } from './preview-server/prerendered-scene';
|
|
15
16
|
import { getEditorName } from './preview-server/routes/open-in-editor';
|
|
17
|
+
import { subscribeToSequenceNodePathMutations } from './preview-server/sequence-node-path-mutation';
|
|
16
18
|
import { getRemotionVersion } from './preview-server/update-available';
|
|
17
19
|
import { remotionSkillNames } from './remotion-skill-names';
|
|
18
20
|
import { startStudio } from './start-studio';
|
|
@@ -71,4 +73,6 @@ export declare const StudioServerInternals: {
|
|
|
71
73
|
parseRemotionSkillVersion: typeof parseRemotionSkillVersion;
|
|
72
74
|
remotionSkillNames: readonly ["remotion-best-practices", "remotion-captions", "remotion-create", "remotion-docs", "remotion-interactivity", "remotion-license", "remotion-maps", "remotion-markup", "remotion-multimedia", "remotion-render", "remotion-saas", "remotion-studio", "remotion-upgrade"];
|
|
73
75
|
getEditorName: typeof getEditorName;
|
|
76
|
+
replaceWithPrerenderedVideo: typeof replaceWithPrerenderedVideo;
|
|
77
|
+
subscribeToSequenceNodePathMutations: typeof subscribeToSequenceNodePathMutations;
|
|
74
78
|
};
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,9 @@ const package_manager_spawn_options_1 = require("./helpers/package-manager-spawn
|
|
|
18
18
|
const max_timeline_tracks_1 = require("./max-timeline-tracks");
|
|
19
19
|
const get_package_manager_1 = require("./preview-server/get-package-manager");
|
|
20
20
|
const live_events_1 = require("./preview-server/live-events");
|
|
21
|
+
const prerendered_scene_1 = require("./preview-server/prerendered-scene");
|
|
21
22
|
const open_in_editor_1 = require("./preview-server/routes/open-in-editor");
|
|
23
|
+
const sequence_node_path_mutation_1 = require("./preview-server/sequence-node-path-mutation");
|
|
22
24
|
const update_available_1 = require("./preview-server/update-available");
|
|
23
25
|
const remotion_skill_names_1 = require("./remotion-skill-names");
|
|
24
26
|
Object.defineProperty(exports, "remotionSkillNames", { enumerable: true, get: function () { return remotion_skill_names_1.remotionSkillNames; } });
|
|
@@ -53,4 +55,6 @@ exports.StudioServerInternals = {
|
|
|
53
55
|
parseRemotionSkillVersion: detect_outdated_remotion_skills_1.parseRemotionSkillVersion,
|
|
54
56
|
remotionSkillNames: remotion_skill_names_1.remotionSkillNames,
|
|
55
57
|
getEditorName: open_in_editor_1.getEditorName,
|
|
58
|
+
replaceWithPrerenderedVideo: prerendered_scene_1.replaceWithPrerenderedVideo,
|
|
59
|
+
subscribeToSequenceNodePathMutations: sequence_node_path_mutation_1.subscribeToSequenceNodePathMutations,
|
|
56
60
|
};
|
|
@@ -42,6 +42,7 @@ const open_in_terminal_1 = require("./routes/open-in-terminal");
|
|
|
42
42
|
const paste_effects_1 = require("./routes/paste-effects");
|
|
43
43
|
const precompose_jsx_nodes_1 = require("./routes/precompose-jsx-nodes");
|
|
44
44
|
const prepare_element_install_1 = require("./routes/prepare-element-install");
|
|
45
|
+
const prerendered_scene_info_1 = require("./routes/prerendered-scene-info");
|
|
45
46
|
const project_info_1 = require("./routes/project-info");
|
|
46
47
|
const redo_1 = require("./routes/redo");
|
|
47
48
|
const register_client_render_1 = require("./routes/register-client-render");
|
|
@@ -55,6 +56,7 @@ const reorder_effect_1 = require("./routes/reorder-effect");
|
|
|
55
56
|
const reorder_sequence_1 = require("./routes/reorder-sequence");
|
|
56
57
|
const replace_video_source_1 = require("./routes/replace-video-source");
|
|
57
58
|
const restart_studio_1 = require("./routes/restart-studio");
|
|
59
|
+
const restore_prerendered_scene_1 = require("./routes/restore-prerendered-scene");
|
|
58
60
|
const save_effect_props_1 = require("./routes/save-effect-props");
|
|
59
61
|
const save_multiple_effect_props_1 = require("./routes/save-multiple-effect-props");
|
|
60
62
|
const save_sequence_props_1 = require("./routes/save-sequence-props");
|
|
@@ -141,6 +143,8 @@ exports.allApiRoutes = {
|
|
|
141
143
|
'/api/split-video-from-audio': split_video_from_audio_1.splitVideoFromAudioHandler,
|
|
142
144
|
'/api/insert-basic-captions': insert_basic_captions_1.insertBasicCaptionsHandler,
|
|
143
145
|
'/api/replace-video-source': replace_video_source_1.replaceVideoSourceHandler,
|
|
146
|
+
'/api/prerendered-scene-info': prerendered_scene_info_1.prerenderedSceneInfoHandler,
|
|
147
|
+
'/api/restore-prerendered-scene': restore_prerendered_scene_1.restorePrerenderedSceneHandler,
|
|
144
148
|
'/api/update-available': update_available_1.handleUpdate,
|
|
145
149
|
'/api/release-notes': release_notes_1.getReleaseNotesHandler,
|
|
146
150
|
'/api/remotion-skills-info': remotion_skills_info_1.remotionSkillsInfoHandler,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CodemodProject, NodeReference } from '@remotion/codemods';
|
|
2
|
+
import type { LogLevel } from '@remotion/renderer';
|
|
3
|
+
import type { SequenceNodePathRemapping } from '@remotion/studio-shared';
|
|
4
|
+
import type { SequenceNodePath } from 'remotion';
|
|
5
|
+
import { type UndoEntryType } from './undo-stack';
|
|
6
|
+
export declare const commitNodeCodemod: <Result extends {
|
|
7
|
+
changes: {
|
|
8
|
+
nextContents: string | null;
|
|
9
|
+
}[];
|
|
10
|
+
nodePathRemappings: SequenceNodePathRemapping[];
|
|
11
|
+
logLine: number;
|
|
12
|
+
}>({ remotionRoot, logLevel, fileName, nodePath, codemod, label, entryType, }: {
|
|
13
|
+
remotionRoot: string;
|
|
14
|
+
logLevel: LogLevel;
|
|
15
|
+
fileName: string;
|
|
16
|
+
nodePath: SequenceNodePath;
|
|
17
|
+
codemod: (options: {
|
|
18
|
+
project: CodemodProject;
|
|
19
|
+
node: NodeReference;
|
|
20
|
+
}) => Result;
|
|
21
|
+
label: string;
|
|
22
|
+
entryType: UndoEntryType;
|
|
23
|
+
}) => Promise<{
|
|
24
|
+
absolutePath: string;
|
|
25
|
+
nodePathMutation: import("@remotion/studio-shared").SequenceNodePathMutation;
|
|
26
|
+
result: Result;
|
|
27
|
+
}>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.commitNodeCodemod = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const renderer_1 = require("@remotion/renderer");
|
|
6
|
+
const file_watcher_1 = require("../file-watcher");
|
|
7
|
+
const resolve_file_inside_project_1 = require("../helpers/resolve-file-inside-project");
|
|
8
|
+
const format_log_file_location_1 = require("./format-log-file-location");
|
|
9
|
+
const source_file_write_queue_1 = require("./routes/source-file-write-queue");
|
|
10
|
+
const sequence_node_path_mutation_1 = require("./sequence-node-path-mutation");
|
|
11
|
+
const undo_stack_1 = require("./undo-stack");
|
|
12
|
+
const commitNodeCodemod = ({ remotionRoot, logLevel, fileName, nodePath, codemod, label, entryType, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(() => {
|
|
13
|
+
var _a;
|
|
14
|
+
var _b;
|
|
15
|
+
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
16
|
+
remotionRoot,
|
|
17
|
+
fileName,
|
|
18
|
+
action: 'modify',
|
|
19
|
+
});
|
|
20
|
+
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
21
|
+
const result = codemod({
|
|
22
|
+
project: {
|
|
23
|
+
files: { [absolutePath]: fileContents },
|
|
24
|
+
rootDir: remotionRoot,
|
|
25
|
+
},
|
|
26
|
+
node: { filePath: absolutePath, nodePath },
|
|
27
|
+
});
|
|
28
|
+
const output = (_b = (_a = result.changes[0]) === null || _a === void 0 ? void 0 : _a.nextContents) !== null && _b !== void 0 ? _b : fileContents;
|
|
29
|
+
const { logLine } = result;
|
|
30
|
+
const nodePathRemappings = result.nodePathRemappings.map(({ oldNodePath, newNodePath, oldJsxName, newJsxName }) => ({
|
|
31
|
+
oldNodePath,
|
|
32
|
+
newNodePath,
|
|
33
|
+
oldJsxName,
|
|
34
|
+
newJsxName,
|
|
35
|
+
}));
|
|
36
|
+
const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([{ absolutePath, remappings: nodePathRemappings }], null);
|
|
37
|
+
(0, undo_stack_1.pushToUndoStack)({
|
|
38
|
+
filePath: absolutePath,
|
|
39
|
+
oldContents: fileContents,
|
|
40
|
+
newContents: output,
|
|
41
|
+
logLevel,
|
|
42
|
+
remotionRoot,
|
|
43
|
+
logLine,
|
|
44
|
+
description: {
|
|
45
|
+
undoMessage: `↩️ ${label}`,
|
|
46
|
+
redoMessage: `↪️ ${label}`,
|
|
47
|
+
},
|
|
48
|
+
entryType,
|
|
49
|
+
suppressHmrOnFileRestore: false,
|
|
50
|
+
nodePathRemappings,
|
|
51
|
+
});
|
|
52
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
|
|
53
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)({
|
|
54
|
+
file: absolutePath,
|
|
55
|
+
content: output,
|
|
56
|
+
originatorClientId: undefined,
|
|
57
|
+
metadata: { skipSequencePropsUpdate: true },
|
|
58
|
+
});
|
|
59
|
+
const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
|
|
60
|
+
remotionRoot,
|
|
61
|
+
absolutePath,
|
|
62
|
+
line: logLine,
|
|
63
|
+
});
|
|
64
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(locationLabel)} ${label}`);
|
|
65
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
66
|
+
return { absolutePath, nodePathMutation, result };
|
|
67
|
+
});
|
|
68
|
+
exports.commitNodeCodemod = commitNodeCodemod;
|
|
@@ -8,8 +8,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
8
8
|
exports.setupWebpackHmr = void 0;
|
|
9
9
|
const renderer_1 = require("@remotion/renderer");
|
|
10
10
|
const hmr_timing_1 = require("../hmr-timing");
|
|
11
|
+
const sequence_node_path_mutation_build_1 = require("../sequence-node-path-mutation-build");
|
|
11
12
|
const setupWebpackHmr = (compiler, logLevel, liveEventsServer) => {
|
|
12
|
-
let
|
|
13
|
+
let latestBuild = null;
|
|
14
|
+
const getSourceMutationId = (0, sequence_node_path_mutation_build_1.trackSequenceNodePathMutationBuilds)(compiler);
|
|
13
15
|
const publishHmr = (hmrEvent) => {
|
|
14
16
|
liveEventsServer.sendEventToClient({ type: 'hmr', hmrEvent });
|
|
15
17
|
};
|
|
@@ -24,7 +26,7 @@ const setupWebpackHmr = (compiler, logLevel, liveEventsServer) => {
|
|
|
24
26
|
logLevel,
|
|
25
27
|
stage: 'compiler-invalid',
|
|
26
28
|
});
|
|
27
|
-
|
|
29
|
+
latestBuild = null;
|
|
28
30
|
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, 'Building...');
|
|
29
31
|
publishHmr({
|
|
30
32
|
action: 'building',
|
|
@@ -36,19 +38,20 @@ const setupWebpackHmr = (compiler, logLevel, liveEventsServer) => {
|
|
|
36
38
|
logLevel,
|
|
37
39
|
stage: 'compiler-done',
|
|
38
40
|
});
|
|
41
|
+
const sourceMutationId = getSourceMutationId(statsResult);
|
|
39
42
|
// Keep hold of latest stats so they can be propagated to new clients
|
|
40
|
-
|
|
41
|
-
publishStats('built',
|
|
43
|
+
latestBuild = { stats: statsResult, sourceMutationId };
|
|
44
|
+
publishStats('built', statsResult, sourceMutationId, publishHmr);
|
|
42
45
|
(0, hmr_timing_1.logHmrTiming)({ detail: null, logLevel, stage: 'hmr-stats-published' });
|
|
43
46
|
}
|
|
44
47
|
liveEventsServer.addNewClientListener(() => {
|
|
45
|
-
if (
|
|
46
|
-
publishStats('sync',
|
|
48
|
+
if (latestBuild) {
|
|
49
|
+
publishStats('sync', latestBuild.stats, latestBuild.sourceMutationId, publishHmr);
|
|
47
50
|
}
|
|
48
51
|
});
|
|
49
52
|
};
|
|
50
53
|
exports.setupWebpackHmr = setupWebpackHmr;
|
|
51
|
-
function publishStats(action, statsResult, publishHmr) {
|
|
54
|
+
function publishStats(action, statsResult, sourceMutationId, publishHmr) {
|
|
52
55
|
var _a;
|
|
53
56
|
// Studio uses a single compiler. Child compilations must not replace the
|
|
54
57
|
// parent compilation's hash in the HMR message.
|
|
@@ -57,6 +60,7 @@ function publishStats(action, statsResult, publishHmr) {
|
|
|
57
60
|
action,
|
|
58
61
|
time: statsResult.endTime - statsResult.startTime,
|
|
59
62
|
hash: statsResult.hash,
|
|
63
|
+
sourceMutationId,
|
|
60
64
|
// Build diagnostics are printed by the dev middleware.
|
|
61
65
|
warnings: [],
|
|
62
66
|
errors: [],
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LogLevel } from '@remotion/renderer';
|
|
2
|
+
import type { SequenceNodePath } from 'remotion';
|
|
3
|
+
type PrerenderedSceneSidecar = {
|
|
4
|
+
compositionId: string;
|
|
5
|
+
source: string;
|
|
6
|
+
importStatements: string[];
|
|
7
|
+
sceneFile: string | null;
|
|
8
|
+
sceneFileHash: string | null;
|
|
9
|
+
};
|
|
10
|
+
export declare const getPrerenderedSceneSidecarFile: (videoFile: string) => string;
|
|
11
|
+
export declare const readPrerenderedSceneSidecar: ({ publicDir, src, }: {
|
|
12
|
+
publicDir: string;
|
|
13
|
+
src: string;
|
|
14
|
+
}) => PrerenderedSceneSidecar | null;
|
|
15
|
+
export declare const hashSceneFile: (file: string) => string;
|
|
16
|
+
export declare const replaceWithPrerenderedVideo: ({ remotionRoot, logLevel, fileName, nodePath, src, videoFile, compositionId, }: {
|
|
17
|
+
remotionRoot: string;
|
|
18
|
+
logLevel: LogLevel;
|
|
19
|
+
fileName: string;
|
|
20
|
+
nodePath: SequenceNodePath;
|
|
21
|
+
src: string;
|
|
22
|
+
videoFile: string;
|
|
23
|
+
compositionId: string;
|
|
24
|
+
}) => Promise<void>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.replaceWithPrerenderedVideo = exports.hashSceneFile = exports.readPrerenderedSceneSidecar = exports.getPrerenderedSceneSidecarFile = void 0;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const codemods_1 = require("@remotion/codemods");
|
|
11
|
+
const commit_node_codemod_1 = require("./commit-node-codemod");
|
|
12
|
+
const getPrerenderedSceneSidecarFile = (videoFile) => `${videoFile}.json`;
|
|
13
|
+
exports.getPrerenderedSceneSidecarFile = getPrerenderedSceneSidecarFile;
|
|
14
|
+
const readPrerenderedSceneSidecar = ({ publicDir, src, }) => {
|
|
15
|
+
const videoFile = node_path_1.default.resolve(publicDir, src);
|
|
16
|
+
const relativeToPublicDir = node_path_1.default.relative(publicDir, videoFile);
|
|
17
|
+
if (relativeToPublicDir.startsWith('..') ||
|
|
18
|
+
node_path_1.default.isAbsolute(relativeToPublicDir)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const sidecarFile = (0, exports.getPrerenderedSceneSidecarFile)(videoFile);
|
|
22
|
+
if (!(0, node_fs_1.existsSync)(sidecarFile)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse((0, node_fs_1.readFileSync)(sidecarFile, 'utf-8'));
|
|
27
|
+
}
|
|
28
|
+
catch (_a) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
exports.readPrerenderedSceneSidecar = readPrerenderedSceneSidecar;
|
|
33
|
+
const hashSceneFile = (file) => (0, node_crypto_1.createHash)('sha256')
|
|
34
|
+
.update((0, node_fs_1.readFileSync)(file, 'utf-8'))
|
|
35
|
+
.digest('hex')
|
|
36
|
+
.slice(0, 16);
|
|
37
|
+
exports.hashSceneFile = hashSceneFile;
|
|
38
|
+
const resolveSceneFile = (importingFile, importSource) => {
|
|
39
|
+
var _a;
|
|
40
|
+
if (!importSource.startsWith('.')) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const base = node_path_1.default.resolve(node_path_1.default.dirname(importingFile), importSource);
|
|
44
|
+
const extensions = ['.tsx', '.ts', '.jsx', '.js', '.mjs'];
|
|
45
|
+
return ((_a = [
|
|
46
|
+
base,
|
|
47
|
+
...extensions.map((extension) => base + extension),
|
|
48
|
+
...extensions.map((extension) => node_path_1.default.join(base, `index${extension}`)),
|
|
49
|
+
].find((file) => (0, node_fs_1.existsSync)(file) && (0, node_fs_1.statSync)(file).isFile())) !== null && _a !== void 0 ? _a : null);
|
|
50
|
+
};
|
|
51
|
+
const replaceWithPrerenderedVideo = async ({ remotionRoot, logLevel, fileName, nodePath, src, videoFile, compositionId, }) => {
|
|
52
|
+
const { absolutePath, result } = await (0, commit_node_codemod_1.commitNodeCodemod)({
|
|
53
|
+
remotionRoot,
|
|
54
|
+
logLevel,
|
|
55
|
+
fileName,
|
|
56
|
+
nodePath,
|
|
57
|
+
codemod: ({ project, node }) => codemods_1.CodemodsInternals.replaceNodeChild({
|
|
58
|
+
project,
|
|
59
|
+
node,
|
|
60
|
+
element: (0, codemods_1.createElement)({
|
|
61
|
+
component: 'Video',
|
|
62
|
+
importPath: '@remotion/media',
|
|
63
|
+
props: { src: (0, codemods_1.staticFileValue)(src) },
|
|
64
|
+
}),
|
|
65
|
+
}),
|
|
66
|
+
label: 'Rendered and replaced scene',
|
|
67
|
+
entryType: 'prerender',
|
|
68
|
+
});
|
|
69
|
+
const sceneFile = result.sceneImportSource === null
|
|
70
|
+
? null
|
|
71
|
+
: resolveSceneFile(absolutePath, result.sceneImportSource);
|
|
72
|
+
const sidecar = {
|
|
73
|
+
compositionId,
|
|
74
|
+
source: result.replacedSource,
|
|
75
|
+
importStatements: result.replacedImports,
|
|
76
|
+
sceneFile: sceneFile === null
|
|
77
|
+
? null
|
|
78
|
+
: node_path_1.default.relative(remotionRoot, sceneFile).split(node_path_1.default.sep).join('/'),
|
|
79
|
+
sceneFileHash: sceneFile === null ? null : (0, exports.hashSceneFile)(sceneFile),
|
|
80
|
+
};
|
|
81
|
+
// Written atomically so that a partially written sidecar is never read
|
|
82
|
+
const sidecarFile = (0, exports.getPrerenderedSceneSidecarFile)(videoFile);
|
|
83
|
+
(0, node_fs_1.writeFileSync)(`${sidecarFile}.tmp`, JSON.stringify(sidecar, null, 2) + '\n');
|
|
84
|
+
(0, node_fs_1.renameSync)(`${sidecarFile}.tmp`, sidecarFile);
|
|
85
|
+
};
|
|
86
|
+
exports.replaceWithPrerenderedVideo = replaceWithPrerenderedVideo;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SequenceNodePath } from 'remotion';
|
|
2
|
+
export declare const resolveCompiledSequencePaths: ({ fileName, remotionRoot, fileContentsCache, targets, }: {
|
|
3
|
+
fileName: string;
|
|
4
|
+
remotionRoot: string;
|
|
5
|
+
fileContentsCache: Map<string, string>;
|
|
6
|
+
targets: {
|
|
7
|
+
index: number;
|
|
8
|
+
hash: string;
|
|
9
|
+
line: number;
|
|
10
|
+
column: number;
|
|
11
|
+
}[];
|
|
12
|
+
}) => Map<number, SequenceNodePath | null>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveCompiledSequencePaths = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const codemods_1 = require("@remotion/codemods");
|
|
6
|
+
const read_source_file_1 = require("../helpers/read-source-file");
|
|
7
|
+
const resolve_file_inside_project_1 = require("../helpers/resolve-file-inside-project");
|
|
8
|
+
const undo_stack_1 = require("./undo-stack");
|
|
9
|
+
const resolveCompiledSequencePaths = ({ fileName, remotionRoot, fileContentsCache, targets, }) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
12
|
+
remotionRoot,
|
|
13
|
+
fileName,
|
|
14
|
+
action: 'read',
|
|
15
|
+
});
|
|
16
|
+
const current = (0, read_source_file_1.readSourceFile)({ absolutePath, fileContentsCache });
|
|
17
|
+
const results = new Map();
|
|
18
|
+
const hashes = new Map();
|
|
19
|
+
const snapshots = new Map();
|
|
20
|
+
const inspect = (contents) => {
|
|
21
|
+
const cached = snapshots.get(contents);
|
|
22
|
+
if (cached !== undefined)
|
|
23
|
+
return cached;
|
|
24
|
+
try {
|
|
25
|
+
const nodes = (0, codemods_1.getNodes)({
|
|
26
|
+
project: { rootDir: remotionRoot, files: { [absolutePath]: contents } },
|
|
27
|
+
filePath: absolutePath,
|
|
28
|
+
});
|
|
29
|
+
const locations = new Map();
|
|
30
|
+
for (const { nodePath, location } of nodes) {
|
|
31
|
+
if (!location)
|
|
32
|
+
continue;
|
|
33
|
+
const key = `${location.line}:${location.column}`;
|
|
34
|
+
locations.set(key, locations.has(key) ? null : nodePath);
|
|
35
|
+
}
|
|
36
|
+
const snapshot = {
|
|
37
|
+
locations,
|
|
38
|
+
structure: JSON.stringify(nodes.map((n) => [n.nodePath, n.tagName, n.componentIdentity])),
|
|
39
|
+
};
|
|
40
|
+
snapshots.set(contents, snapshot);
|
|
41
|
+
return snapshot;
|
|
42
|
+
}
|
|
43
|
+
catch (_a) {
|
|
44
|
+
snapshots.set(contents, null);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const matchingTargets = new Map();
|
|
49
|
+
for (const target of targets) {
|
|
50
|
+
const group = (_a = matchingTargets.get(target.hash)) !== null && _a !== void 0 ? _a : [];
|
|
51
|
+
group.push(target);
|
|
52
|
+
matchingTargets.set(target.hash, group);
|
|
53
|
+
}
|
|
54
|
+
const acceptSnapshot = (contents, towardCurrent) => {
|
|
55
|
+
var _a;
|
|
56
|
+
var _b;
|
|
57
|
+
let hash = hashes.get(contents);
|
|
58
|
+
if (!hash) {
|
|
59
|
+
hash = (0, node_crypto_1.createHash)('sha256').update(contents).digest('hex');
|
|
60
|
+
hashes.set(contents, hash);
|
|
61
|
+
}
|
|
62
|
+
const group = matchingTargets.get(hash);
|
|
63
|
+
if (!group)
|
|
64
|
+
return;
|
|
65
|
+
const locations = (_a = inspect(contents)) === null || _a === void 0 ? void 0 : _a.locations;
|
|
66
|
+
const maps = towardCurrent.map((step) => {
|
|
67
|
+
if (step.remappings === null) {
|
|
68
|
+
// Props edits preserve JSX order, but pasted expressions can insert
|
|
69
|
+
// hooks. Without an explicit mapping every JSX path must still match.
|
|
70
|
+
const before = inspect(step.from);
|
|
71
|
+
const after = inspect(step.to);
|
|
72
|
+
return before !== null && before.structure === (after === null || after === void 0 ? void 0 : after.structure)
|
|
73
|
+
? new Map()
|
|
74
|
+
: null;
|
|
75
|
+
}
|
|
76
|
+
const paths = new Map();
|
|
77
|
+
const destinations = new Set();
|
|
78
|
+
for (const { oldNodePath, newNodePath } of step.remappings) {
|
|
79
|
+
const from = step.reverse ? newNodePath : oldNodePath;
|
|
80
|
+
const to = step.reverse ? oldNodePath : newNodePath;
|
|
81
|
+
if (to !== null) {
|
|
82
|
+
const destination = JSON.stringify(to);
|
|
83
|
+
if (destinations.has(destination))
|
|
84
|
+
return null;
|
|
85
|
+
destinations.add(destination);
|
|
86
|
+
}
|
|
87
|
+
if (from === null)
|
|
88
|
+
continue;
|
|
89
|
+
const key = JSON.stringify(from);
|
|
90
|
+
if (paths.has(key))
|
|
91
|
+
return null;
|
|
92
|
+
paths.set(key, to);
|
|
93
|
+
}
|
|
94
|
+
// If a different node took a path, its former occupant cannot
|
|
95
|
+
// have survived there, even if the remapping omitted that occupant.
|
|
96
|
+
for (const key of destinations) {
|
|
97
|
+
if (!paths.has(key))
|
|
98
|
+
paths.set(key, null);
|
|
99
|
+
}
|
|
100
|
+
return paths;
|
|
101
|
+
});
|
|
102
|
+
for (const target of group) {
|
|
103
|
+
let nodePath = (_b = locations === null || locations === void 0 ? void 0 : locations.get(`${target.line}:${target.column}`)) !== null && _b !== void 0 ? _b : null;
|
|
104
|
+
for (let i = maps.length - 1; nodePath !== null && i >= 0; i--) {
|
|
105
|
+
const map = maps[i];
|
|
106
|
+
if (map === null) {
|
|
107
|
+
nodePath = null;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const moved = map.get(JSON.stringify(nodePath));
|
|
111
|
+
if (moved !== undefined)
|
|
112
|
+
nodePath = moved;
|
|
113
|
+
}
|
|
114
|
+
// An identical source can occur on both sides of Undo. If those
|
|
115
|
+
// histories disagree, that hash cannot identify the live element.
|
|
116
|
+
const previous = results.get(target.index);
|
|
117
|
+
results.set(target.index, previous === undefined ||
|
|
118
|
+
JSON.stringify(previous) === JSON.stringify(nodePath)
|
|
119
|
+
? nodePath
|
|
120
|
+
: null);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
acceptSnapshot(current, []);
|
|
124
|
+
for (const [entries, reverse] of [
|
|
125
|
+
[(0, undo_stack_1.getUndoStack)(), false],
|
|
126
|
+
[(0, undo_stack_1.getRedoStack)(), true],
|
|
127
|
+
]) {
|
|
128
|
+
let contents = current;
|
|
129
|
+
const changes = [];
|
|
130
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
131
|
+
const entry = entries[i];
|
|
132
|
+
const snapshot = entry.snapshots.find((s) => s.filePath === absolutePath);
|
|
133
|
+
if (!snapshot)
|
|
134
|
+
continue;
|
|
135
|
+
const from = reverse ? snapshot.newContents : snapshot.oldContents;
|
|
136
|
+
const to = reverse ? snapshot.oldContents : snapshot.newContents;
|
|
137
|
+
if (from === null ||
|
|
138
|
+
to !== contents ||
|
|
139
|
+
(snapshot.nodePathRemappings === null &&
|
|
140
|
+
entry.entryType !== 'sequence-props' &&
|
|
141
|
+
entry.entryType !== 'effect-props'))
|
|
142
|
+
break;
|
|
143
|
+
changes.push({
|
|
144
|
+
from,
|
|
145
|
+
to,
|
|
146
|
+
reverse,
|
|
147
|
+
remappings: snapshot.nodePathRemappings,
|
|
148
|
+
});
|
|
149
|
+
acceptSnapshot(from, changes);
|
|
150
|
+
contents = from;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return results;
|
|
154
|
+
};
|
|
155
|
+
exports.resolveCompiledSequencePaths = resolveCompiledSequencePaths;
|
|
@@ -48,7 +48,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
|
|
|
48
48
|
(0, undo_stack_1.pushToUndoStack)({
|
|
49
49
|
filePath: absolutePath,
|
|
50
50
|
oldContents: fileContents,
|
|
51
|
-
newContents:
|
|
51
|
+
newContents: output,
|
|
52
52
|
logLevel,
|
|
53
53
|
remotionRoot,
|
|
54
54
|
logLine,
|
|
@@ -4,7 +4,6 @@ exports.addKeyframesHandler = exports.addKeyframes = void 0;
|
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const renderer_1 = require("@remotion/renderer");
|
|
6
6
|
const get_node_path_remappings_1 = require("../../codemods/get-node-path-remappings");
|
|
7
|
-
const parse_ast_1 = require("../../codemods/parse-ast");
|
|
8
7
|
const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
|
|
9
8
|
const file_watcher_1 = require("../../file-watcher");
|
|
10
9
|
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
@@ -89,7 +88,7 @@ const addKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, remo
|
|
|
89
88
|
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
90
89
|
let output = fileContents;
|
|
91
90
|
let firstLogLine = Number.POSITIVE_INFINITY;
|
|
92
|
-
const originalNodes = (0, get_node_path_remappings_1.captureJsxNodePaths)(
|
|
91
|
+
const originalNodes = (0, get_node_path_remappings_1.captureJsxNodePaths)(fileContents);
|
|
93
92
|
// Keyframe codemods may wrap a concise arrow in a return statement.
|
|
94
93
|
// JSX nodes remain in order, but their node paths can all change.
|
|
95
94
|
const currentPathFor = (originalPath) => {
|
|
@@ -97,7 +96,7 @@ const addKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, remo
|
|
|
97
96
|
if (index === -1) {
|
|
98
97
|
throw new Error('Could not find the original JSX node for keyframing');
|
|
99
98
|
}
|
|
100
|
-
const currentNodes = (0, get_node_path_remappings_1.captureJsxNodePaths)(
|
|
99
|
+
const currentNodes = (0, get_node_path_remappings_1.captureJsxNodePaths)(output);
|
|
101
100
|
if (currentNodes.length !== originalNodes.length) {
|
|
102
101
|
throw new Error('Could not remap JSX nodes after keyframing');
|
|
103
102
|
}
|
|
@@ -169,7 +168,7 @@ const addKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, remo
|
|
|
169
168
|
});
|
|
170
169
|
}
|
|
171
170
|
}
|
|
172
|
-
const finalNodes = (0, get_node_path_remappings_1.captureJsxNodePaths)(
|
|
171
|
+
const finalNodes = (0, get_node_path_remappings_1.captureJsxNodePaths)(output);
|
|
173
172
|
if (finalNodes.length !== originalNodes.length) {
|
|
174
173
|
throw new Error('Could not remap JSX nodes after keyframing');
|
|
175
174
|
}
|
|
@@ -178,11 +177,20 @@ const addKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, remo
|
|
|
178
177
|
oldContents: fileContents,
|
|
179
178
|
newContents: output,
|
|
180
179
|
logLine: Number.isFinite(firstLogLine) ? firstLogLine : 1,
|
|
181
|
-
nodePathRemappings: originalNodes.flatMap(({ nodePath }, index) => {
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
nodePathRemappings: originalNodes.flatMap(({ location, nodePath }, index) => {
|
|
181
|
+
var _a, _b;
|
|
182
|
+
const next = finalNodes[index];
|
|
183
|
+
return (location === null || location === void 0 ? void 0 : location.line) === ((_a = next.location) === null || _a === void 0 ? void 0 : _a.line) &&
|
|
184
|
+
(location === null || location === void 0 ? void 0 : location.column) === ((_b = next.location) === null || _b === void 0 ? void 0 : _b.column) &&
|
|
185
|
+
JSON.stringify(nodePath) === JSON.stringify(next.nodePath)
|
|
184
186
|
? []
|
|
185
|
-
: [
|
|
187
|
+
: [
|
|
188
|
+
{
|
|
189
|
+
oldNodePath: nodePath,
|
|
190
|
+
newNodePath: next.nodePath,
|
|
191
|
+
sourceLocations: { before: location, after: next.location },
|
|
192
|
+
},
|
|
193
|
+
];
|
|
186
194
|
}),
|
|
187
195
|
});
|
|
188
196
|
}
|
|
@@ -231,7 +239,7 @@ const addKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, remo
|
|
|
231
239
|
});
|
|
232
240
|
}
|
|
233
241
|
const nodePathMutation = filesWithRemappings.length
|
|
234
|
-
? (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)(filesWithRemappings, null)
|
|
242
|
+
? (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)(filesWithRemappings, null, true)
|
|
235
243
|
: null;
|
|
236
244
|
for (const log of sequenceLogs) {
|
|
237
245
|
(0, log_update_1.logUpdate)({
|