@remotion/studio-server 4.0.533 → 4.0.535

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 (68) hide show
  1. package/dist/detect-outdated-remotion-skills.d.ts +4 -0
  2. package/dist/detect-outdated-remotion-skills.js +3 -2
  3. package/dist/file-watcher.js +2 -0
  4. package/dist/helpers/app-discovery.d.ts +9 -0
  5. package/dist/helpers/app-discovery.js +61 -0
  6. package/dist/helpers/coding-agent-registry.d.ts +1 -0
  7. package/dist/helpers/coding-agent-registry.js +22 -1
  8. package/dist/helpers/editor-registry.d.ts +1 -0
  9. package/dist/helpers/editor-registry.js +24 -1
  10. package/dist/helpers/open-in-app.d.ts +13 -0
  11. package/dist/helpers/open-in-app.js +72 -0
  12. package/dist/helpers/open-in-editor.d.ts +1 -1
  13. package/dist/helpers/open-in-editor.js +67 -84
  14. package/dist/helpers/recently-used-apps.d.ts +9 -0
  15. package/dist/helpers/recently-used-apps.js +63 -0
  16. package/dist/helpers/running-processes.d.ts +12 -0
  17. package/dist/helpers/running-processes.js +88 -0
  18. package/dist/helpers/video-config-numeric-expression.js +29 -20
  19. package/dist/helpers/video-config-values.d.ts +6 -3
  20. package/dist/helpers/video-config-values.js +42 -26
  21. package/dist/preview-server/api-routes.js +8 -5
  22. package/dist/preview-server/live-events.d.ts +1 -0
  23. package/dist/preview-server/live-events.js +12 -1
  24. package/dist/preview-server/routes/add-sequence-keyframe.js +0 -1
  25. package/dist/preview-server/routes/app-info.d.ts +3 -0
  26. package/dist/preview-server/routes/app-info.js +16 -0
  27. package/dist/preview-server/routes/can-update-effect-props.d.ts +4 -6
  28. package/dist/preview-server/routes/can-update-effect-props.js +5 -28
  29. package/dist/preview-server/routes/can-update-sequence-props.d.ts +6 -8
  30. package/dist/preview-server/routes/can-update-sequence-props.js +11 -12
  31. package/dist/preview-server/routes/default-coding-agent.d.ts +1 -2
  32. package/dist/preview-server/routes/default-coding-agent.js +11 -19
  33. package/dist/preview-server/routes/default-editor.js +9 -29
  34. package/dist/preview-server/routes/delete-keyframes.d.ts +2 -2
  35. package/dist/preview-server/routes/delete-keyframes.js +0 -1
  36. package/dist/preview-server/routes/element-install-plan.js +5 -0
  37. package/dist/preview-server/routes/insert-basic-captions.js +1 -0
  38. package/dist/preview-server/routes/insert-element.js +63 -20
  39. package/dist/preview-server/routes/install-remotion-skill.d.ts +2 -1
  40. package/dist/preview-server/routes/install-remotion-skill.js +87 -56
  41. package/dist/preview-server/routes/open-in-editor.d.ts +1 -1
  42. package/dist/preview-server/routes/open-in-editor.js +2 -56
  43. package/dist/preview-server/routes/redo.js +2 -1
  44. package/dist/preview-server/routes/remotion-skills-info.d.ts +2 -1
  45. package/dist/preview-server/routes/remotion-skills-info.js +57 -3
  46. package/dist/preview-server/routes/save-sequence-props.js +0 -1
  47. package/dist/preview-server/routes/shared-memory-capture-support.d.ts +3 -0
  48. package/dist/preview-server/routes/shared-memory-capture-support.js +13 -0
  49. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -1
  50. package/dist/preview-server/routes/subscribe-to-sequence-props.js +1 -2
  51. package/dist/preview-server/routes/undo.js +2 -1
  52. package/dist/preview-server/routes/unsubscribe-from-sequence-props.js +0 -1
  53. package/dist/preview-server/routes/update-config.js +12 -5
  54. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +0 -1
  55. package/dist/preview-server/routes/wrap-node.js +13 -4
  56. package/dist/preview-server/sequence-props-watchers.d.ts +3 -5
  57. package/dist/preview-server/sequence-props-watchers.js +9 -17
  58. package/dist/preview-server/studio-protocol/handle-element-library.js +14 -0
  59. package/dist/preview-server/studio-protocol/handle-install.js +2 -1
  60. package/dist/preview-server/undo-stack.js +1 -0
  61. package/dist/preview-server/update-available.js +17 -0
  62. package/dist/preview-server/watch-ignore-next-change.d.ts +1 -0
  63. package/dist/preview-server/watch-ignore-next-change.js +15 -2
  64. package/dist/routes.js +3 -1
  65. package/dist/start-studio.js +13 -6
  66. package/dist/studio-shortcuts.d.ts +13 -0
  67. package/dist/studio-shortcuts.js +257 -0
  68. package/package.json +8 -8
@@ -11,13 +11,13 @@ const renderer_1 = require("@remotion/renderer");
11
11
  const file_watcher_1 = require("./file-watcher");
12
12
  const get_network_address_1 = require("./get-network-address");
13
13
  const maybe_open_browser_1 = require("./maybe-open-browser");
14
- const open_browser_shortcut_1 = require("./open-browser-shortcut");
15
14
  const close_and_restart_1 = require("./preview-server/close-and-restart");
16
15
  const get_absolute_public_dir_1 = require("./preview-server/get-absolute-public-dir");
17
16
  const live_events_1 = require("./preview-server/live-events");
18
17
  const public_folder_1 = require("./preview-server/public-folder");
19
18
  const start_server_1 = require("./preview-server/start-server");
20
19
  const server_ready_1 = require("./server-ready");
20
+ const studio_shortcuts_1 = require("./studio-shortcuts");
21
21
  const watch_root_file_1 = require("./watch-root-file");
22
22
  const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, remotionRoot, relativePublicDir, bundlerOverride, rspackOverride, webpackOverride, poll, getRenderDefaults, getRenderQueue, getNumberOfAudioTags, queueMethods, previewEntry, gitSource, binariesDirectory, forceIPv4, getAudioLatencyHint, getExperimentalKeepAudioContextAlive, getPreviewSampleRate, enableCrossSiteIsolation, forceNew, rspack, getStudioRuntimeConfig, getDefaultCodingAgent, getDefaultEditor, configFile, }) => {
23
23
  try {
@@ -39,11 +39,15 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
39
39
  relativePublicDir,
40
40
  remotionRoot,
41
41
  });
42
- const hash = node_crypto_1.default.randomBytes(6).toString('hex');
43
42
  const outputHashPrefix = '/outputs-';
44
- const outputHash = `${outputHashPrefix}${hash}`;
43
+ const outputHash = `${outputHashPrefix}${node_crypto_1.default.randomBytes(6).toString('hex')}`;
44
+ // Asset URLs must survive restarts, but remain scoped to this project and folder.
45
45
  const staticHashPrefix = '/static-';
46
- const staticHash = `${staticHashPrefix}${hash}`;
46
+ const staticHash = `${staticHashPrefix}${node_crypto_1.default
47
+ .createHash('sha256')
48
+ .update(JSON.stringify([remotionRoot, publicDir]))
49
+ .digest('hex')
50
+ .slice(0, 12)}`;
47
51
  (0, public_folder_1.initPublicFolderWatch)({
48
52
  publicDir,
49
53
  remotionRoot,
@@ -124,11 +128,14 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
124
128
  (0, server_ready_1.printServerReadyComment)('Server ready', logLevel);
125
129
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, 'Building...');
126
130
  const studioUrl = `http://localhost:${port}`;
127
- const openBrowserShortcut = (0, open_browser_shortcut_1.registerOpenBrowserShortcut)({
131
+ const studioShortcuts = (0, studio_shortcuts_1.registerStudioShortcuts)({
128
132
  browserArgs,
129
133
  browserFlag,
130
134
  url: studioUrl,
131
135
  logLevel,
136
+ remotionRoot,
137
+ getDefaultEditor,
138
+ getDefaultCodingAgent,
132
139
  });
133
140
  let action;
134
141
  try {
@@ -142,7 +149,7 @@ const startStudio = async ({ browserArgs, browserFlag, shouldOpenBrowser, fullEn
142
149
  action = await (0, close_and_restart_1.noOpUntilRestart)();
143
150
  }
144
151
  finally {
145
- openBrowserShortcut.cleanup();
152
+ studioShortcuts.cleanup();
146
153
  }
147
154
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, action === 'shutdown'
148
155
  ? 'Shutting down Studio...'
@@ -0,0 +1,13 @@
1
+ import type { DefaultEditor } from '@remotion/renderer';
2
+ export declare const registerStudioShortcuts: ({ browserArgs, browserFlag, url, logLevel, remotionRoot, getDefaultEditor, getDefaultCodingAgent, }: {
3
+ browserArgs: string;
4
+ browserFlag: string;
5
+ url: string;
6
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
7
+ remotionRoot: string;
8
+ getDefaultEditor: () => DefaultEditor | null;
9
+ getDefaultCodingAgent: () => "claude-code" | "codex" | "copilot" | "cursor" | null;
10
+ }) => {
11
+ registered: boolean;
12
+ cleanup: () => void;
13
+ };
@@ -0,0 +1,257 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerStudioShortcuts = void 0;
37
+ const readline = __importStar(require("node:readline"));
38
+ const renderer_1 = require("@remotion/renderer");
39
+ const studio_shared_1 = require("@remotion/studio-shared");
40
+ const better_opn_1 = require("./better-opn");
41
+ const app_discovery_1 = require("./helpers/app-discovery");
42
+ const open_in_app_1 = require("./helpers/open-in-app");
43
+ const recently_used_apps_1 = require("./helpers/recently-used-apps");
44
+ const maybe_open_browser_1 = require("./maybe-open-browser");
45
+ const live_events_1 = require("./preview-server/live-events");
46
+ const registerStudioShortcuts = ({ browserArgs, browserFlag, url, logLevel, remotionRoot, getDefaultEditor, getDefaultCodingAgent, }) => {
47
+ if (!process.stdin.isTTY) {
48
+ return { registered: false, cleanup: () => undefined };
49
+ }
50
+ if (typeof process.stdin.setRawMode !== 'function') {
51
+ return { registered: false, cleanup: () => undefined };
52
+ }
53
+ const wasRaw = process.stdin.isRaw;
54
+ const shouldPauseAfterCleanup = process.stdin.isPaused();
55
+ let cleanedUp = false;
56
+ let isOpeningBrowser = false;
57
+ let editor = null;
58
+ let codingAgent = null;
59
+ const openingApps = new Set();
60
+ let refreshRevision = 0;
61
+ let lastPrintedAssignment = null;
62
+ const refreshShortcuts = async () => {
63
+ var _a;
64
+ const revision = ++refreshRevision;
65
+ const configuredEditor = getDefaultEditor();
66
+ const configuredCodingAgent = getDefaultCodingAgent();
67
+ const [discovery, editorInfo, recentEditors, recentCodingAgents] = await Promise.all([
68
+ (0, app_discovery_1.getAppDiscovery)(),
69
+ (0, app_discovery_1.getEditorInfo)(configuredEditor),
70
+ (0, recently_used_apps_1.getRecentlyUsedApps)({
71
+ remotionRoot,
72
+ type: 'editor',
73
+ recentlyUsedIds: null,
74
+ }),
75
+ (0, recently_used_apps_1.getRecentlyUsedApps)({
76
+ remotionRoot,
77
+ type: 'coding-agent',
78
+ recentlyUsedIds: null,
79
+ }),
80
+ ]);
81
+ if (cleanedUp || revision !== refreshRevision) {
82
+ return;
83
+ }
84
+ editor = (0, studio_shared_1.getPreferredApp)({
85
+ installedApps: editorInfo.installedEditors,
86
+ configuredId: editorInfo.defaultEditor,
87
+ runningIds: (_a = editorInfo.runningEditors) !== null && _a !== void 0 ? _a : [],
88
+ recentlyUsedIds: recentEditors,
89
+ fallbackIds: studio_shared_1.preferredFallbackEditorIds,
90
+ });
91
+ codingAgent = (0, studio_shared_1.getPreferredApp)({
92
+ installedApps: discovery.installedCodingAgents,
93
+ configuredId: configuredCodingAgent,
94
+ runningIds: discovery.runningCodingAgents,
95
+ recentlyUsedIds: recentCodingAgents,
96
+ fallbackIds: discovery.installedCodingAgents.map(({ id }) => id),
97
+ });
98
+ printShortcuts();
99
+ };
100
+ const printShortcuts = () => {
101
+ var _a, _b;
102
+ if (cleanedUp) {
103
+ return;
104
+ }
105
+ const shortcuts = [
106
+ '[s] Open Studio',
107
+ ...(codingAgent ? [`[a] Open agent (${codingAgent.name})`] : []),
108
+ ...(editor
109
+ ? [
110
+ `[e] Open editor (${editor.name === 'Code' ? 'VS Code' : editor.name})`,
111
+ ]
112
+ : []),
113
+ ];
114
+ const assignment = JSON.stringify([
115
+ (_a = editor === null || editor === void 0 ? void 0 : editor.id) !== null && _a !== void 0 ? _a : null,
116
+ (_b = codingAgent === null || codingAgent === void 0 ? void 0 : codingAgent.id) !== null && _b !== void 0 ? _b : null,
117
+ shortcuts,
118
+ (editor === null || editor === void 0 ? void 0 : editor.id) === 'custom' ? getDefaultEditor() : null,
119
+ ]);
120
+ if (assignment === lastPrintedAssignment) {
121
+ return;
122
+ }
123
+ lastPrintedAssignment = assignment;
124
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(shortcuts.join(' ')));
125
+ };
126
+ const onPreferencesChange = () => {
127
+ if (cleanedUp) {
128
+ return;
129
+ }
130
+ refreshShortcuts().catch((err) => {
131
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, 'Could not refresh Studio shortcuts:', err);
132
+ printShortcuts();
133
+ });
134
+ };
135
+ const unsubscribeHistory = (0, recently_used_apps_1.subscribeToRecentlyUsedApps)({
136
+ remotionRoot,
137
+ onChange: onPreferencesChange,
138
+ });
139
+ const unsubscribeConfig = (0, live_events_1.subscribeToConfigChanges)(onPreferencesChange);
140
+ const openApp = async (key) => {
141
+ if (openingApps.has(key) || cleanedUp) {
142
+ return;
143
+ }
144
+ openingApps.add(key);
145
+ try {
146
+ const response = key === 'a' && codingAgent
147
+ ? await (0, open_in_app_1.openInCodingAgent)({
148
+ input: { codingAgentId: codingAgent.id, prompt: null },
149
+ remotionRoot,
150
+ logLevel,
151
+ })
152
+ : key === 'e' && editor
153
+ ? await (0, open_in_app_1.openInEditor)({
154
+ input: {
155
+ editorId: editor.id,
156
+ stack: {
157
+ originalFileName: remotionRoot,
158
+ originalLineNumber: 1,
159
+ originalColumnNumber: 1,
160
+ originalFunctionName: null,
161
+ originalScriptCode: null,
162
+ },
163
+ },
164
+ remotionRoot,
165
+ logLevel,
166
+ getDefaultEditor,
167
+ })
168
+ : null;
169
+ if (response && !response.success) {
170
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, `Could not open ${key === 'a' ? codingAgent === null || codingAgent === void 0 ? void 0 : codingAgent.name : editor === null || editor === void 0 ? void 0 : editor.name}`);
171
+ }
172
+ }
173
+ catch (err) {
174
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, key === 'a' ? 'Could not open coding agent:' : 'Could not open editor:', err);
175
+ }
176
+ finally {
177
+ openingApps.delete(key);
178
+ }
179
+ };
180
+ const cleanup = () => {
181
+ if (cleanedUp) {
182
+ return;
183
+ }
184
+ cleanedUp = true;
185
+ unsubscribeHistory();
186
+ unsubscribeConfig();
187
+ process.stdin.removeListener('keypress', onKeypress);
188
+ process.removeListener('SIGINT', cleanup);
189
+ process.removeListener('exit', cleanup);
190
+ if (!wasRaw && process.stdin.isTTY) {
191
+ process.stdin.setRawMode(false);
192
+ }
193
+ if (shouldPauseAfterCleanup) {
194
+ process.stdin.pause();
195
+ }
196
+ };
197
+ const openStudio = async () => {
198
+ if (isOpeningBrowser) {
199
+ return;
200
+ }
201
+ isOpeningBrowser = true;
202
+ (0, live_events_1.clearPrintPortMessageTimeout)();
203
+ try {
204
+ const didFocus = await (0, better_opn_1.focusBrowserTabByOrigin)({
205
+ url,
206
+ browserArgs,
207
+ browserFlag,
208
+ });
209
+ if (didFocus) {
210
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Opened ${url} in browser`));
211
+ return;
212
+ }
213
+ const result = await (0, maybe_open_browser_1.maybeOpenBrowser)({
214
+ browserArgs,
215
+ browserFlag,
216
+ shouldOpenBrowser: true,
217
+ url,
218
+ logLevel,
219
+ });
220
+ if (result.didOpenBrowser) {
221
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Opened ${url} in browser`));
222
+ }
223
+ }
224
+ catch (err) {
225
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, 'Could not open browser:', err);
226
+ }
227
+ finally {
228
+ isOpeningBrowser = false;
229
+ }
230
+ };
231
+ function onKeypress(_str, key) {
232
+ if ((key === null || key === void 0 ? void 0 : key.ctrl) && key.name === 'c') {
233
+ cleanup();
234
+ process.kill(process.pid, 'SIGINT');
235
+ return;
236
+ }
237
+ if ((key === null || key === void 0 ? void 0 : key.meta) || (key === null || key === void 0 ? void 0 : key.ctrl)) {
238
+ return;
239
+ }
240
+ if ((key === null || key === void 0 ? void 0 : key.name) === 's') {
241
+ openStudio().catch(() => undefined);
242
+ }
243
+ else if ((key === null || key === void 0 ? void 0 : key.name) === 'a' || (key === null || key === void 0 ? void 0 : key.name) === 'e') {
244
+ openApp(key.name).catch(() => undefined);
245
+ }
246
+ }
247
+ readline.emitKeypressEvents(process.stdin);
248
+ process.stdin.setRawMode(true);
249
+ process.stdin.resume();
250
+ process.stdin.on('keypress', onKeypress);
251
+ process.once('SIGINT', cleanup);
252
+ process.once('exit', cleanup);
253
+ // Discovery may finish after other startup logs; never await it here.
254
+ onPreferencesChange();
255
+ return { registered: true, cleanup };
256
+ };
257
+ exports.registerStudioShortcuts = registerStudioShortcuts;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
4
4
  },
5
5
  "name": "@remotion/studio-server",
6
- "version": "4.0.533",
6
+ "version": "4.0.535",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -23,7 +23,7 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@remotion/studio-protocol": "4.0.533",
26
+ "@remotion/studio-protocol": "4.0.535",
27
27
  "@babel/types": "7.24.0",
28
28
  "@babel/parser": "7.24.1",
29
29
  "@svgr/core": "8.1.0",
@@ -31,12 +31,12 @@
31
31
  "kiwi-schema": "0.5.0",
32
32
  "semver": "7.5.3",
33
33
  "zod": "4.5.4",
34
- "remotion": "4.0.533",
34
+ "remotion": "4.0.535",
35
35
  "recast": "0.23.21",
36
- "@remotion/bundler": "4.0.533",
37
- "@remotion/renderer": "4.0.533",
38
- "@remotion/codemods": "4.0.533",
39
- "@remotion/studio-shared": "4.0.533",
36
+ "@remotion/bundler": "4.0.535",
37
+ "@remotion/renderer": "4.0.535",
38
+ "@remotion/codemods": "4.0.535",
39
+ "@remotion/studio-shared": "4.0.535",
40
40
  "memfs": "3.4.3",
41
41
  "open": "8.4.2"
42
42
  },
@@ -44,7 +44,7 @@
44
44
  "ast-types": "0.16.1",
45
45
  "react": "19.2.3",
46
46
  "@types/semver": "7.5.3",
47
- "@remotion/eslint-config-internal": "4.0.533",
47
+ "@remotion/eslint-config-internal": "4.0.535",
48
48
  "eslint": "9.19.0",
49
49
  "prettier": "3.8.1",
50
50
  "@types/node": "20.12.14",